Changes in / [24d6572:34b4268]


Ignore:
Files:
156 added
744 deleted
239 edited

Legend:

Unmodified
Added
Removed
  • Jenkins/FullBuild

    r24d6572 r34b4268  
    2020                                        gcc_08_x86_new: { trigger_build( 'gcc-10',  'x86', false ) },
    2121                                        gcc_07_x86_new: { trigger_build( 'gcc-9',   'x86', false ) },
    22                                         gcc_11_x64_new: { trigger_build( 'gcc-11',  'x64', false ) },
    2322                                        gcc_10_x64_new: { trigger_build( 'gcc-10',  'x64', false ) },
    2423                                        gcc_09_x64_new: { trigger_build( 'gcc-9',   'x64', false ) },
    2524                                        gcc_08_x64_new: { trigger_build( 'gcc-8',   'x64', false ) },
    2625                                        gcc_07_x64_new: { trigger_build( 'gcc-7',   'x64', false ) },
    27                                         // gcc_06_x64_new: { trigger_build( 'gcc-6',   'x64', false ) },
     26                                        gcc_06_x64_new: { trigger_build( 'gcc-6',   'x64', false ) },
    2827                                        clang_x64_new:  { trigger_build( 'clang',   'x64', true  ) },
    2928                                )
     
    4241        }
    4342
    44         // If an exception is caught we need to change the status and remember to
    45         // attach the build log to the email
     43        //If an exception is caught we need to change the status and remember to
     44        //attach the build log to the email
    4645        catch (Exception caughtError) {
    4746                echo('error caught')
     
    7473        // Run the build
    7574        // Don't propagate, it doesn't play nice with our email setup
    76         def result = build job: 'Cforall/master',                       \
     75        def result = build job: 'Cforall/master',               \
    7776                parameters: [                                           \
    7877                        [$class: 'StringParameterValue',                \
     
    8483                        [$class: 'BooleanParameterValue',               \
    8584                          name: 'NewAST',                               \
    86                           value: true],                                 \
     85                          value: true],                                         \
    8786                        [$class: 'BooleanParameterValue',               \
    8887                          name: 'RunAllTests',                          \
    89                           value: true],                                 \
     88                          value: true],                                         \
    9089                        [$class: 'BooleanParameterValue',               \
    9190                          name: 'RunBenchmark',                         \
    92                           value: true],                                 \
     91                          value: true],                                         \
    9392                        [$class: 'BooleanParameterValue',               \
    94                           name: 'BuildDocumentation',                   \
     93                          name: 'BuildDocumentation',           \
    9594                          value: doc],                                  \
    9695                        [$class: 'BooleanParameterValue',               \
    9796                          name: 'Publish',                              \
    98                           value: true],                                 \
     97                          value: true],                                         \
    9998                        [$class: 'BooleanParameterValue',               \
    10099                          name: 'Silent',                               \
    101                           value: true],                                 \
    102                 ],                                                      \
     100                          value: true],                                         \
     101                ],                                                              \
    103102                propagate: false
    104103
     
    112111
    113112def trigger_dist(String commitId, String buildNum) {
    114         def result = build job: 'Cforall_Distribute_Ref',               \
     113        def result = build job: 'Cforall_Distribute_Ref',       \
    115114                parameters: [                                           \
    116115                        string(name: 'GitRef', value: commitId),        \
    117                         string(name: 'Build' , value: buildNum)         \
    118                 ],                                                      \
     116                        string(name: 'Build' , value: buildNum) \
     117                ],                                                              \
    119118                propagate: false
    120119
  • Jenkins/Promote

    r24d6572 r34b4268  
    3636                dir (BuildDir) {
    3737                    sh 'rm -rf *'
    38                         sshagent (credentials: ['git_key_mar27']) {
     38                        sshagent (credentials: ['github_key_jun1']) {
    3939                                sh "git clone --bare ${RemoteRepo} repo"
    4040                        }
     
    6969                        sh "git status"
    7070                        sh "git diff-index --quiet HEAD || git commit -m 'Push from build machine: ${name}'"
    71                         sshagent (credentials: ['git_key_mar27']) {
     71                        sshagent (credentials: ['github_key_jun1']) {
    7272                                sh "git push origin master"
    7373                        }
  • Jenkinsfile

    r24d6572 r34b4268  
    155155                        dir (BuildDir) {
    156156                                //Run the tests from the tests directory
    157                                 sh """make ${jopt} --no-print-directory -C tests timeout=600 global-timeout=14400 tests debug=yes archive-errors=${BuildDir}/tests/crashes/full-debug"""
     157                                sh """make ${jopt} --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
    158158                        }
    159159                }
     
    162162                        dir (BuildDir) {
    163163                                //Run the tests from the tests directory
    164                                 sh """make ${jopt} --no-print-directory -C tests timeout=600 global-timeout=14400 tests debug=no archive-errors=${BuildDir}/tests/crashes/full-nodebug"""
     164                                sh """make ${jopt} --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
    165165                        }
    166166                }
     
    305305                                this.Compiler = new CC_Desc('gcc-7', 'g++-7', 'gcc-7', '-flto=auto')
    306306                        break
    307                         // case 'gcc-6':
    308                         //      this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto')
    309                         // break
    310                         // case 'gcc-5':
    311                         //      this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto')
    312                         // break
    313                         // case 'gcc-4.9':
    314                         //      this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto')
    315                         // break
     307                        case 'gcc-6':
     308                                this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto')
     309                        break
     310                        case 'gcc-5':
     311                                this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto')
     312                        break
     313                        case 'gcc-4.9':
     314                                this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto')
     315                        break
    316316                        case 'clang':
    317317                                this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-10', '-flto=thin -flto-jobs=0')
     
    359359def prepare_build() {
    360360        // prepare the properties
    361         properties ([                                                                           \
    362                 buildDiscarder(logRotator(                                                      \
    363                         artifactDaysToKeepStr: '',                                              \
    364                         artifactNumToKeepStr: '',                                               \
    365                         daysToKeepStr: '730',                                                   \
    366                         numToKeepStr: '1000'                                                    \
    367                 )),                                                                             \
    368                 [$class: 'ParametersDefinitionProperty',                                        \
    369                         parameterDefinitions: [                                                 \
    370                                 [$class: 'ChoiceParameterDefinition',                           \
    371                                         description: 'Which compiler to use',                   \
    372                                         name: 'Compiler',                                       \
    373                                         choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\nclang',  \
    374                                         defaultValue: 'gcc-9',                                  \
    375                                 ],                                                              \
    376                                 [$class: 'ChoiceParameterDefinition',                           \
    377                                         description: 'The target architecture',                 \
    378                                         name: 'Architecture',                                   \
    379                                         choices: 'x64\nx86',                                    \
    380                                         defaultValue: 'x64',                                    \
    381                                 ],                                                              \
    382                                 [$class: 'BooleanParameterDefinition',                          \
     361        properties ([                                                                                                   \
     362                buildDiscarder(logRotator(                                                                              \
     363                        artifactDaysToKeepStr: '',                                                                      \
     364                        artifactNumToKeepStr: '',                                                                       \
     365                        daysToKeepStr: '730',                                                                           \
     366                        numToKeepStr: '1000'                                                                            \
     367                )),                                                                                                             \
     368                [$class: 'ParametersDefinitionProperty',                                                                \
     369                        parameterDefinitions: [                                                                         \
     370                                [$class: 'ChoiceParameterDefinition',                                           \
     371                                        description: 'Which compiler to use',                                   \
     372                                        name: 'Compiler',                                                                       \
     373                                        choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang',   \
     374                                        defaultValue: 'gcc-8',                                                          \
     375                                ],                                                                                              \
     376                                [$class: 'ChoiceParameterDefinition',                                           \
     377                                        description: 'The target architecture',                                 \
     378                                        name: 'Architecture',                                                           \
     379                                        choices: 'x64\nx86',                                                            \
     380                                        defaultValue: 'x64',                                                            \
     381                                ],                                                                                              \
     382                                [$class: 'BooleanParameterDefinition',                                                  \
    383383                                        description: 'If false, the test suite is only ran in debug',   \
    384                                         name: 'RunAllTests',                                    \
    385                                         defaultValue: false,                                    \
    386                                 ],                                                              \
    387                                 [$class: 'BooleanParameterDefinition',                          \
    388                                         description: 'If true, jenkins also runs benchmarks',   \
    389                                         name: 'RunBenchmark',                                   \
    390                                         defaultValue: false,                                    \
    391                                 ],                                                              \
    392                                 [$class: 'BooleanParameterDefinition',                          \
    393                                         description: 'If true, jenkins also builds documentation', \
    394                                         name: 'BuildDocumentation',                             \
    395                                         defaultValue: true,                                     \
    396                                 ],                                                              \
    397                                 [$class: 'BooleanParameterDefinition',                          \
    398                                         description: 'If true, jenkins also publishes results', \
    399                                         name: 'Publish',                                        \
    400                                         defaultValue: false,                                    \
    401                                 ],                                                              \
    402                                 [$class: 'BooleanParameterDefinition',                          \
    403                                         description: 'If true, jenkins will not send emails',   \
    404                                         name: 'Silent',                                         \
    405                                         defaultValue: false,                                    \
    406                                 ],                                                              \
     384                                        name: 'RunAllTests',                                                            \
     385                                        defaultValue: false,                                                            \
     386                                ],                                                                                              \
     387                                [$class: 'BooleanParameterDefinition',                                                  \
     388                                        description: 'If true, jenkins also runs benchmarks',           \
     389                                        name: 'RunBenchmark',                                                           \
     390                                        defaultValue: false,                                                            \
     391                                ],                                                                                              \
     392                                [$class: 'BooleanParameterDefinition',                                                  \
     393                                        description: 'If true, jenkins also builds documentation',              \
     394                                        name: 'BuildDocumentation',                                                     \
     395                                        defaultValue: true,                                                             \
     396                                ],                                                                                              \
     397                                [$class: 'BooleanParameterDefinition',                                                  \
     398                                        description: 'If true, jenkins also publishes results',                 \
     399                                        name: 'Publish',                                                                        \
     400                                        defaultValue: false,                                                            \
     401                                ],                                                                                              \
     402                                [$class: 'BooleanParameterDefinition',                                                  \
     403                                        description: 'If true, jenkins will not send emails',           \
     404                                        name: 'Silent',                                                                         \
     405                                        defaultValue: false,                                                            \
     406                                ],                                                                                              \
    407407                        ],
    408408                ]])
    409                                         // choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang',
    410                                         // defaultValue: 'gcc-8',
    411409
    412410        // It's unfortunate but it looks like we need to checkout the entire repo just to get
  • Makefile.am

    r24d6572 r34b4268  
    1111## Created On       : Sun May 31 22:14:18 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Wed May 17 11:02:34 2023
    14 ## Update Count     : 56
     13## Last Modified On : Sat Feb  2 16:54:42 2019
     14## Update Count     : 21
    1515###############################################################################
    1616
     
    2424DIST_SUBDIRS = driver src . libcfa tests
    2525
    26 @LIBCFA_TARGET_MAKEFILES@ : Makefile ${srcdir}/libcfa/configure
    27         @${eval config_file = ${dir ${@}}config.data}
    28         @ls ${config_file} || (echo "Missing config.data, re-run configure script again" && false)
    29         @${eval config_data = ${shell cat ${config_file}}}
    30         @echo "Configuring libcfa (${abs_top_srcdir}/libcfa/configure) with '${config_data}' from ${shell pwd} / ${dir ${@}}"
    31         @cd ${dir ${@}} && ${abs_top_srcdir}/libcfa/configure ${config_data}
     26@LIBCFA_TARGET_MAKEFILES@ : Makefile $(srcdir)/libcfa/configure
     27        @$(eval config_file = $(dir $@)config.data)
     28        @ls $(config_file) || (echo "Missing config.data, re-run configure script again" && false)
     29        @$(eval config_data = $(shell cat $(config_file)))
     30        @echo "Configuring libcfa ($(abs_top_srcdir)/libcfa/configure) with '$(config_data)' from $(shell pwd) / $(dir $@)"
     31        @cd $(dir $@) && $(abs_top_srcdir)/libcfa/configure $(config_data)
    3232
    3333noinst_DATA = @LIBCFA_TARGET_MAKEFILES@
     
    3737EXTRA_DIST = LICENSE doc/man/cfa.1 libcfa/configure libcfa/Makefile.dist.am libcfa/Makefile.dist.in tools/build/distcc_hash tools/build/push2dist.sh
    3838
    39 debug ?= yes
    40 installed ?= no
    41 ARCH = ${if ${arch},"arch=${arch}"}
    42 arch_support = "x86/x64/arm"
     39debug=yes
     40check:
     41        $(MAKE) -C tests all-tests installed=no debug=${debug}
    4342
    44 # target "all" created by automake
     43installcheck:
     44        $(MAKE) -C tests all-tests installed=yes debug=${debug}
    4545
    46 check :
    47         ${MAKE} -C tests tests installed=${installed} debug=${debug} ${ARCH}
     46configure-libcfa: @LIBCFA_TARGET_MAKEFILES@
     47        @true
    4848
    49 tests : check # synonym
    50 
    51 installcheck :
    52         ${MAKE} -C tests tests installed=yes debug=${debug} ${ARCH}
    53 
    54 installtest : installcheck # synonym
    55 
    56 status : @LIBCFA_TARGET_MAKEFILES@
     49status: @LIBCFA_TARGET_MAKEFILES@
    5750        @echo -ne "translator\n\t"
    5851        @./config.status --config | sed "s/ /\n\t/g; s/\t'/\t/g; s/'\n/\n/g; s/^'//g; s/'$$//g"
    5952        @find libcfa -name config.status -printf "\n%h\n\t" -exec {} --config \; | sed "s/ /\n\t/g; s/\t'/\t/g; s/'\n/\n/g; s/^'//g; s/'$$//g"
    6053
    61 help :
    62         @echo "user targets:"
    63         @echo "    Compile compiler/runtime."
    64         @echo "    $$ make (null) / all"
    65         @echo ""
    66         @echo "    Compile compiler/runtime and run test suite."
    67         @echo "    $$ make check / tests [debug=yes/no] [installed=yes/no] [arch=${arch_support}]"
    68         @echo ""
    69         @echo "    Compile compiler/runtime, install, and run test suite on installed system."
    70         @echo "    $$ make installcheck / installtests [debug=yes/no] installed=yes [arch=${arch_support}]"
    71         @echo ""
    72         @echo "    Print configuration parameters and system build information."
    73         @echo "    $$ make status"
     54@LIBCFA_TARGET_DIRS@::
     55        $(MAKE) -C $@ $(MAKECMDGOALS)
    7456
    75 configure-libcfa : @LIBCFA_TARGET_MAKEFILES@
    76         @true
    77 
    78 @LIBCFA_TARGET_DIRS@ ::
    79         ${MAKE} -C ${@} ${MAKECMDGOALS}
    80 
    81 mostlyclean clean distclean maintainer-clean : @LIBCFA_TARGET_DIRS@
     57mostlyclean clean distclean maintainer-clean: @LIBCFA_TARGET_DIRS@
  • benchmark/Makefile.am

    r24d6572 r34b4268  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Fri May 26 12:13:48 2023
    14 ## Update Count     : 260
     13## Last Modified On : Tue Mar 10 11:41:18 2020
     14## Update Count     : 258
    1515###############################################################################
    1616
     
    374374## =========================================================================================================
    375375
    376 mutexStmt$(EXEEXT) :                    \
    377         mutexStmt-cpp1.run              \
    378         mutexStmt-cpp2.run              \
    379         mutexStmt-cpp4.run              \
    380         mutexStmt-cpp8.run              \
    381         mutexStmt-java.run              \
    382         mutexStmt-lock1.run             \
    383         mutexStmt-lock2.run             \
    384         mutexStmt-lock4.run             \
    385         mutexStmt-lock8.run             \
    386         mutexStmt-no-stmt-lock1.run     \
    387         mutexStmt-no-stmt-lock2.run     \
    388         mutexStmt-no-stmt-lock4.run     \
    389         mutexStmt-no-stmt-lock8.run     \
    390         mutexStmt-monitor1.run          \
    391         mutexStmt-monitor2.run          \
     376mutexStmt$(EXEEXT) :                \
     377        mutexStmt-cpp1.run                      \
     378        mutexStmt-cpp2.run                      \
     379        mutexStmt-cpp4.run                      \
     380        mutexStmt-cpp8.run                      \
     381        mutexStmt-java.run                      \
     382        mutexStmt-lock1.run                 \
     383        mutexStmt-lock2.run                 \
     384        mutexStmt-lock4.run                 \
     385        mutexStmt-lock8.run                 \
     386        mutexStmt-no-stmt-lock1.run \
     387        mutexStmt-no-stmt-lock2.run \
     388        mutexStmt-no-stmt-lock4.run \
     389        mutexStmt-no-stmt-lock8.run \
     390        mutexStmt-monitor1.run      \
     391        mutexStmt-monitor2.run      \
    392392        mutexStmt-monitor4.run
    393393
     
    567567        compile-array.make      \
    568568        compile-attributes.make \
    569         compile-empty.make      \
     569        compile-empty.make      \
    570570        compile-expression.make \
    571571        compile-io.make         \
     
    592592
    593593compile-monitor$(EXEEXT):
    594         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrency/monitor.cfa
     594        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/monitor.cfa
    595595
    596596compile-operators$(EXEEXT):
     
    598598
    599599compile-thread$(EXEEXT):
    600         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrency/thread.cfa
     600        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/thread.cfa
    601601
    602602compile-typeof$(EXEEXT):
  • configure.ac

    r24d6572 r34b4268  
    4747
    4848#==============================================================================
    49 # HACK to be able to use conditionals inside makefiles
     49# HACK to be able to use conditionnals inside makefiles
    5050DOifskipcompile='ifeq ($(skipcompile),yes)
    5151else'
     
    226226AC_PROG_YACC
    227227if test "${YACC}" = "yacc" ; then echo "Error: bison required." ; exit 1 ; fi
    228 AC_PROG_LEX(yywrap)
     228AC_PROG_LEX
    229229if test "${LEX}" = "lex" ; then echo "Error: flex required." ; exit 1 ; fi
    230 LT_INIT
     230AC_PROG_LIBTOOL
    231231AC_PROG_INSTALL
    232232
     
    284284                tools/Makefile
    285285                tools/prettyprinter/Makefile
    286                 benchmark/Cargo.toml
    287286        ])
     287
     288        AC_OUTPUT(benchmark/Cargo.toml)
    288289])
    289290
    290291AC_CONFIG_LINKS([tests/test.py:tests/test.py])
    291 AC_CONFIG_FILES([tests/config.py])
    292 
    293 AC_OUTPUT
     292
     293AC_OUTPUT(tests/config.py)
    294294
    295295# Final text
  • doc/LaTeXmacros/common.sty

    r24d6572 r34b4268  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Apr  4 12:03:19 2023
    14 %% Update Count     : 585
     13%% Last Modified On : Sat Apr  2 17:35:23 2022
     14%% Update Count     : 570
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\setlist[itemize,1]{label=\textbullet}% local
    3131%\renewcommand{\labelitemi}{{\raisebox{0.25ex}{\footnotesize$\bullet$}}}
    32 \setlist[enumerate]{topsep=0.5ex,parsep=0.25ex,itemsep=0.25ex,listparindent=\parindent}% global
     32\setlist[enumerate]{listparindent=\parindent}% global
    3333\setlist[enumerate,2]{leftmargin=\parindent,labelsep=*,align=parleft,label=\alph*.}% local
    3434\setlist[description]{topsep=0.5ex,itemsep=0pt,listparindent=\parindent,leftmargin=\parindent,labelsep=1.5ex}
     
    4949\newcommand{\CCseventeen}{\protect\CCIcon{17}\xspace}   % C++17 symbolic name
    5050\newcommand{\CCtwenty}{\protect\CCIcon{20}\xspace}              % C++20 symbolic name
    51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\relsize{2}$^\sharp$}\xspace} % C# symbolic name
     51\newcommand{\Csharp}{C\raisebox{-0.7ex}{\Large$^\sharp$}\xspace} % C# symbolic name
    5252
    5353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    5454
    55 \usepackage[scaled=0.85]{helvet}                                                % descent Helvetica font and scale to times size
    56 \usepackage[T1]{fontenc}
     55\usepackage{pslatex}                                                                    % reduce size of san serif font
    5756\usepackage{relsize}                                                                    % must be after change to small or selects old size
    5857\usepackage{rotating}
     
    196195\newcommand{\viz}{\VIZ\CheckPeriod}
    197196
    198 \newcommand{\VS}{\abbrevFont{vs}}
    199 \newcommand{\vs}{\VS\CheckPeriod}
    200 
    201197\newenvironment{cquote}{%
    202198        \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}%
     
    248244\renewcommand{\reftextpagerange}[2]{\unskip, pp.~\pageref{#1}--\pageref{#2}}
    249245\newcommand{\VRef}[2][Section]{\ifx#1\@empty\else{#1}\nobreakspace\fi\vref{#2}}
    250 \newcommand{\VRefrange}[3][Sections]{\ifx#1\@empty\else{#1}\nobreakspace\fi\vrefrange{#2}{#3}}
    251246\newcommand{\VPageref}[2][page]{\ifx#1\@empty\else{#1}\nobreakspace\fi\pageref{#2}}
    252 \newcommand{\VPagerefrange}[3][pages]{\ifx#1\@empty\else{#1}\nobreakspace\fi\pageref{#2}{#3}}
    253247
    254248\let\Oldthebibliography\thebibliography
     
    266260\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
    267261\newcommand{\LstStringStyle}[1]{{\lst@basicstyle{\lst@stringstyle{#1}}}}
    268 \newcommand{\LstNumberStyle}[1]{{\lst@basicstyle{\lst@numberstyle{#1}}}}
    269262
    270263\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
     
    287280columns=fullflexible,
    288281basicstyle=\linespread{0.9}\sf,                 % reduce line spacing and use sanserif font
    289 stringstyle=\small\tt,                                  % use typewriter font
     282stringstyle=\tt,                                                % use typewriter font
    290283tabsize=5,                                                              % N space tabbing
    291284xleftmargin=\parindentlnth,                             % indent code to paragraph indentation
  • doc/LaTeXmacros/common.tex

    r24d6572 r34b4268  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Apr  4 12:03:18 2023
    14 %% Update Count     : 567
     13%% Last Modified On : Tue Apr 26 16:02:48 2022
     14%% Update Count     : 558
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    4949\newcommand{\CCseventeen}{\protect\CCIcon{17}\xspace}   % C++17 symbolic name
    5050\newcommand{\CCtwenty}{\protect\CCIcon{20}\xspace}              % C++20 symbolic name
    51 \newcommand{\Csharp}{C\raisebox{-0.7ex}{\relsize{2}$^\sharp$}\xspace} % C# symbolic name
     51\newcommand{\Csharp}{C\raisebox{-0.7ex}{\Large$^\sharp$}\xspace} % C# symbolic name
    5252
    5353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    5454
    55 \usepackage[scaled=0.85]{helvet}                                                % descent Helvetica font and scale to times size
    56 \usepackage[T1]{fontenc}
     55\usepackage{pslatex}                                                                    % reduce size of san serif font
    5756\usepackage{relsize}                                                                    % must be after change to small or selects old size
    5857\usepackage{rotating}
     
    197196\newcommand{\viz}{\VIZ\CheckPeriod}
    198197
    199 \newcommand{\VS}{\abbrevFont{vs}}
    200 \newcommand{\vs}{\VS\CheckPeriod}
    201198\makeatother
    202199
     
    269266\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
    270267\newcommand{\LstStringStyle}[1]{{\lst@basicstyle{\lst@stringstyle{#1}}}}
    271 \newcommand{\LstNumberStyle}[1]{{\lst@basicstyle{\lst@numberstyle{#1}}}}
    272268
    273269\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
     
    291287columns=fullflexible,
    292288basicstyle=\linespread{0.9}\sf,                 % reduce line spacing and use sanserif font
    293 stringstyle=\small\tt,                                  % use typewriter font
     289stringstyle=\tt,                                                % use typewriter font
    294290tabsize=5,                                                              % N space tabbing
    295291xleftmargin=\parindentlnth,                             % indent code to paragraph indentation
  • doc/LaTeXmacros/lstlang.sty

    r24d6572 r34b4268  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Tue May  2 08:52:35 2023
    11 %% Update Count     : 30
     10%% Last Modified On : Mon May 31 08:20:41 2021
     11%% Update Count     : 28
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    112112\lstdefinelanguage{CFA}[ANSI]{C}{
    113113        morekeywords={
    114                 _Alignas, _Alignof, __alignof, __alignof__, and, asm, __asm, __asm__, _Atomic, __attribute, __attribute__,
    115                 __auto_type, basetypeof, _Bool, catch, catchResume, choose, coerce, _Complex, __complex, __complex__, __const, __const__,
    116                 coroutine, _Decimal32, _Decimal64, _Decimal128, disable, enable, exception, __extension__, fallthrough, fallthru, finally, fixup,
    117                 __float80, float80, __float128, float128, _Float16, _Float32, _Float32x, _Float64, _Float64x, _Float128, _Float128x,
    118                 forall, fortran, generator, _Generic, _Imaginary, __imag, __imag__, inline, __inline, __inline__, int128, __int128, __int128_t,
    119                 __label__, monitor, mutex, _Noreturn, __builtin_offsetof, one_t, or, recover, report, restrict, __restrict, __restrict__,
    120                 __signed, __signed__, _Static_assert, suspend, thread, __thread, _Thread_local, throw, throwResume, timeout, trait, try,
    121                 typeof, __typeof, __typeof__, typeid, __uint128_t, __builtin_va_arg, __builtin_va_list, virtual, __volatile, __volatile__,
    122                 vtable, waitfor, waituntil, when, with, zero_t,
     114                _Alignas, _Alignof, __alignof, __alignof__, asm, __asm, __asm__, __attribute, __attribute__,
     115                auto, basetypeof, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
     116                coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally, fixup,
     117                __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__,
     118                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
     119                otype, restrict, __restrict, __restrict__, recover, report, __signed, __signed__, _Static_assert, suspend,
     120                thread, __thread, _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,
     121                virtual, __volatile, __volatile__, waitfor, when, with, zero_t,
    123122    },
    124123        moredirectives={defined,include_next}%
  • doc/bibliography/pl.bib

    r24d6572 r34b4268  
    147147    author      = {Zhang, Yizhou and Salvaneschi, Guido and Beightol, Quinn and Liskov, Barbara and Myers, Andrew C.},
    148148    title       = {Accepting Blame for Safe Tunneled Exceptions},
    149     organization= {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation},
     149    booktitle   = {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation},
    150150    series      = {PLDI'16},
    151151    year        = {2016},
     
    198198}
    199199
    200 @inproceedings{Koster16,
    201     keywords    = {Actor Model, Concurrency},
    202     contributer = {pabuhr@plg},
    203     author      = {De Koster, Joeri and Van Cutsem, Tom and De Meuter, Wolfgang},
    204     title       = {43 Years of Actors: A Taxonomy of Actor Models and Their Key Properties},
    205     publisher   = {ACM},
    206     address     = {New York, NY, USA},
    207     organization= {Proceedings of the 6th International Workshop on Programming Based on Actors, Agents, and Decentralized Control},
    208     pages       = {31-40},
    209     numpages    = {10},
    210     year        = {2016},
    211     location    = {Amsterdam, Netherlands},
    212     series      = {AGERE 2016}
    213 }
    214 
    215 @misc{ActorBenchmarks,
    216     keywords    = {Actors, microbenchmarks, uC++. CAF, ProtoActor, AkkaC, AkkaT},
    217     contributer = {pabuhr@plg},
    218     key         = {ActorBenchmarks},
    219     title       = {Actor Benchmarks},
    220     author      = {Peter A. Buhr and Colby A. Parsons},
    221     howpublished= {\href{https://github.com/pabuhr/ActorExperiments}{https://\-github.com/\-pabuhr/\-ActorExperiments}},
    222     year        = 2022,
    223 }
    224 
    225200@book{Actors,
    226201    keywords    = {actors, concurrency},
     
    230205    publisher   = {MIT Press, Cambridge},
    231206    year        = 1986
    232 }
    233 
    234 @inproceedings{Srinivasan08,
    235     author      = {Srinivasan, Sriram and Mycroft, Alan},
    236     editor      = {Vitek, Jan},
    237     title       = {Kilim: Isolation-Typed Actors for Java},
    238     organization= {ECOOP 2008 -- Object-Oriented Programming},
    239     year        = {2008},
    240     publisher   = {Springer Berlin Heidelberg},
    241     address     = {Berlin, Heidelberg},
    242     pages       = {104--128},
    243 }
    244 
    245 @inproceedings{Haller07,
    246     author      = {Haller, Philipp and Odersky, Martin},
    247     editor      = {Murphy, Amy L. and Vitek, Jan},
    248     title       = {Actors That Unify Threads and Events},
    249     organization= {Coordination Models and Languages},
    250     year        = 2007,
    251     publisher   = {Springer Berlin Heidelberg},
    252     address     = {Berlin, Heidelberg},
    253     pages       = {171-190},
    254207}
    255208
     
    292245}
    293246
    294 @manual{Ada95,
    295     keywords    = {Ada},
    296     contributer = {pabuhr@plg},
    297     title       = {{A}da Reference Manual},
    298     edition     = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}},
    299     organization= {Intermetrics, Inc.},
    300     month       = dec,
    301     year        = 1995,
    302     note        = {Language and Standards Libraries}
    303 }
    304 
    305 @manual{Ada12,
    306     keywords    = {ISO/IEC Ada},
    307     contributer = {pabuhr@plg},
    308     author      = {Ada12},
    309     title       = {Programming languages -- {Ada} ISO/IEC 8652:2012},
    310     edition     = {3rd},
    311     organization= {International Standard Organization},
    312     address     = {Geneva, Switzerland},
    313     year        = 2012,
    314     note        = {\href{https://www.iso.org/standard/61507.html}{https://\-www.iso.org/\-standard/\-61507.html}},
    315 }
    316 
    317 @manual{Ada95:annotated,
    318     keywords    = {Ada},
    319     contributer = {pabuhr@plg},
    320     title       = {Annotated {A}da Reference Manual},
    321     edition     = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}},
    322     organization= {Intermetrics, Inc.},
    323     month       = dec,
    324     year        = 1995,
    325     note        = {Language and Standards Libraries}
    326 }
    327 
    328247@article{dim:ada,
    329248    keywords    = {Dimensional Analysis, Ada},
     
    337256    number      = 2,
    338257    pages       = {189-203},
    339 }
    340 
    341 @article{Agrawal08,
    342     keywords    = {Adaptive scheduling, multiprocessing, processor allocation, randomized algorithm, space sharing, thread scheduling, two-level scheduling, work-stealing},
    343     author      = {Agrawal, Kunal and Leiserson, Charles E. and He, Yuxiong and Hsu, Wen Jing},
    344     title       = {Adaptive Work-stealing with Parallelism Feedback},
    345     journal     = {ACM Trans. Comput. Syst.},
    346     issue_date  = {September 2008},
    347     volume      = {26},
    348     number      = {3},
    349     month       = sep,
    350     year        = {2008},
    351     pages       = {7:1-7:32},
    352     publisher   = {ACM},
    353     address     = {New York, NY, USA},
    354258}
    355259
     
    472376    month       = sep,
    473377    year        = 2016,
    474     note        = {\url{http://doc.akka.io/docs/akka/2.4/AkkaScala.pdf}},
    475 }
    476 
    477 @misc{AkkaClassic,
    478     contributer = {pabuhr@plg},
    479     key         = {AkkaClassic},
    480     title       = {Akka Classic Actors},
    481     author      = {{Lightbend}},
    482     howpublished= {\url{https://doc.akka.io/docs/akka/current/index-classic.html}},
    483     year        = 2023,
    484 }
    485 
    486 @misc{AkkaFuture,
    487     contributer = {pabuhr@plg},
    488     key         = {AkkaFuture},
    489     title       = {Akka Futures},
    490     author      = {{Lightbend}},
    491     howpublished= {\url{https://doc.akka.io/docs/akka/2.5/futures.html}},
    492     year        = 2022,
    493 }
    494 
    495 @misc{AkkaTyped,
    496     contributer = {pabuhr@plg},
    497     key         = {AkkaTyped},
    498     title       = {Akka Typed Actors},
    499     author      = {{Lightbend}},
    500     howpublished= {\url{https://doc.akka.io/docs/akka/2.5/typed-actors.html}},
    501     year        = 2022,
     378    note        = {\href{http://doc.akka.io/docs/akka/2.4/AkkaScala.pdf}{http://\-doc.akka.io/\-docs/\-akka/\-2.4/\-AkkaScala.pdf}},
    502379}
    503380
     
    671548}
    672549
    673 @inproceedings{Mitzenmacher98,
    674     author      = {Mitzenmacher, Michael},
    675     title       = {Analyses of Load Stealing Models Based on Differential Equations},
    676     organization= {Proceedings of the Tenth Annual ACM Symposium on Parallel Algorithms and Architectures},
    677     series      = {SPAA '98},
    678     year        = {1998},
    679     isbn        = {0-89791-989-0},
    680     location    = {Puerto Vallarta, Mexico},
    681     pages       = {212-221},
    682     publisher   = {ACM},
    683     address     = {New York, NY, USA},
    684 }
    685 
    686 @inproceedings{Squillante91,
    687     author      = {Squillante, Mark S. and Nelson, Randolph D.},
    688     title       = {Analysis of Task Migration in Shared-memory Multiprocessor Scheduling},
    689     organization= {Proceedings of the 1991 ACM SIGMETRICS Conference on Measurement and Modeling of Computer Systems},
    690     series      = {SIGMETRICS '91},
    691     year        = {1991},
    692     isbn        = {0-89791-392-2},
    693     location    = {San Diego, California, USA},
    694     pages       = {143-155},
    695     publisher   = {ACM},
    696     address     = {New York, NY, USA},
    697 }
    698 
    699550@article{Sinha00,
    700551    author      = {Saurabh Sinha and Mary Jean Harrold},
     
    711562    author      = {Martin P. Robillard and Gail C. Murphy},
    712563    title       = {Analyzing Exception Flow in {J}ava Programs},
    713     organization= {ESEC/FSE-7: Proceedings of the 7th European Software Engineering Conference held jointly
     564    booktitle   = {ESEC/FSE-7: Proceedings of the 7th European Software Engineering Conference held jointly
    714565                   with the 7th ACM SIGSOFT International Symposium on Foundations of Software Engineering},
    715566    year        = 1999,
     
    753604    author      = {Henry Qin and Qian Li and Jacqueline Speiser and Peter Kraft and John Ousterhout},
    754605    title       = {Arachne: Core-Aware Thread Management},
    755     organization= {13th {USENIX} Symp. on Oper. Sys. Design and Impl. ({OSDI} 18)},
     606    booktitle   = {13th {USENIX} Symp. on Oper. Sys. Design and Impl. ({OSDI} 18)},
    756607    year        = {2018},
    757608    address     = {Carlsbad, CA},
     
    810661    author      = {Jaewoong Chung and Luke Yen and Stephan Diestelhorst and Martin Pohlack and Michael Hohmuth and David Christie and Dan Grossman},
    811662    title       = {ASF: AMD64 Extension for Lock-Free Data Structures and Transactional Memory},
    812     organization= {Proceedings of the 2010 43rd Annual IEEE/ACM International Symposium on Microarchitecture},
     663    booktitle   = {Proceedings of the 2010 43rd Annual IEEE/ACM International Symposium on Microarchitecture},
    813664    series      = {MICRO '43},
    814665    year        = 2010,
     
    831682}
    832683
    833 @misc{AsyncAwait,
    834     contributer = {pabuhr@plg},
    835     key         = {AsyncAwait},
    836     title       = {Async Await},
    837     author      = {{WikipediA}},
    838     howpublished= {\href{https://en.wikipedia.org/wiki/Async/await}{https://\-en.wikipedia.org/\-wiki/\-Async/\-await}},
    839     year        = 2022,
    840 }
    841 
    842684@inproceedings{Krischer08,
    843685    keywords    = {exception handling, asynchronous, blocked tasks},
     
    845687    author      = {Roy Krischer and Peter A. Buhr},
    846688    title       = {Asynchronous Exception Propagation in Blocked Tasks},
    847     organization= {4th International Workshop on Exception Handling (WEH.08)},
     689    booktitle   = {4th International Workshop on Exception Handling (WEH.08)},
    848690    optorganization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)},
    849691    address     = {Atlanta, U.S.A},
     
    854696
    855697@article{Joung00,
    856     keywords    = {group mutual exclusion, congenial talking philosophers, resource allocation, shared-memory algorithms},
    857698    author      = {Joung, Yuh-Jzer},
    858699    title       = {Asynchronous group mutual exclusion},
     
    918759    publisher   = {ACM},
    919760    address     = {New York, NY, USA},
    920 }
    921 
    922 @techreport{Neill09,
    923     author      = {Daniel Neill and Adam Wierman},
    924     title       = {On the Benefits of Work Stealing in Shared-Memory Multiprocessors},
    925     institution = {Carnegie Mellon University},
    926     address     = {California Institute of Technology, Pasadena, CA, USA},
    927     note        = {\href{http://www.cs.cmu.edu/~acw/15740/paper.pdf}{http://\-www.cs.cmu.edu/\-$\sim$acw/\-15740/\-paper.pdf}, Accessed May 2014},
    928     year        = 2009,
    929761}
    930762
     
    1084916}
    1085917
    1086 @inproceedings{Ding12,
    1087     keywords    = {fairness, multicore, time sharing, work stealing},
    1088     author      = {Ding, Xiaoning and Wang, Kaibo and Gibbons, Phillip B. and Zhang, Xiaodong},
    1089     title       = {BWS: Balanced Work Stealing for Time-sharing Multicores},
    1090     organization= {Proceedings of the 7th ACM European Conference on Computer Systems},
    1091     series      = {EuroSys '12},
    1092     year        = {2012},
    1093     location    = {Bern, Switzerland},
    1094     pages       = {365-378},
    1095     publisher   = {ACM},
    1096     address     = {New York, NY, USA},
    1097 }
    1098 
    1099918% C
    1100919
     
    1171990}
    1172991
    1173 @inproceedings{CAF,
    1174     keywords    = {performance measurement, actor model, c++, message-oriented middleware, distributed debugging},
    1175     contributer = {pabuhr@plg},
    1176     author      = {Charousset, Dominik and Hiesgen, Raphael and Schmidt, Thomas C.},
    1177     title       = {{CAF} -- the {C}++ Actor Framework for Scalable and Resource-Efficient Applications},
    1178     publisher   = {ACM},
    1179     address     = {New York, NY, USA},
    1180     organization= {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control},
    1181     pages       = {15-28},
    1182     numpages    = 14,
    1183     location    = {Portland, Oregon, USA},
    1184     series      = {AGERE'14},
    1185     year        = 2014,
    1186 }
    1187 
    1188992@techreport{cfa-cc,
    1189993    keywords    = {Cforall, cfa-cc, transpiler},
     
    12091013    year        = 2018,
    12101014    pages       = {2111-2146},
    1211     optnote     = {\href{http://dx.doi.org/10.1002/spe.2624}{http://\-dx.doi.org/\-10.1002/\-spe.2624}},
     1015    note        = {\href{http://dx.doi.org/10.1002/spe.2624}{http://\-dx.doi.org/\-10.1002/\-spe.2624}},
    12121016}
    12131017
     
    13681172@techreport{Prokopec11,
    13691173    keywords    = {ctrie, concurrent map},
    1370     contributer = {a3moss@uwaterloo.ca},
     1174    contributer = {a3moss@uwaterloo.ca},
    13711175    title       = {Cache-aware lock-free concurrent hash tries},
    13721176    author      = {Prokopec, Aleksandar and Bagwell, Phil and Odersky, Martin},
     
    16921496    author      = {Emery D. Berger and Benjamin G. Zorn and Kathryn S. McKinley},
    16931497    title       = {Composing High-Performance Memory Allocators},
    1694     organization= {{SIGPLAN} Conference on Programming Language Design and Implementation},
     1498    booktitle   = {{SIGPLAN} Conference on Programming Language Design and Implementation},
    16951499    pages       = {114-124},
    16961500    year        = 2001,
     
    18701674    month       = sep,
    18711675    year        = 2020,
    1872     note        = {\url{https://plg.uwaterloo.ca/~usystem/pub/uSystem/uC++.pdf}},
     1676    note        = {\href{https://plg.uwaterloo.ca/~usystem/pub/uSystem/uC++.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-pub/\-uSystem/uC++.pdf}},
    18731677}
    18741678
     
    20041808    number      = 5,
    20051809    pages       = {1005-1042},
    2006     optnote     = {\href{https://onlinelibrary.wiley.com/doi/10.1002/spe.2925}{https://\-onlinelibrary.wiley.com/\-doi/\-10.1002/\-spe.2925}},
     1810    note        = {\href{https://onlinelibrary.wiley.com/doi/10.1002/spe.2925}{https://\-onlinelibrary.wiley.com/\-doi/\-10.1002/\-spe.2925}},
    20071811}
    20081812
     
    21921996    address     = {Eindhoven, Neth.},
    21931997    year        = 1965,
    2194     optnote     = {Reprinted in \cite{Genuys68} pp. 43--112.},
    2195     note        = {\url{https://pure.tue.nl/ws/files/4279816/344354178746665.pdf}},
     1998    note        = {Reprinted in \cite{Genuys68} pp. 43--112.}
    21961999}
    21972000
     
    22002003    author      = {Adya, Atul and Howell, Jon and Theimer, Marvin and Bolosky, William J. and Douceur, John R.},
    22012004    title       = {Cooperative Task Management Without Manual Stack Management},
    2202     organization= {Proc. of the General Track USENIX Tech. Conf.},
     2005    booktitle   = {Proc. of the General Track USENIX Tech. Conf.},
    22032006    series      = {ATEC '02},
    22042007    year        = {2002},
     
    23082111    year        = 2016,
    23092112    note        = {\href{http://dlang.org/spec/spec.html}{http://\-dlang.org/\-spec/\-spec.html}},
    2310 }
    2311 
    2312 @article{Acar02,
    2313     author      = {Acar, Umut A. and Blelloch, Guy E. and Blumofe, Robert D.},
    2314     title       = {The Data Locality of Work Stealing},
    2315     journal     = {Theory of Computing Systems},
    2316     volume      = {35},
    2317     number      = {3},
    2318     year        = {2002},
    2319     publisher   = {Springer-Verlag},
    2320     pages       = {321-347},
    23212113}
    23222114
     
    25782370    editor      = {R. E. A. Mason},
    25792371    organization= {IFIP},
    2580     publisher   = {North-Holland},
    2581     summary     = {
     2372    publisher = {North-Holland},
     2373    summary = {
    25822374        Packages group related declarations or subprograms, and encapsulate
    25832375        data types.  Separate interfaces and bodies promotes information
     
    28062598    address     = {Waterview Corporate Center, 20 Waterview Boulevard, Parsippany, NJ 07054},
    28072599    year        = {1993}
    2808 }
    2809 
    2810 @inproceedings{Chen14,
    2811     keywords    = {Core allocation, Multi-programmed, Work-stealing},
    2812     author      = {Chen, Quan and Zheng, Long and Guo, Minyi},
    2813     title       = {DWS: Demand-aware Work-Stealing in Multi-programmed Multi-core Architectures},
    2814     organization= {Proceedings of Programming Models and Applications on Multicores and Manycores},
    2815     series      = {PMAM'14},
    2816     year        = {2007},
    2817     location    = {Orlando, FL, USA},
    2818     pages       = {131:131-131:139},
    2819     articleno   = {131},
    2820     numpages    = {9},
    2821     publisher   = {ACM},
    2822     address     = {New York, NY, USA},
    28232600}
    28242601
     
    28542631    year        = 2003,
    28552632    pages       = {29-35},
    2856 }
    2857 
    2858 @inproceedings{Hamidzadeh96,
    2859     keywords    = {processor scheduling, resource allocation, shared memory systems, average memory referencing delay},
    2860     author      = {Hamidzadeh, B. and Lilja, D.J.},
    2861     booktitle   = {Distributed Computing Systems, 1996., Proceedings of the 16th International Conference on},
    2862     title       = {Dynamic scheduling strategies for shared-memory multiprocessors},
    2863     year        = {1996},
    2864     month       = {May},
    2865     pages       = {208-215},
    2866 }
    2867 
    2868 @article{Hendler06,
    2869     keywords    = {Concurrent programming; Load balancing; Work stealing; Lock-free; Data structures},
    2870     author      = {Hendler, Danny and Lev, Yossi and Moir, Mark and Shavit, Nir},
    2871     title       = {A dynamic-sized nonblocking work stealing deque},
    2872     journal     = {Distributed Computing},
    2873     volume      = {18},
    2874     number      = {3},
    2875     year        = {2006},
    2876     publisher   = {Springer-Verlag},
    2877     pages       = {189-207},
    28782633}
    28792634
     
    29792734}
    29802735
    2981 @inproceedings{Blelloch04,
    2982     keywords    = {chip multiprocessors, multithreaded architectures, scheduling algorithms, shared cache},
    2983     author      = {Blelloch, Guy E. and Gibbons, Phillip B.},
    2984     title       = {Effectively Sharing a Cache Among Threads},
    2985     organization= {Proceedings of the Sixteenth Annual ACM Symposium on Parallelism in Algorithms and Architectures},
    2986     series      = {SPAA '04},
    2987     year        = {2004},
    2988     location    = {Barcelona, Spain},
    2989     pages       = {235-244},
    2990     publisher   = {ACM},
    2991     address     = {New York, NY, USA},
    2992 }
    2993 
    29942736@techreport{Habermann80,
    29952737    keywords    = {Ada, threads},
     
    30662808    title       = {Encapsulation and Inheritance in Object-Oriented Programming Languages},
    30672809    journal     = sigplan,
    3068     volume      = {21},
    3069     number      = {11},
     2810    volume      = {21},    number = {11},
    30702811    pages       = {38-45},
    3071     month       = nov,
    3072     year        = 1986,
     2812    month       = nov, year = 1986,
    30732813    comment     = {
    30742814        Client, child interfaces should be distinct.  Child interface
     
    31262866}
    31272867
    3128 @inproceedings{Ribic14,
    3129     keywords    = {dvfs, energy efficiency, language runtimes, thread management, work stealing},
    3130     author      = {Ribic, Haris and Liu, Yu David},
    3131     title       = {Energy-efficient Work-stealing Language Runtimes},
    3132     organization= {Proceedings of the 19th International Conference on Architectural Support for Programming Languages and Operating Systems},
    3133     series      = {ASPLOS '14},
    3134     year        = {2014},
    3135     location    = {Salt Lake City, Utah, USA},
    3136     pages       = {513-528},
    3137     publisher   = {ACM},
    3138     address     = {New York, NY, USA},
    3139 }
    3140 
    31412868@manual{EPT,
    31422869    keywords    = {concurrency, light-weight threads},
     
    31602887}
    31612888
    3162 @misc{Soleimani16,
    3163     keywords    = {Erlang, scheduler, history},
    3164     contributer = {pabuhr@plg},
    3165     author      = {Hamidreza Soleimani},
    3166     title       = {Erlang Scheduler Details and Why It Matters},
    3167     month       = feb,
    3168     year        = 2016,
    3169     howpublished= {\url{https://hamidreza-s.github.io/erlang/scheduling/real-time/preemptive/migration/2016/02/09/erlang-scheduler-details.html}},
    3170 }
    3171 
    31722889@inproceedings{MH88,
    31732890    keywords    = {modules, general sums, general products},
     
    31862903    publisher   = {North Oxford Academic},
    31872904    year        = 1985
    3188 }
    3189 
    3190 @article{Torrellas95,
    3191     author      = {J. Torrellas and A. Tucker and A. Gupta},
    3192     title       = {Evaluating the Performance of Cache-Affinity Scheduling in Shared-Memory Multiprocessors},
    3193     journal     = {Journal of Parallel and Distributed Computing},
    3194     volume      = {24},
    3195     number      = {2},
    3196     pages       = {139-151},
    3197     year        = {1995},
    31982905}
    31992906
     
    39073614    author      = {Robert Griesemer and Rob Pike and Ken Thompson},
    39083615    title       = {{Go} Programming Language},
    3909     address     = {Mountain View, CA, USA},
    39103616    organization= {Google},
    39113617    year        = 2009,
     
    40193725@article{Michael04a,
    40203726    keywords    = {Lock-free, synchronization, concurrent programming, memory management, multiprogramming, dynamic data structures},
    4021     contributer = {pabuhr@plg},
    40223727    author      = {Maged M. Michael},
    40233728    title       = {Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects},
     
    40303735    publisher   = {IEEE Press},
    40313736    address     = {Piscataway, NJ, USA},
    4032 }
    4033 
    4034 @inproceedings{Johansson02,
    4035     keywords    = {concurrent languages, erlang, garbage collection, message passing, runtime systems},
    4036     contributer = {pabuhr@plg},
    4037     author      = {Erik Johansson and Konstantinos Sagonas and Jesper Wilhelmsson},
    4038     title       = {Heap Architectures for Concurrent Languages Using Message Passing},
    4039     year        = {2002},
    4040     isbn        = {1581135394},
    4041     publisher   = {ACM},
    4042     address     = {New York, NY, USA},
    4043     organization= {Proceedings of the 3rd International Symposium on Memory Management},
    4044     pages       = {88-99},
    4045     location    = {Berlin, Germany},
    40463737}
    40473738
     
    42233914    title       = {Implementing Lock-Free Queues},
    42243915    booktitle   = {Seventh International Conference on Parallel and Distributed Computing Systems},
    4225     organization= {International Society for Computers and Their Applications},
    42263916    address     = {Las Vegas, Nevada, U.S.A.},
    42273917    year        = {1994},
    42283918    pages       = {64-69},
    4229 }
    4230 
    4231 @inproceedings{Halstead84,
    4232     author      = {Halstead,Jr., Robert H.},
    4233     title       = {Implementation of Multilisp: Lisp on a Multiprocessor},
    4234     organization= {Proceedings of the 1984 ACM Symposium on LISP and Functional Programming},
    4235     series      = {LFP '84},
    4236     year        = {1984},
    4237     location    = {Austin, Texas, USA},
    4238     pages       = {9-17},
    4239     publisher   = {ACM},
    4240     address     = {New York, NY, USA},
    42413919}
    42423920
     
    50174695    contributer = {pabuhr@plg},
    50184696    author      = {Lua},
    5019     title       = {Lua 5.4 Reference Manual},
    5020     organization= {Pontifical Catholic University},
    5021     address     = {\href{https://www.lua.org/manual/5.4}{https://\-www.lua.org/\-manual/\-5.4}},
    5022     year        = 2020,
     4697    title       = {Lua 5.3 Reference Manual},
     4698    address     = {\href{https://www.lua.org/manual/5.3}{https://\-www.lua.org/\-manual/\-5.3}},
     4699    year        = 2018,
    50234700}
    50244701
     
    50874764}
    50884765
    5089 @misc{MMTk,
     4766@manual{MMTk,
    50904767    keywords    = {Java memory management},
    50914768    contributer = {pabuhr@plg},
     
    50944771    month       = sep,
    50954772    year        = 2006,
    5096     howpublished= {\url{http://cs.anu.edu.au/~Robin.Garner/mmtk-guide.pdf}},
     4773    note        = {\href{http://cs.anu.edu.au/~Robin.Garner/mmtk-guide.pdf}
     4774                  {http://cs.anu.edu.au/\-$\sim$Robin.Garner/\-mmtk-guide.pdf}},
    50974775}
    50984776
     
    54005078    year        = 2015,
    54015079    note        = {\href{http://www.mpi-forum.org/docs/mpi-3.1/mpi31-report.pdf}{http://www.mpi-forum.org/\-docs/\-mpi-3.1/\-mpi31-report.pdf}},
    5402 }
    5403 
    5404 @article{Lombardo19,
    5405     contributer = {pabuhr@plg},
    5406     author      = {Lombardo, Gianfranco and Fornacciari, Paolo and Mordonini, Monica and Tomaiuolo, Michele and Poggi, Agostino},
    5407     title       = {A Multi-Agent Architecture for Data Analysis},
    5408     journal     = {Future Internet},
    5409     volume      = 11,
    5410     year        = 2019,
    5411     number      = 2,
    54125080}
    54135081
     
    56095277        Programming Language},
    56105278    year        = 1980,
    5611     month       = dec,
    5612     pages       = {139-145},
     5279    month       = dec, pages = {139-145},
    56135280    note        = {SIGPLAN Notices, v. 15, n. 11},
    56145281    abstract    = {
     
    57315398    year        = 2005,
    57325399    pages       = {146-196},
    5733     publisher   = {ACM},
    5734     address     = {New York, NY, USA},
    5735 }
    5736 
    5737 @inproceedings{Hendler02,
    5738     author      = {Hendler, Danny and Shavit, Nir},
    5739     title       = {Non-blocking Steal-half Work Queues},
    5740     organization= {Proceedings of the Twenty-first Annual Symposium on Principles of Distributed Computing},
    5741     series      = {PODC '02},
    5742     year        = {2002},
    5743     location    = {Monterey, California},
    5744     pages       = {280-289},
    57455400    publisher   = {ACM},
    57465401    address     = {New York, NY, USA},
     
    59915646}
    59925647
    5993 @misc{OpenTelemetry,
    5994     contributer = {pabuhr@plg},
    5995     key         = {OpenTelemetry},
    5996     title       = {OpenTelemetry},
    5997     author      = {{Asynkron AB}},
    5998     howpublished= {\href{https://proto.actor/docs/tracing}{https://\-proto.actor/\-docs/\-tracing}},
    5999     year        = 2022,
    6000 }
    6001 
    60025648@inproceedings{Krebbers14,
    60035649    keywords    = {c formalization},
     
    62375883}
    62385884
    6239 @article{Nigro21,
    6240     keywords    = {Actors, Asynchronous messages, Reflective control on message passing, Lock-free parallel computing, Java, Scalable multi-agent systems, Parallel matrix multiplication, Iterated Prisoner's Dilemma},
    6241     contributer = {pabuhr@plg},
    6242     author      = {Libero Nigro},
    6243     title       = {Parallel Theatre: An actor framework in {Java} for high performance computing},
    6244     journal     = {Simulation Modelling Practice and Theory},
    6245     volume      = {106},
    6246     number      = {102189},
    6247     year        = {2021},
    6248 }
    6249 
    62505885@incollection{Stroustrup96,
    62515886    keywords    = {concurrency, C++},
     
    62825917    journal     = ieeese,
    62835918    year        = 1984,
    6284     month       = sep,
    6285     volume      = "SE-10",
    6286     number      = 5,
    6287     pages       = {528-543},
     5919    month       = sep, volume = "SE-10", number = 5, pages = {528-543},
    62885920    abstract    = {
    62895921        Parameterized programming is a powerful technique for the reliable
     
    63175949    booktitle   = {USENIX {C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Conference},
    63185950    organization= {USENIX Association},
    6319     year        = 1988,
    6320     pages       = {1-18},
     5951    year        = 1988, pages = {1-18}
    63215952}
    63225953
     
    64066037}
    64076038
    6408 @incollection{Kazempour08,
    6409     keywords    = {multicore processors; cache affinity; performance evaluation; scheduling},
    6410     author      = {Kazempour, Vahid and Fedorova, Alexandra and Alagheband, Pouya},
    6411     title       = {Performance Implications of Cache Affinity on Multicore Processors},
    6412     organization= {Euro-Par 2008 -- Parallel Processing},
    6413     series      = {Lecture Notes in Computer Science},
    6414     editor      = {Luque, Emilio and Margalef, Tomas and Benitez, Domingo},
    6415     year        = {2008},
    6416     volume      = {5168},
    6417     pages       = {151-161},
    6418     publisher   = {Springer Berlin Heidelberg},
    6419 }
    6420 
    6421 @article{Anderson89,
    6422     keywords    = {data structures, multiprocessing systems, operating systems (computers), performance evaluation, critical resource waiting},
    6423     author      = {Anderson, T.E. and Lazowska, E.D. and Levy, H.M.},
    6424     journal     = {Computers, IEEE Transactions on},
    6425     title       = {The Performance Implications of Thread Management Alternatives for Shared-Memory Multiprocessors},
    6426     year        = {1989},
    6427     month       = {Dec},
    6428     volume      = {38},
    6429     number      = {12},
    6430     pages       = {1631-1644},
    6431 }
    6432 
    64336039@article{Anderson90,
    64346040    keywords    = {spin locks, back off, performance},
     
    64426048    number      = 1,
    64436049    pages       = {6-16},
    6444 }
    6445 
    6446 @article{Blumofe98,
    6447     author      = {Blumofe, Robert D. and Papadopoulos, Dionisios},
    6448     title       = {The Performance of Work Stealing in Multiprogrammed Environments (Extended Abstract)},
    6449     journal     = {SIGMETRICS Perform. Eval. Rev.},
    6450     volume      = {26},
    6451     number      = {1},
    6452     month       = jun,
    6453     year        = {1998},
    6454     issn        = {0163-5999},
    6455     pages       = {266-267},
    6456     publisher   = {ACM},
    6457     address     = {New York, NY, USA},
    64586050}
    64596051
     
    66946286}
    66956287
    6696 @article{Varela01,
    6697     keywords    = {programming languages, SALSA, continuations, actors, java, internet, network computing, open systems, mobile computing},
    6698     contributer = {pabuhr@plg},
    6699     author      = {Varela, Carlos and Agha, Gul},
    6700     title       = {Programming Dynamically Reconfigurable Open Systems with SALSA},
    6701     issue_date  = {December 2001},
    6702     publisher   = {Association for Computing Machinery},
    6703     address     = {New York, NY, USA},
    6704     volume      = 36,
    6705     number      = 12,
    6706     journal     = {SIGPLAN Not.},
    6707     year        = 2001,
    6708     month       = dec,
    6709     pages       = {20-34},
    6710 }
    6711 
    67126288@book{PowerPC,
    67136289    key         = {PowerPC processor},
     
    67716347    title       = {Programming Languages -- {C}},
    67726348    organization= {International Standard ISO/IEC 9899:1999 (E)},
    6773     publisher   = {American National Standards Institute},
     6349    publisher   = {American National Standards Institute},
    67746350    address     = {www.ansi.org},
    67756351    year        = 1999,
     
    67826358    title       = {{C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Programming Language ISO/IEC 14882:1998},
    67836359    edition     = {1st},
    6784     organization= {International Standard Organization},
     6360    organization  = {International Standard Organization},
    67856361    address     = {Geneva, Switzerland},
    67866362    year        = 1998,
     
    70736649}
    70746650
    7075 @misc{protoactor,
    7076     contributer = {pabuhr@plg},
    7077     key         = {Protoactor},
    7078     author      = {{proto.actor}},
    7079     title       = {Asynkron AB},
    7080     year        = 2023,
    7081     howpublished= {\url{https://proto.actor}},
    7082 }
    7083 
    70846651@misc{Pthreads,
    70856652    keywords    = {pthreads, C concurrency},
     
    71936760}
    71946761
    7195 @inproceedings{Bacon03,
    7196     keywords    = {utilization, real-time scheduling, read barrier, defragmentation},
    7197     contributer = {pabuhr@plg},
    7198     author      = {David F. Bacon and Perry Cheng and V. T. Rajan},
    7199     title       = {A Real-Time Garbage Collector with Low Overhead and Consistent Utilization},
    7200     year        = {2003},
    7201     organization= {Proceedings of the 30th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages},
    7202     publisher   = {ACM},
    7203     address     = {New York, NY, USA},
    7204     pages       = {285-298},
    7205     location    = {New Orleans, Louisiana, USA},
     6762@manual{Ada95,
     6763    keywords    = {Ada},
     6764    contributer = {pabuhr@plg},
     6765    title       = {{A}da Reference Manual},
     6766    edition     = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}},
     6767    organization= {Intermetrics, Inc.},
     6768    month       = dec,
     6769    year        = 1995,
     6770    note        = {Language and Standards Libraries}
     6771}
     6772
     6773@manual{Ada12,
     6774    keywords    = {ISO/IEC Ada},
     6775    contributer = {pabuhr@plg},
     6776    author      = {Ada12},
     6777    title       = {Programming languages -- {Ada} ISO/IEC 8652:2012},
     6778    edition     = {3rd},
     6779    organization= {International Standard Organization},
     6780    address     = {Geneva, Switzerland},
     6781    year        = 2012,
     6782    note        = {\href{https://www.iso.org/standard/61507.html}{https://\-www.iso.org/\-standard/\-61507.html}},
     6783}
     6784
     6785@manual{Ada95:annotated,
     6786    keywords    = {Ada},
     6787    contributer = {pabuhr@plg},
     6788    title       = {Annotated {A}da Reference Manual},
     6789    edition     = {International Standard {ISO}/{IEC} {8652:1995(E)} with {COR.1:2000}},
     6790    organization = {Intermetrics, Inc.},
     6791    month       = dec,
     6792    year        = 1995,
     6793    note        = {Language and Standards Libraries}
    72066794}
    72076795
     
    73396927    journal     = sigplan,
    73406928    year        = 1991,
    7341     month       = oct,
    7342     volume      = 26,
    7343     number      = 10,
    7344     pages       = {29-43},
     6929    month       = oct, volume = 26, number = 10, pages = {29-43},
    73456930    abstract    = {
    73466931        {\tt lcc} is a new retargetable compiler for ANSI C.  Versions for
     
    74026987}
    74036988
    7404 @misc{rpmalloc,
    7405     author      = {Mattias Jansson},
    7406     title       = {rpmalloc version 1.4.1},
    7407     month       = apr,
    7408     year        = 2022,
    7409     howpublished= {\href{https://github.com/mjansson/rpmalloc}{https://\-github.com/\-mjansson/\-rpmalloc}},
    7410 }
    7411 
    74126989@manual{Rust,
    74136990    keywords    = {Rust programming language},
     
    74407017    publisher   = {ACM},
    74417018    address     = {New York, NY, USA},
    7442     organization= {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control},
     7019    booktitle   = {Proceedings of the 4th International Workshop on Programming Based on Actors Agents \& Decentralized Control},
    74437020    pages       = {67-80},
    74447021    numpages    = {14},
     
    74647041    booktitle   = {PLDI '04: Proceedings of the ACM SIGPLAN 2004 Conference on Programming Language Design and Implementation},
    74657042    location    = {Washington DC, USA},
    7466     organization= {ACM},
     7043    publisher   = {ACM},
    74677044    address     = {New York, NY, USA},
    74687045    volume      = 39,
     
    74707047    month       = jun,
    74717048    pages       = {35-46},
    7472 }
    7473 
    7474 @article{Nickolls08,
    7475     author      = {Nickolls, John and Buck, Ian and Garland, Michael and Skadron, Kevin},
    7476     title       = {Scalable Parallel Programming with CUDA},
    7477     journal     = {Queue},
    7478     volume      = {6},
    7479     number      = {2},
    7480     month       = mar,
    7481     year        = 2008,
    7482     pages       = {40-53},
    7483     publisher   = {ACM},
    7484     address     = {New York, NY, USA},
    74857049}
    74867050
     
    74987062}
    74997063
    7500 @article{Blumofe99,
    7501     keywords    = {critical-path length, multiprocessor, multithreading, randomized algorithm, thread scheduling, work stealing},
    7502     author      = {Blumofe, Robert D. and Leiserson, Charles E.},
    7503     title       = {Scheduling Multithreaded Computations by Work Stealing},
    7504     journal     = {Journal of the ACM},
    7505     volume      = {46},
    7506     number      = {5},
    7507     month       = sep,
    7508     year        = {1999},
    7509     pages       = {720-748},
    7510     publisher   = {ACM},
    7511     address     = {New York, NY, USA},
    7512 }
    7513 
    7514 @inproceedings{Acar13,
    7515     keywords    = {dynamic load balancing, nested parallelism, work stealing},
    7516     author      = {Acar, Umut A. and Chargueraud, Arthur and Rainey, Mike},
    7517     title       = {Scheduling Parallel Programs by Work Stealing with Private Deques},
    7518     organization= {Proceedings of the 18th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming},
    7519     series      = {PPoPP '13},
    7520     year        = {2013},
    7521     location    = {Shenzhen, China},
    7522     pages       = {219-228},
    7523     publisher   = {ACM},
    7524     address     = {New York, NY, USA},
    7525 }
    7526 
    7527 @inproceedings{Chen07,
    7528     keywords    = {chip multiprocessors, constructive cache sharing, parallel depth first, scheduling algorithms, thread granularity, work stealing, working set profiling},
    7529     author      = {Chen, Shimin and Gibbons, Phillip B. and Kozuch, Michael and Liaskovitis, Vasileios and Ailamaki, Anastassia and Blelloch, Guy E. and Falsafi, Babak and Fix, Limor and Hardavellas, Nikos and Mowry, Todd C. and Wilkerson, Chris},
    7530     title       = {Scheduling Threads for Constructive Cache Sharing on CMPs},
    7531     organization= {Proceedings of the Nineteenth Annual ACM Symposium on Parallel Algorithms and Architectures},
    7532     series      = {SPAA '07},
    7533     year        = {2007},
    7534     location    = {San Diego, California, USA},
    7535     pages       = {105-115},
    7536     numpages    = {11},
    7537     publisher   = {ACM},
    7538     address     = {New York, NY, USA},
    7539 }
    7540 
    75417064@manual{SELF,
    75427065    keywords    = {programming language, obect-oriented, polymorphism},
     
    75607083    publisher   = {Springer},
    75617084    note        = {Lecture Notes in Computer Science v. 173},
    7562 }
    7563 
    7564 @inproceedings{Kahn74,
    7565     keywords    = {programming language, obect-oriented, polymorphism},
    7566     contributer = {pabuhr@plg},
    7567     title       = {The Semantics of a Simple Language for Parallel Programming},
    7568     author      = {Gilles Kahn},
    7569     organization= {IFIP Congress},
    7570     year        = 1974,
    75717085}
    75727086
     
    76297143    number      = 12,
    76307144    pages       = {66-76},
    7631 }
    7632 
    7633 @book{Scott13,
    7634     author      = {Michael L. Scott},
    7635     title       = {Shared-Memory Synchronization},
    7636     publisher   = {Morgan \& Claypool},
    7637     year        = 2013,
    7638 }
    7639 
    7640 @inproceedings{Leissa14,
    7641     title       = {{S}ierra: a {SIMD} extension for {C}++},
    7642     author      = {Lei{\ss}a, Roland and Haffner, Immanuel and Hack, Sebastian},
    7643     booktitle   = {Proceedings of the 2014 Workshop on Workshop on programming models for SIMD/Vector processing},
    7644     pages       = {17-24},
    7645     year        = {2014},
    7646     organization= {ACM}
    76477145}
    76487146
     
    82827780
    82837781@article{SysVABI,
    8284     keywords    = {System V ABI},
    8285     contributer = {a3moss@uwaterloo.ca},
     7782    keywords    =  {System V ABI},
     7783    contributer =  {a3moss@uwaterloo.ca},
    82867784    title       = {System {V} application binary interface},
    82877785    author      = {Matz, Michael and Hubicka, Jan and Jaeger, Andreas and Mitchell, Mark},
     
    82897787    volume      = {99},
    82907788    year        = {2013}
    8291 }
    8292 
    8293 @article{Albert18,
    8294     keywords    = {actor-based concurrency, partial order reduction, systematic testing, synchronization, task independence},
    8295     contributer = {pabuhr@plg},
    8296     author      = {Albert, Elvira and Arenas, Puri and G\'{o}mez-Zamalloa, Miguel},
    8297     title       = {Systematic testing of actor systems},
    8298     journal     = {Software Testing, Verification and Reliability},
    8299     volume      = {28},
    8300     number      = {3},
    8301     pages       = {e1661},
    8302     year        = {2018}
    83037789}
    83047790
     
    83277813    journal     = jcss,
    83287814    year        = 1978,
    8329     volume      = 17,
    8330     pages       = {348-375},
     7815    volume      = 17, pages = {348-375}
    83317816}
    83327817
     
    83397824    address     = {New York, New York, U.S.A.},
    83407825    year        = 1982
    8341 }
    8342 
    8343 @article{Arora01,
    8344     author      = {Arora, N. S. and Blumofe, R. D. and Plaxton, C. G.},
    8345     title       = {Thread Scheduling for Multiprogrammed Multiprocessors},
    8346     journal     = {Theory of Computing Systems},
    8347     year        = {2001},
    8348     volume      = {34},
    8349     number      = {2},
    8350     pages       = {115-144},
    8351     publisher   = {Springer-Verlag},
    83527826}
    83537827
     
    85798053}
    85808054
    8581 @misc{AkkaBecome,
    8582     contributer = {pabuhr@plg},
    8583     key         = {AkkaBecome},
    8584     title       = {Typed Actors},
    8585     author      = {{Lightbend}},
    8586     howpublished= {\href{https://doc.akka.io/docs/akka/2.5/typed-actors.html}{https://\-doc.akka.io/\-docs/\-akka/\-2.5/\-typed-actors.html}},
    8587     year        = 2022,
    8588 }
    8589 
    85908055@article{concatenation,
    85918056    keywords    = {record concatenation, isa},
     
    86528117    author      = {Paul R. Wilson},
    86538118    title       = {Uniprocessor Garbage Collection Techniques},
    8654     organization= {Proceedings of the International Workshop on Memory Management},
     8119    booktitle   = {Proceedings of the International Workshop on Memory Management},
    86558120    location    = {St. Malo, France},
    86568121    publisher   = {Springer},
     
    86658130    author      = {Carl Hewitt and Peter Bishop and Richard Steiger},
    86668131    title       = {A Universal Modular {ACTOR} Formalism for Artificial Intelligence},
    8667     organization= {Proceedings of the 3rd International Joint Conference on Artificial Intelligence},
     8132    booktitle   = {Proceedings of the 3rd International Joint Conference on Artificial Intelligence},
    86688133    address     = {Standford, California, U.S.A.},
    86698134    pages       = {235-245},
    8670     location    = {Stanford, USA},
    8671     series      = {IJCAI'73},
    86728135    month       = aug,
    86738136    year        = 1973,
     
    87018164@article{Karsten20,
    87028165    author      = {Karsten, Martin and Barghi, Saman},
    8703     title       = {User-level Threading: Have Your Cake and Eat It Too},
     8166    title       = {{User-level Threading: Have Your Cake and Eat It Too}},
    87048167    year        = {2020},
    87058168    issue_date  = {March 2020},
     
    87268189}
    87278190
    8728 @article{Squillante93,
    8729     keywords    = {buffer storage, performance evaluation, queueing theory, scheduling, shared memory systems, processor-cache affinity},
    8730     author      = {Squillante, M.S. and Lazowska, E.D.},
    8731     title       = {Using Processor-Cache Affinity Information in Shared-Memory Multiprocessor Scheduling},
    8732     journal     = {Parallel and Distributed Systems, IEEE Transactions on},
    8733     year        = {1993},
    8734     month       = {Feb},
    8735     volume      = {4},
    8736     number      = {2},
    8737     pages       = {131-143},
    8738 }
    8739 
    87408191@article{delegation,
    87418192    keywords    = {delegation, inheritance, actors},
     
    88878338    year        = 2003,
    88888339    pages       = {19-24},
    8889 }
    8890 
    8891 @inproceedings{Saman18,
    8892     keywords    = {actors, scheduling, NUMA, locality},
    8893     contributer = {pabuhr@plg},
    8894     author      = {Saman Barghi and Martin Karsten},
    8895     organization= {2018 IEEE International Parallel and Distributed Processing Symposium (IPDPS)},
    8896     title       = {Work-Stealing, Locality-Aware Actor Scheduling},
    8897     year        = {2018},
    8898     address     = {Vancouver, BC, Canada},
    8899     pages       = {484-494},
    8900 }
    8901 
    8902 @article{Wimmer13,
    8903     keywords    = {priorities, scheduler hints, strategies, work-stealing},
    8904     author      = {Wimmer, Martin and Cederman, Daniel and Tr\"{a}ff, Jesper Larsson and Tsigas, Philippas},
    8905     title       = {Work-stealing with Configurable Scheduling Strategies},
    8906     journal     = {SIGPLAN Not.},
    8907     issue_date  = {August 2013},
    8908     volume      = {48},
    8909     number      = {8},
    8910     month       = feb,
    8911     year        = {2013},
    8912     issn        = {0362-1340},
    8913     pages       = {315-316},
    8914     publisher   = {ACM},
    8915     address     = {New York, NY, USA},
    89168340}
    89178341
  • doc/theses/mike_brooks_MMath/Makefile

    r24d6572 r34b4268  
    88PicSRC = ${notdir ${wildcard ${Pictures}/*.png}}
    99DemoSRC = ${notdir ${wildcard ${Programs}/*-demo.cfa}}
    10 PgmSRC = ${notdir ${wildcard ${Programs}/*}}
    11 RunPgmSRC = ${notdir ${wildcard ${Programs}/*.run.*}}
     10PgmSRC = ${notdir ${wildcard ${Programs}/*.cfa}}
    1211BibSRC = ${wildcard *.bib}
    1312
     
    1514BibLIB = .:../../bibliography                   # common citation repository
    1615
    17 #MAKEFLAGS = --no-print-directory # --silent
     16MAKEFLAGS = --no-print-directory # --silent
    1817VPATH = ${Build} ${Pictures} ${Programs} # extra search path for file names used in document
    1918
     
    2120BASE = ${basename ${DOCUMENT}}                  # remove suffix
    2221
    23 DemoTex = ${DemoSRC:%.cfa=${Build}/%.tex}
    24 RunPgmExe = ${addprefix ${Build}/,${basename ${basename ${RunPgmSRC}}}}
    25 RunPgmOut = ${RunPgmExe:%=%.out}
    26 
    2722# Commands
    2823
    2924LaTeX = TEXINPUTS=${TeXLIB} && export TEXINPUTS && pdflatex -halt-on-error -output-directory=${Build}
    3025BibTeX = BIBINPUTS=${BibLIB} && export BIBINPUTS && bibtex
    31 CFA = cfa -O0 -g
    32 CC  = gcc -O0 -g
    33 CXX = g++-11 --std=c++20 -O0 -g
     26CFA = cfa
    3427
    3528# Rules and Recipes
    3629
    37 .PHONY : all fragments_ran clean                        # not file names
    38 .PRECIOUS : ${Build}/% ${Build}/%-demo      # don't delete intermediates
     30.PHONY : all clean                              # not file names
    3931.ONESHELL :
    4032
    41 all : fragments_ran ${DOCUMENT}
    42 
    43 fragments_ran : $(RunPgmOut)
     33all : ${DOCUMENT}
    4434
    4535clean :
     
    4838# File Dependencies
    4939
    50 %.pdf : ${TeXSRC} ${DemoTex} ${PicSRC} ${PgmSRC} ${BibSRC} Makefile | ${Build}
     40%.pdf : ${TeXSRC} ${DemoSRC:%.cfa=%.tex} ${PicSRC} ${PgmSRC} ${BibSRC} Makefile | ${Build}
    5141        ${LaTeX} ${BASE}
    5242        ${BibTeX} ${Build}/${BASE}
     
    6252
    6353%-demo.tex: %-demo | ${Build}
    64         $< > $@
     54        ${Build}/$< > ${Build}/$@
    6555
    66 ${Build}/%-demo: ${Programs}/%-demo.cfa | ${Build}
    67         ${CFA} $< -o $@
     56%-demo: %-demo.cfa
     57        ${CFA} $< -o ${Build}/$@
    6858
    69 ${Build}/%: ${Programs}/%.run.cfa | ${Build}
    70         ${CFA} $< -o $@
    71 
    72 ${Build}/%: ${Programs}/%.run.c | ${Build}
    73         ${CC}  $< -o $@
    74 
    75 ${Build}/%: ${Programs}/%.run.cpp | ${Build}
    76         ${CXX} -MMD $< -o $@
    77 
    78 ${Build}/%.out: ${Build}/% | ${Build}
    79         $< > $@
    80 
    81 -include ${Build}/*.d
  • doc/theses/mike_brooks_MMath/uw-ethesis.bib

    r24d6572 r34b4268  
    6565  bibsource = {dblp computer science bibliography, https://dblp.org}
    6666}
    67 
    68 % --------------------------------------------------
    69 % Linked-list prior work
    70 
    71 @misc{CFAStackEvaluation,
    72     contributer = {a3moss@plg},
    73     author      = {Aaron Moss},
    74     title       = {\textsf{C}$\mathbf{\forall}$ Stack Evaluation Programs},
    75     year        = 2018,
    76     howpublished= {\href{https://cforall.uwaterloo.ca/CFAStackEvaluation.zip}{https://cforall.uwaterloo.ca/\-CFAStackEvaluation.zip}},
    77 }
    78 
    79 @misc{lst:linuxq,
    80   title     = {queue(7) — Linux manual page},
    81   howpublished= {\href{https://man7.org/linux/man-pages/man3/queue.3.html}{https://man7.org/linux/man-pages/man3/queue.3.html}},
    82 }
    83   % see also https://man7.org/linux/man-pages/man7/queue.7.license.html
    84   %          https://man7.org/tlpi/
    85   %          https://www.kernel.org/doc/man-pages/
    86 
    87 @misc{lst:stl,
    88   title     = {std::list},
    89   howpublished= {\href{https://en.cppreference.com/w/cpp/container/list}{https://en.cppreference.com/w/cpp/container/list}},
    90 }
    91 
  • doc/theses/mike_brooks_MMath/uw-ethesis.tex

    r24d6572 r34b4268  
    6060% For hyperlinked PDF, suitable for viewing on a computer, use this:
    6161\documentclass[letterpaper,12pt,titlepage,oneside,final]{book}
    62 \usepackage{times}
    6362\usepackage[T1]{fontenc}        % Latin-1 => 256-bit characters, => | not dash, <> not Spanish question marks
    6463
     
    8887\usepackage{comment} % Removes large sections of the document.
    8988\usepackage{tabularx}
    90 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt,font=normalsize]{subfig}
    91 \renewcommand\thesubfigure{(\alph{subfigure})}
     89\usepackage{subfigure}
    9290
    9391\usepackage{algorithm}
     
    117115    citecolor=blue,        % color of links to bibliography
    118116    filecolor=magenta,      % color of file links
    119     urlcolor=blue,           % color of external links
    120     breaklinks=true
     117    urlcolor=blue           % color of external links
    121118}
    122119\ifthenelse{\boolean{PrintVersion}}{   % for improved print quality, change some hyperref options
     
    132129% although it's supposed to be in both the TeX Live and MikTeX distributions. There are also documentation and
    133130% installation instructions there.
    134 
    135 % Customizing tabularx
    136 \newcolumntype{Y}{>{\centering\arraybackslash}X}
    137131
    138132% Setting up the page margins...
     
    181175\CFAStyle                                               % CFA code-style
    182176\lstset{language=CFA}                                   % default language
    183 \lstset{basicstyle=\linespread{0.9}\sf}                 % CFA typewriter font
     177\lstset{basicstyle=\linespread{0.9}\tt}                 % CFA typewriter font
    184178\lstset{inputpath={programs}}
    185179\newcommand{\PAB}[1]{{\color{red}PAB: #1}}
    186 
    187 \newcommand{\uCpp}{$\mu$\CC}
    188180
    189181%======================================================================
     
    209201%----------------------------------------------------------------------
    210202\begin{sloppypar}
     203
    211204\input{intro}
    212205\input{background}
    213 \input{list}
    214206\input{array}
    215207\input{string}
  • driver/cfa.cc

    r24d6572 r34b4268  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 30 10:47:52 2023
    13 // Update Count     : 478
     12// Last Modified On : Wed Jul 14 21:55:12 2021
     13// Update Count     : 467
    1414//
    1515
     
    4444        static int flags = 0;
    4545
    46     // This allocation 'leaks' memory from the program to the execution
    47     // environment, as putenv does not manage the storage of the string used
    48     // as an environment variable. This leak is necessary to ensure the
    49     // underlying C string is allocated long enough.
    5046        if ( putenv( (char *)( *new string( string( __CFA_FLAGPREFIX__ + to_string( flags++ ) + "__=" ) + arg ) ).c_str() ) ) {
    5147                cerr << argv[0] << " error, cannot set environment variable." << endl;
     
    202198                                } // if
    203199                        } else if ( arg == "-CFA" ) {
    204                                 CFA_flag = true;                                                // strip -CFA flag
     200                                CFA_flag = true;                                                // strip the -CFA flag
    205201                                link = false;
    206202                                args[nargs++] = "-fsyntax-only";                // stop after stage 2
    207203                        } else if ( arg == "-debug" ) {
    208                                 debug = true;                                                   // strip debug flag
     204                                debug = true;                                                   // strip the debug flag
    209205                        } else if ( arg == "-nodebug" ) {
    210                                 debug = false;                                                  // strip nodebug flag
     206                                debug = false;                                                  // strip the nodebug flag
    211207                        } else if ( arg == "-quiet" ) {
    212                                 quiet = true;                                                   // strip quiet flag
     208                                quiet = true;                                                   // strip the quiet flag
    213209                        } else if ( arg == "-noquiet" ) {
    214                                 quiet = false;                                                  // strip noquiet flag
    215                         } else if ( arg == "-invariant" ) {
    216                                 Putenv( argv, "-" + arg );
    217                         } else if ( arg == "--invariant" ) {
    218                                 Putenv( argv, arg );
     210                                quiet = false;                                                  // strip the noquiet flag
    219211                        } else if ( arg == "-no-include-stdhdr" ) {
    220                                 noincstd_flag = true;                                   // strip no-include-stdhdr flag
     212                                noincstd_flag = true;                                   // strip the no-include-stdhdr flag
    221213                        } else if ( arg == "-nolib" ) {
    222                                 nolib = true;                                                   // strip nolib flag
     214                                nolib = true;                                                   // strip the nolib flag
    223215                        } else if ( arg == "-help" ) {
    224                                 help = true;                                                    // strip help flag
     216                                help = true;                                                    // strip the help flag
    225217                        } else if ( arg == "-nohelp" ) {
    226                                 help = false;                                                   // strip nohelp flag
     218                                help = false;                                                   // strip the nohelp flag
    227219                        } else if ( arg == "-cfalib") {
    228220                                compiling_libs = true;
     
    282274                                } // if
    283275                        } else if ( prefix( arg, "-B" ) ) {
    284                                 bprefix = arg.substr(2);                                // strip -B flag
     276                                bprefix = arg.substr(2);                                // strip the -B flag
    285277                        } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) {
    286278                                args[nargs++] = argv[i];                                // pass flag along
     
    329321        #endif // __x86_64__
    330322
    331         // ARM -mno-outline-atomics => use LL/SC instead of calls to atomic routines: __aarch64_swp_acq_rel, __aarch64_cas8_acq_rel
    332         // ARM -march=armv8.2-a+lse => generate Arm LSE extension instructions SWAP and CAS
    333         // https://community.arm.com/developer/tools-software/tools/b/tools-software-ides-blog/posts/making-the-most-of-the-arm-architecture-in-gcc-10
    334         #ifdef __ARM_ARCH
    335         args[nargs++] = "-mno-outline-atomics";                         // use ARM LL/SC instructions for atomics
    336         #endif // __ARM_ARCH
    337 
    338323        #ifdef __DEBUG_H__
    339324        cerr << "args:";
     
    459444
    460445        args[nargs++] = "-fexceptions";                                         // add exception flags (unconditionally)
    461         args[nargs++] = "-D_GNU_SOURCE";                                        // force gnu libraries
    462446
    463447        // add flags based on the type of compile
  • libcfa/configure.ac

    r24d6572 r34b4268  
    122122AC_PROG_CC
    123123AM_PROG_AS
    124 LT_INIT
     124AC_PROG_LIBTOOL
    125125AC_PROG_INSTALL
    126126AC_PROG_MAKE_SET
     
    246246AC_CONFIG_HEADERS(prelude/defines.hfa)
    247247
    248 AC_OUTPUT
     248AC_OUTPUT()
    249249
    250250# Final text
  • libcfa/prelude/builtins.c

    r24d6572 r34b4268  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:33:56 2023
    13 // Update Count     : 135
     12// Last Modified On : Sat Aug 14 08:45:54 2021
     13// Update Count     : 133
    1414//
    1515
     
    6464static inline void ^?{}(generator$ &) {}
    6565
    66 forall( T & )
    67 trait is_generator {
     66trait is_generator(T &) {
    6867      void main(T & this);
    6968      generator$ * get_generator(T & this);
     
    149148
    150149static inline {
    151         int ?\?( int x, unsigned int y ) { __CFA_EXP__(); }
     150        long int ?\?( int x, unsigned int y ) { __CFA_EXP__(); }
    152151        long int ?\?( long int x, unsigned long int y ) { __CFA_EXP__(); }
    153152        long long int ?\?( long long int x, unsigned long long int y ) { __CFA_EXP__(); }
    154153        // unsigned computation may be faster and larger
    155         unsigned int ?\?( unsigned int x, unsigned int y ) { __CFA_EXP__(); }
     154        unsigned long int ?\?( unsigned int x, unsigned int y ) { __CFA_EXP__(); }
    156155        unsigned long int ?\?( unsigned long int x, unsigned long int y ) { __CFA_EXP__(); }
    157156        unsigned long long int ?\?( unsigned long long int x, unsigned long long int y ) { __CFA_EXP__(); }
     
    176175
    177176static inline {
    178         int ?\=?( int & x, unsigned int y ) { x = x \ y; return x; }
     177        long int ?\=?( int & x, unsigned int y ) { x = x \ y; return x; }
    179178        long int ?\=?( long int & x, unsigned long int y ) { x = x \ y; return x; }
    180179        long long int ?\=?( long long int & x, unsigned long long int y ) { x = x \ y; return x; }
    181         unsigned int ?\=?( unsigned int & x, unsigned int y ) { x = x \ y; return x; }
     180        unsigned long int ?\=?( unsigned int & x, unsigned int y ) { x = x \ y; return x; }
    182181        unsigned long int ?\=?( unsigned long int & x, unsigned long int y ) { x = x \ y; return x; }
    183182        unsigned long long int ?\=?( unsigned long long int & x, unsigned long long int y ) { x = x \ y; return x; }
  • libcfa/prelude/prelude-gen.cc

    r24d6572 r34b4268  
    1010// Created On       : Sat Feb 16 08:44:58 2019
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:40:01 2023
    13 // Update Count     : 38
     12// Last Modified On : Tue Apr  2 17:18:24 2019
     13// Update Count     : 37
    1414//
    1515
     
    159159int main() {
    160160        cout << "# 2 \"prelude.cfa\"  // needed for error messages from this file" << endl;
    161         cout << "forall( T & ) trait sized {};" << endl;
     161        cout << "trait sized(T &) {};" << endl;
    162162
    163163        cout << "//////////////////////////" << endl;
  • libcfa/src/Makefile.am

    r24d6572 r34b4268  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Thu May 25 15:20:04 2023
    14 ## Update Count     : 259
     13## Last Modified On : Fri Jul 16 16:00:40 2021
     14## Update Count     : 255
    1515###############################################################################
    1616
     
    4848        math.hfa \
    4949        time_t.hfa \
    50         virtual_dtor.hfa \
    5150        bits/algorithm.hfa \
    5251        bits/align.hfa \
     
    5958        bits/queue.hfa \
    6059        bits/sequence.hfa \
    61         concurrency/atomic.hfa \
    6260        concurrency/iofwd.hfa \
    6361        concurrency/barrier.hfa \
     
    115113        concurrency/once.hfa \
    116114        concurrency/kernel/fwd.hfa \
    117         concurrency/mutex_stmt.hfa \
    118         concurrency/channel.hfa \
    119         concurrency/actor.hfa
     115        concurrency/mutex_stmt.hfa
    120116
    121117inst_thread_headers_src = \
     
    128124        concurrency/monitor.hfa \
    129125        concurrency/mutex.hfa \
    130         concurrency/select.hfa \
    131126        concurrency/thread.hfa
    132127
  • libcfa/src/algorithms/range_iterator.hfa

    r24d6572 r34b4268  
    99// Author           : Thierry Delisle
    1010// Created On       : Tue Nov 30 13:06:22 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 13 23:10:35 2023
    13 // Update Count     : 1
     11// Last Modified By :
     12// Last Modified On :
     13// Update Count     :
    1414//
    15 
    16 #pragma once
    1715
    1816generator RangeIter {
  • libcfa/src/bitmanip.hfa

    r24d6572 r34b4268  
    1111// Created On       : Sat Mar 14 18:12:27 2020
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Mon Jan  9 09:02:43 2023
    14 // Update Count     : 144
     13// Last Modified On : Sat Oct  8 08:28:15 2022
     14// Update Count     : 142
    1515//
    1616
    1717#pragma once
    18 
    19 #include "bits/debug.hfa"                                                               // verify
    2018
    2119// Reference: Bit Twiddling Hacks: http://graphics.stanford.edu/%7Eseander/bithacks.html#CountBitsSetNaive
  • libcfa/src/bits/containers.hfa

    r24d6572 r34b4268  
    1010// Created On       : Tue Oct 31 16:38:50 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:33:08 2023
    13 // Update Count     : 29
     12// Last Modified On : Wed Jan 15 07:42:35 2020
     13// Update Count     : 28
    1414
    1515#pragma once
     
    6969
    7070#ifdef __cforall
    71         forall( T & )
    72         trait is_node {
     71        trait is_node(T &) {
    7372                T *& get_next( T & );
    7473        };
  • libcfa/src/bits/random.hfa

    r24d6572 r34b4268  
    1010// Created On       : Fri Jan 14 07:18:11 2022
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 20 21:45:24 2023
    13 // Update Count     : 186
     12// Last Modified On : Sun Dec 11 18:43:58 2022
     13// Update Count     : 171
    1414//
    1515
    1616#pragma once
    1717
    18 #include <stdint.h>                                                                             // uintXX_t
     18#include <stdint.h>
    1919
    2020#define GLUE2( x, y ) x##y
     
    2424#ifdef __x86_64__                                                                               // 64-bit architecture
    2525        // 64-bit generators
    26         //#define LEHMER64
     26        #define LEHMER64
    2727        //#define XORSHIFT_12_25_27
    28         #define XOSHIRO256PP
     28        //#define XOSHIRO256PP
    2929        //#define KISS_64
    30     // #define SPLITMIX_64
    3130
    3231        // 32-bit generators
    33         //#define XORSHIFT_6_21_7
    34         #define XOSHIRO128PP
    35     // #define SPLITMIX_32
     32        #define XORSHIFT_6_21_7
     33        //#define XOSHIRO128PP
    3634#else                                                                                                   // 32-bit architecture
    3735        // 64-bit generators
    38         //#define XORSHIFT_13_7_17
    39         #define XOSHIRO256PP
    40     // #define SPLITMIX_64
     36        #define XORSHIFT_13_7_17
    4137
    4238        // 32-bit generators
    43         //#define XORSHIFT_6_21_7
    44         #define XOSHIRO128PP
    45     // #define SPLITMIX_32
     39        #define XORSHIFT_6_21_7
    4640#endif // __x86_64__
    4741
    4842// Define C/CFA PRNG name and random-state.
     43
     44// SKULLDUGGERY: typedefs name struct and typedef with the same name to deal with CFA typedef numbering problem.
    4945
    5046#ifdef XOSHIRO256PP
    5147#define PRNG_NAME_64 xoshiro256pp
    5248#define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t)
    53 typedef struct { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T;
     49typedef struct PRNG_STATE_64_T { uint64_t s[4]; } PRNG_STATE_64_T;
    5450#endif // XOSHIRO256PP
    5551
     
    5753#define PRNG_NAME_32 xoshiro128pp
    5854#define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t)
    59 typedef struct { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T;
     55typedef struct PRNG_STATE_32_T { uint32_t s[4]; } PRNG_STATE_32_T;
    6056#endif // XOSHIRO128PP
    6157
     
    8581#endif // XORSHIFT_12_25_27
    8682
    87 #ifdef SPLITMIX_64
    88 #define PRNG_NAME_64 splitmix64
    89 #define PRNG_STATE_64_T uint64_t
    90 #endif // SPLITMIX32
    91 
    92 #ifdef SPLITMIX_32
    93 #define PRNG_NAME_32 splitmix32
    94 #define PRNG_STATE_32_T uint32_t
    95 #endif // SPLITMIX32
    96 
    9783#ifdef KISS_64
    9884#define PRNG_NAME_64 kiss_64
    9985#define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t)
    100 typedef struct { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T;
     86typedef struct PRNG_STATE_64_T { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T;
    10187#endif // KISS_^64
    10288
     
    10490#define PRNG_NAME_32 xorwow
    10591#define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t)
    106 typedef struct { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T;
     92typedef struct PRNG_STATE_32_T { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T;
    10793#endif // XOSHIRO128PP
    10894
     
    124110
    125111// ALL PRNG ALGORITHMS ARE OPTIMIZED SO THAT THE PRNG LOGIC CAN HAPPEN IN PARALLEL WITH THE USE OF THE RESULT.
    126 // Specifically, the current random state is copied for returning, before computing the next value.  As a consequence,
    127 // the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the first random
    128 // value.
    129 
     112// Therefore, the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the
     113// first random value.
    130114
    131115#ifdef __cforall                                                                                // don't include in C code (invoke.h)
    132 
    133 // https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64
    134 //
    135 // Splitmix64 is not recommended for demanding random number requirements, but is often used to calculate initial states
    136 // for other more complex pseudo-random number generators (see https://prng.di.unimi.it).
    137 // Also https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64.
    138 static inline uint64_t splitmix64( uint64_t & state ) {
    139     state += 0x9e3779b97f4a7c15;
    140     uint64_t z = state;
    141     z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
    142     z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
    143     return z ^ (z >> 31);
    144 } // splitmix64
    145 
    146 static inline void splitmix64_set_seed( uint64_t & state , uint64_t seed ) {
    147     state = seed;
    148     splitmix64( state );                                                                // prime
    149 } // splitmix64_set_seed
    150 
    151 // https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32
    152 //
    153 // Splitmix32 is not recommended for demanding random number requirements, but is often used to calculate initial states
    154 // for other more complex pseudo-random number generators (see https://prng.di.unimi.it).
    155 
    156 static inline uint32_t splitmix32( uint32_t & state ) {
    157     state += 0x9e3779b9;
    158     uint64_t z = state;
    159     z = (z ^ (z >> 15)) * 0x85ebca6b;
    160     z = (z ^ (z >> 13)) * 0xc2b2ae35;
    161     return z ^ (z >> 16);
    162 } // splitmix32
    163 
    164 static inline void splitmix32_set_seed( uint32_t & state, uint64_t seed ) {
    165     state = seed;
    166     splitmix32( state );                                                                // prime
    167 } // splitmix32_set_seed
    168 
    169 #ifdef __SIZEOF_INT128__
    170 //--------------------------------------------------
    171 static inline uint64_t lehmer64( __uint128_t & state ) {
    172         __uint128_t ret = state;
    173         state *= 0x_da94_2042_e4dd_58b5;
    174         return ret >> 64;
    175 } // lehmer64
    176 
    177 static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) {
    178         // The seed needs to be coprime with the 2^64 modulus to get the largest period, so no factors of 2 in the seed.
    179         state = splitmix64( seed );                                                     // prime
    180 } // lehmer64_set_seed
    181 
    182 //--------------------------------------------------
    183 static inline uint64_t wyhash64( uint64_t & state ) {
    184         uint64_t ret = state;
    185         state += 0x_60be_e2be_e120_fc15;
    186         __uint128_t tmp;
    187         tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d;
    188         uint64_t m1 = (tmp >> 64) ^ tmp;
    189         tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9;
    190         uint64_t m2 = (tmp >> 64) ^ tmp;
    191         return m2;
    192 } // wyhash64
    193 
    194 static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) {
    195         state = splitmix64( seed );                                                     // prime
    196 } // wyhash64_set_seed
    197 #endif // __SIZEOF_INT128__
    198116
    199117// https://prng.di.unimi.it/xoshiro256starstar.c
     
    208126
    209127#ifndef XOSHIRO256PP
    210 typedef struct { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;
     128typedef struct xoshiro256pp_t { uint64_t s[4]; } xoshiro256pp_t;
    211129#endif // ! XOSHIRO256PP
    212130
    213131static inline uint64_t xoshiro256pp( xoshiro256pp_t & rs ) with(rs) {
    214         inline uint64_t rotl( const uint64_t x, int k ) {
     132        inline uint64_t rotl(const uint64_t x, int k) {
    215133                return (x << k) | (x >> (64 - k));
    216134        } // rotl
    217135
    218         const uint64_t result = rotl( s0 + s3, 23 ) + s0;
    219         const uint64_t t = s1 << 17;
    220 
    221         s2 ^= s0;
    222         s3 ^= s1;
    223         s1 ^= s2;
    224         s0 ^= s3;
    225         s2 ^= t;
    226         s3 = rotl( s3, 45 );
     136        const uint64_t result = rotl( s[0] + s[3], 23 ) + s[0];
     137        const uint64_t t = s[1] << 17;
     138
     139        s[2] ^= s[0];
     140        s[3] ^= s[1];
     141        s[1] ^= s[2];
     142        s[0] ^= s[3];
     143        s[2] ^= t;
     144        s[3] = rotl( s[3], 45 );
    227145        return result;
    228146} // xoshiro256pp
    229147
    230 static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) {
    231     // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined.
    232     uint64_t seed1 = splitmix64( seed );                                // prime
    233     uint64_t seed2 = splitmix64( seed );
    234     uint64_t seed3 = splitmix64( seed );
    235     uint64_t seed4 = splitmix64( seed );
    236         state = (xoshiro256pp_t){ seed1, seed2, seed3, seed4 };
     148static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state,  uint64_t seed ) {
     149        state = (xoshiro256pp_t){ {seed, seed, seed, seed} };
     150        xoshiro256pp( state );
    237151} // xoshiro256pp_set_seed
    238152
     
    247161
    248162#ifndef XOSHIRO128PP
    249 typedef struct { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;
     163typedef struct xoshiro128pp_t { uint32_t s[4]; } xoshiro128pp_t;
    250164#endif // ! XOSHIRO128PP
    251165
     
    255169        } // rotl
    256170
    257         const uint32_t result = rotl( s0 + s3, 7 ) + s0;
    258         const uint32_t t = s1 << 9;
    259 
    260         s2 ^= s0;
    261         s3 ^= s1;
    262         s1 ^= s2;
    263         s0 ^= s3;
    264         s2 ^= t;
    265         s3 = rotl( s3, 11 );
     171        const uint32_t result = rotl( s[0] + s[3], 7 ) + s[0];
     172        const uint32_t t = s[1] << 9;
     173
     174        s[2] ^= s[0];
     175        s[3] ^= s[1];
     176        s[1] ^= s[2];
     177        s[0] ^= s[3];
     178        s[2] ^= t;
     179        s[3] = rotl( s[3], 11 );
    266180        return result;
    267181} // xoshiro128pp
    268182
    269183static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) {
    270     // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined.
    271     uint32_t seed1 = splitmix32( seed );                                // prime
    272     uint32_t seed2 = splitmix32( seed );
    273     uint32_t seed3 = splitmix32( seed );
    274     uint32_t seed4 = splitmix32( seed );
    275         state = (xoshiro128pp_t){ seed1, seed2, seed3, seed4 };
     184        state = (xoshiro128pp_t){ {seed, seed, seed, seed} };
     185        xoshiro128pp( state );                                                          // prime
    276186} // xoshiro128pp_set_seed
     187
     188#ifdef __SIZEOF_INT128__
     189        // Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is
     190        // returned (copied), and then compute and store the next random value.
     191        //--------------------------------------------------
     192        static inline uint64_t lehmer64( __uint128_t & state ) {
     193                __uint128_t ret = state;
     194                state *= 0xda942042e4dd58b5;
     195                return ret >> 64;
     196        } // lehmer64
     197
     198        static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) {
     199                state = seed;
     200                lehmer64( state );
     201        } // lehmer64_set_seed
     202
     203        //--------------------------------------------------
     204        static inline uint64_t wyhash64( uint64_t & state ) {
     205                uint64_t ret = state;
     206                state += 0x_60be_e2be_e120_fc15;
     207                __uint128_t tmp;
     208                tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d;
     209                uint64_t m1 = (tmp >> 64) ^ tmp;
     210                tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9;
     211                uint64_t m2 = (tmp >> 64) ^ tmp;
     212                return m2;
     213        } // wyhash64
     214
     215        static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) {
     216                state = seed;
     217                wyhash64( state );                                                              // prime
     218        } // wyhash64_set_seed
     219#endif // __SIZEOF_INT128__
    277220
    278221//--------------------------------------------------
     
    286229
    287230static inline void xorshift_13_7_17_set_seed( uint64_t & state, uint64_t seed ) {
    288         state = splitmix64( seed );                                                     // prime
     231        state = seed;
     232        xorshift_13_7_17( state );                                                      // prime
    289233} // xorshift_13_7_17_set_seed
    290234
     
    303247
    304248static inline void xorshift_6_21_7_set_seed( uint32_t & state, uint32_t seed ) {
    305     state = splitmix32( seed );                                                 // prime
     249        state = seed;
     250        xorshift_6_21_7( state );                                                       // prime
    306251} // xorshift_6_21_7_set_seed
    307252
     
    317262
    318263static inline void xorshift_12_25_27_set_seed( uint64_t & state, uint64_t seed ) {
    319         state = splitmix64( seed );                                                     // prime
     264        state = seed;
     265        xorshift_12_25_27( state );                                                     // prime
    320266} // xorshift_12_25_27_set_seed
    321267
     
    323269// The state must be seeded with a nonzero value.
    324270#ifndef KISS_64
    325 typedef struct { uint64_t z, w, jsr, jcong; } kiss_64_t;
     271typedef struct kiss_64_t { uint64_t z, w, jsr, jcong; } kiss_64_t;
    326272#endif // ! KISS_64
    327273
    328 static inline uint64_t kiss_64( kiss_64_t & rs ) with(rs) {
    329         kiss_64_t ret = rs;
     274static inline uint64_t kiss_64( kiss_64_t & state ) with(state) {
     275        kiss_64_t ret = state;
    330276        z = 36969 * (z & 65535) + (z >> 16);
    331277        w = 18000 * (w & 65535) + (w >> 16);
     278        jsr ^= (jsr << 17);
    332279        jsr ^= (jsr << 13);
    333         jsr ^= (jsr >> 17);
    334280        jsr ^= (jsr << 5);
    335281        jcong = 69069 * jcong + 1234567;
     
    337283} // kiss_64
    338284
    339 static inline void kiss_64_set_seed( kiss_64_t & rs, uint64_t seed ) with(rs) {
    340         z = 1; w = 1; jsr = 4; jcong = splitmix64( seed );      // prime
     285static inline void kiss_64_set_seed( kiss_64_t & state, uint64_t seed ) with(state) {
     286        z = 1; w = 1; jsr = 4; jcong = seed;
     287        kiss_64( state );                                                                       // prime
    341288} // kiss_64_set_seed
    342289
     
    344291// The state array must be initialized to non-zero in the first four words.
    345292#ifndef XORWOW
    346 typedef struct { uint32_t a, b, c, d, counter; } xorwow_t;
     293typedef struct xorwow_t { uint32_t a, b, c, d, counter; } xorwow_t;
    347294#endif // ! XORWOW
    348295
    349 static inline uint32_t xorwow( xorwow_t & rs ) with(rs) {
     296static inline uint32_t xorwow( xorwow_t & state ) with(state) {
    350297        // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs".
    351298        uint32_t ret = a + counter;
     
    365312} // xorwow
    366313
    367 static inline void xorwow_set_seed( xorwow_t & rs, uint32_t seed ) {
    368     // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined.
    369     uint32_t seed1 = splitmix32( seed );                                // prime
    370     uint32_t seed2 = splitmix32( seed );
    371     uint32_t seed3 = splitmix32( seed );
    372     uint32_t seed4 = splitmix32( seed );
    373         rs = (xorwow_t){ seed1, seed2, seed3, seed4, 0 };
     314static inline void xorwow_set_seed( xorwow_t & state, uint32_t seed ) {
     315        state = (xorwow_t){ seed, seed, seed, seed, 0 };
     316        xorwow( state );                                                                        // prime
    374317} // xorwow_set_seed
    375318
     
    377320// Used in __tls_rand_fwd
    378321#define M  (1_l64u << 48_l64u)
    379 #define A  (25_214_903_917_l64u)
    380 #define AI (18_446_708_753_438_544_741_l64u)
     322#define A  (25214903917_l64u)
     323#define AI (18446708753438544741_l64u)
    381324#define C  (11_l64u)
    382325#define D  (16_l64u)
    383326
    384327// Bi-directional LCG random-number generator
    385 static inline uint32_t LCGBI_fwd( uint64_t & rs ) {
    386         rs = (A * rs + C) & (M - 1);
    387         return rs >> D;
     328static inline uint32_t LCGBI_fwd( uint64_t & state ) {
     329        state = (A * state + C) & (M - 1);
     330        return state >> D;
    388331} // LCGBI_fwd
    389332
    390 static inline uint32_t LCGBI_bck( uint64_t & rs ) {
    391         unsigned int r = rs >> D;
    392         rs = AI * (rs - C) & (M - 1);
     333static inline uint32_t LCGBI_bck( uint64_t & state ) {
     334        unsigned int r = state >> D;
     335        state = AI * (state - C) & (M - 1);
    393336        return r;
    394337} // LCGBI_bck
  • libcfa/src/bits/weakso_locks.cfa

    r24d6572 r34b4268  
    1515// Update Count     :
    1616//
     17
    1718#include "bits/weakso_locks.hfa"
     19
    1820#pragma GCC visibility push(default)
    1921
     
    2527void unlock( blocking_lock & ) {}
    2628void on_notify( blocking_lock &, struct thread$ * ) {}
    27 size_t on_wait( blocking_lock &, void (*pp_fn)( void * ), void * pp_datum ) { return 0; }
     29size_t on_wait( blocking_lock & ) { return 0; }
    2830void on_wakeup( blocking_lock &, size_t ) {}
    2931size_t wait_count( blocking_lock & ) { return 0; }
    30 bool register_select( blocking_lock & this, select_node & node ) { return false; }
    31 bool unregister_select( blocking_lock & this, select_node & node ) { return false; }
    32 void on_selected( blocking_lock & this, select_node & node ) {}
    33 
  • libcfa/src/bits/weakso_locks.hfa

    r24d6572 r34b4268  
    2323#include "containers/list.hfa"
    2424
    25 struct select_node;
     25struct thread$;
    2626
    2727//-----------------------------------------------------------------------------
     
    3232
    3333        // List of blocked threads
    34         dlist( select_node ) blocked_threads;
     34        dlist( thread$ ) blocked_threads;
    3535
    3636        // Count of current blocked threads
     
    5757void unlock( blocking_lock & this ) OPTIONAL_THREAD;
    5858void on_notify( blocking_lock & this, struct thread$ * t ) OPTIONAL_THREAD;
    59 size_t on_wait( blocking_lock & this, void (*pp_fn)( void * ), void * pp_datum ) OPTIONAL_THREAD;
     59size_t on_wait( blocking_lock & this ) OPTIONAL_THREAD;
    6060void on_wakeup( blocking_lock & this, size_t ) OPTIONAL_THREAD;
    6161size_t wait_count( blocking_lock & this ) OPTIONAL_THREAD;
    62 bool register_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;
    63 bool unregister_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;
    64 void on_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;
    6562
    6663//----------
     
    7572static inline bool   try_lock ( multiple_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
    7673static inline void   unlock   ( multiple_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
    77 static inline size_t on_wait  ( multiple_acquisition_lock & this, void (*pp_fn)( void * ), void * pp_datum ) { return on_wait ( (blocking_lock &)this, pp_fn, pp_datum ); }
     74static inline size_t on_wait  ( multiple_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
    7875static inline void   on_wakeup( multiple_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    7976static inline void   on_notify( multiple_acquisition_lock & this, struct thread$ * t ){ on_notify( (blocking_lock &)this, t ); }
    80 static inline bool   register_select( multiple_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    81 static inline bool   unregister_select( multiple_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); }
    82 static inline void   on_selected( multiple_acquisition_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); }
  • libcfa/src/common.hfa

    r24d6572 r34b4268  
    3232} // extern "C"
    3333static inline __attribute__((always_inline)) {
    34         unsigned char abs( signed char v ) { return (int)abs( (int)v ); }
     34        unsigned char abs( signed char v ) { return abs( (int)v ); }
    3535        // use default C routine for int
    3636        unsigned long int abs( long int v ) { return labs( v ); }
     
    7070        unsigned int min( unsigned int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; }
    7171        long int min( long int v1, long int v2 ) { return v1 < v2 ? v1 : v2; }
    72         unsigned long int min( unsigned long int v1, unsigned long int v2 ) { return v1 < v2 ? v1 : v2; }
     72        unsigned long int min( unsigned long int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; }
    7373        long long int min( long long int v1, long long int v2 ) { return v1 < v2 ? v1 : v2; }
    74         unsigned long long int min( unsigned long long int v1, unsigned long long int v2 ) { return v1 < v2 ? v1 : v2; }
     74        unsigned long long int min( unsigned long long int v1, unsigned int v2 ) { return v1 < v2 ? v1 : v2; }
    7575        forall( T | { int ?<?( T, T ); } )                                      // generic
    7676        T min( T v1, T v2 ) { return v1 < v2 ? v1 : v2; }
  • libcfa/src/concurrency/clib/cfathread.cfa

    r24d6572 r34b4268  
    1616// #define EPOLL_FOR_SOCKETS
    1717
    18 #include <string.h>
    19 
    2018#include "fstream.hfa"
    2119#include "locks.hfa"
     
    2523#include "time.hfa"
    2624#include "stdlib.hfa"
    27 #include "iofwd.hfa"
     25
    2826#include "cfathread.h"
     27
     28extern "C" {
     29                #include <string.h>
     30                #include <errno.h>
     31}
    2932
    3033extern void ?{}(processor &, const char[], cluster &, thread$ *);
    3134extern "C" {
    32         extern void __cfactx_invoke_thread(void (*main)(void *), void * this);
     35      extern void __cfactx_invoke_thread(void (*main)(void *), void * this);
     36        extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
    3337}
    3438
     
    435439        // Mutex
    436440        struct cfathread_mutex {
    437                 exp_backoff_then_block_lock impl;
     441                linear_backoff_then_block_lock impl;
    438442        };
    439443        int cfathread_mutex_init(cfathread_mutex_t *restrict mut, const cfathread_mutexattr_t *restrict) __attribute__((nonnull (1))) { *mut = new(); return 0; }
     
    450454        // Condition
    451455        struct cfathread_condition {
    452                 condition_variable(exp_backoff_then_block_lock) impl;
     456                condition_variable(linear_backoff_then_block_lock) impl;
    453457        };
    454458        int cfathread_cond_init(cfathread_cond_t *restrict cond, const cfathread_condattr_t *restrict) __attribute__((nonnull (1))) { *cond = new(); return 0; }
     
    468472}
    469473
     474#include <iofwd.hfa>
     475
    470476extern "C" {
     477        #include <unistd.h>
     478        #include <sys/types.h>
     479        #include <sys/socket.h>
     480
    471481        //--------------------
    472482        // IO operations
     
    478488                , protocol);
    479489        }
    480         int cfathread_bind(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len) {
     490        int cfathread_bind(int socket, const struct sockaddr *address, socklen_t address_len) {
    481491                return bind(socket, address, address_len);
    482492        }
     
    486496        }
    487497
    488         int cfathread_accept(int socket, __SOCKADDR_ARG address, socklen_t *restrict address_len) {
     498        int cfathread_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {
    489499                #if defined(EPOLL_FOR_SOCKETS)
    490500                        int ret;
     
    503513        }
    504514
    505         int cfathread_connect(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len) {
     515        int cfathread_connect(int socket, const struct sockaddr *address, socklen_t address_len) {
    506516                #if defined(EPOLL_FOR_SOCKETS)
    507517                        int ret;
  • libcfa/src/concurrency/clib/cfathread.h

    r24d6572 r34b4268  
    99// Author           : Thierry Delisle
    1010// Created On       : Tue Sep 22 15:31:20 2020
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 13 23:48:40 2023
    13 // Update Count     : 7
     11// Last Modified By :
     12// Last Modified On :
     13// Update Count     :
    1414//
    1515
    16 #pragma once
    17 
    1816#if defined(__cforall) || defined(__cplusplus)
    19 #include <unistd.h>
    20 #include <errno.h>
    21 #include <sys/socket.h>
    22 
    2317extern "C" {
    2418#endif
     19        #include <asm/types.h>
     20        #include <errno.h>
     21        #include <unistd.h>
     22
     23
    2524        //--------------------
    2625        // Basic types
     
    7473        } cfathread_mutexattr_t;
    7574        typedef struct cfathread_mutex * cfathread_mutex_t;
    76         int cfathread_mutex_init(cfathread_mutex_t * restrict mut, const cfathread_mutexattr_t * restrict attr) __attribute__((nonnull (1)));
     75        int cfathread_mutex_init(cfathread_mutex_t *restrict mut, const cfathread_mutexattr_t *restrict attr) __attribute__((nonnull (1)));
    7776        int cfathread_mutex_destroy(cfathread_mutex_t *mut) __attribute__((nonnull (1)));
    7877        int cfathread_mutex_lock(cfathread_mutex_t *mut) __attribute__((nonnull (1)));
     
    9291        //--------------------
    9392        // IO operations
     93        struct sockaddr;
     94        struct msghdr;
    9495        int cfathread_socket(int domain, int type, int protocol);
    95         int cfathread_bind(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len);
     96        int cfathread_bind(int socket, const struct sockaddr *address, socklen_t address_len);
    9697        int cfathread_listen(int socket, int backlog);
    97         int cfathread_accept(int socket, __SOCKADDR_ARG address, socklen_t * restrict address_len);
    98         int cfathread_connect(int socket, __CONST_SOCKADDR_ARG address, socklen_t address_len);
     98        int cfathread_accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
     99        int cfathread_connect(int socket, const struct sockaddr *address, socklen_t address_len);
    99100        int cfathread_dup(int fildes);
    100101        int cfathread_close(int fildes);
  • libcfa/src/concurrency/coroutine.cfa

    r24d6572 r34b4268  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 16 15:34:46 2023
    13 // Update Count     : 24
     12// Last Modified On : Tue Dec 15 12:06:04 2020
     13// Update Count     : 23
    1414//
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819#include "coroutine.hfa"
  • libcfa/src/concurrency/coroutine.hfa

    r24d6572 r34b4268  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:31:42 2023
    13 // Update Count     : 13
     12// Last Modified On : Thu Jan  6 16:33:16 2022
     13// Update Count     : 12
    1414//
    1515
     
    3838// Anything that implements this trait can be resumed.
    3939// Anything that is resumed is a coroutine.
    40 forall( T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled(T)) )
    41 trait is_coroutine {
     40trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled(T))) {
    4241        void main(T & this);
    4342        coroutine$ * get_coroutine(T & this);
  • libcfa/src/concurrency/future.hfa

    r24d6572 r34b4268  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // concurrency/future.hfa --
     7// io/types.hfa --
    88//
    9 // Author           : Thierry Delisle & Peiran Hong & Colby Parsons
     9// Author           : Thierry Delisle & Peiran Hong
    1010// Created On       : Wed Jan 06 17:33:18 2021
    1111// Last Modified By :
     
    1818#include "bits/locks.hfa"
    1919#include "monitor.hfa"
    20 #include "select.hfa"
    21 #include "locks.hfa"
    22 
    23 //----------------------------------------------------------------------------
    24 // future
    25 // I don't use future_t here since I need to use a lock for this future
    26 //  since it supports multiple consumers
    27 //  future_t is lockfree and uses atomics which aren't needed given we use locks here
    28 forall( T ) {
    29     // enum { FUTURE_EMPTY = 0, FUTURE_FULFILLED = 1 }; // Enums seem to be broken so feel free to add this back afterwards
    30 
    31     // temporary enum replacement
    32     const int FUTURE_EMPTY = 0;
    33     const int FUTURE_FULFILLED = 1;
    34 
    35         struct future {
    36                 int state;
    37                 T result;
    38                 dlist( select_node ) waiters;
    39         futex_mutex lock;
    40         };
    41 
    42     struct future_node {
    43         inline select_node;
    44         T * my_result;
    45     };
    46 
    47         static inline {
    48 
    49         void ?{}( future_node(T) & this, thread$ * blocked_thread, T * my_result ) {
    50             ((select_node &)this){ blocked_thread };
    51             this.my_result = my_result;
    52         }
    53 
    54         void ?{}( future(T) & this ) {
    55                         this.waiters{};
    56             this.state = FUTURE_EMPTY;
    57             this.lock{};
    58                 }
    59 
    60                 // Reset future back to original state
    61                 void reset( future(T) & this ) with(this)
    62         {
    63             lock( lock );
    64             if( ! waiters`isEmpty )
    65                 abort("Attempting to reset a future with blocked waiters");
    66             state = FUTURE_EMPTY;
    67             unlock( lock );
    68         }
    69 
    70                 // check if the future is available
    71         // currently no mutual exclusion because I can't see when you need this call to be synchronous or protected
    72                 bool available( future(T) & this ) { return __atomic_load_n( &this.state, __ATOMIC_RELAXED ); }
    73 
    74 
    75         // memcpy wrapper to help copy values
    76         void copy_T( T & from, T & to ) {
    77             memcpy((void *)&to, (void *)&from, sizeof(T));
    78         }
    79 
    80         // internal helper to signal waiters off of the future
    81         void _internal_flush( future(T) & this ) with(this) {
    82             while( ! waiters`isEmpty ) {
    83                 if ( !__handle_waituntil_OR( waiters ) ) // handle special waituntil OR case
    84                     break; // if handle_OR returns false then waiters is empty so break
    85                 select_node &s = try_pop_front( waiters );
    86 
    87                 if ( s.clause_status == 0p ) // poke in result so that woken threads do not need to reacquire any locks
    88                     copy_T( result, *(((future_node(T) &)s).my_result) );
    89                
    90                 wake_one( waiters, s );
    91             }
    92         }
    93 
    94                 // Fulfil the future, returns whether or not someone was unblocked
    95                 bool fulfil( future(T) & this, T val ) with(this) {
    96             lock( lock );
    97             if( state != FUTURE_EMPTY )
    98                 abort("Attempting to fulfil a future that has already been fulfilled");
    99 
    100             copy_T( val, result );
    101 
    102             bool ret_val = ! waiters`isEmpty;
    103             state = FUTURE_FULFILLED;
    104                         _internal_flush( this );
    105             unlock( lock );
    106             return ret_val;
    107                 }
    108 
    109                 // Wait for the future to be fulfilled
    110                 // Also return whether the thread had to block or not
    111                 [T, bool] get( future(T) & this ) with( this ) {
    112             lock( lock );
    113             T ret_val;
    114             if( state == FUTURE_FULFILLED ) {
    115                 copy_T( result, ret_val );
    116                 unlock( lock );
    117                 return [ret_val, false];
    118             }
    119 
    120             future_node(T) node = { active_thread(), &ret_val };
    121             insert_last( waiters, ((select_node &)node) );
    122             unlock( lock );
    123             park( );
    124 
    125                         return [ret_val, true];
    126                 }
    127 
    128                 // Wait for the future to be fulfilled
    129                 T get( future(T) & this ) {
    130                         [T, bool] tt;
    131                         tt = get(this);
    132                         return tt.0;
    133                 }
    134 
    135         // Gets value if it is available and returns [ val, true ]
    136         // otherwise returns [ default_val, false]
    137         // will not block
    138         [T, bool] try_get( future(T) & this ) with(this) {
    139             lock( lock );
    140             T ret_val;
    141             if( state == FUTURE_FULFILLED ) {
    142                 copy_T( result, ret_val );
    143                 unlock( lock );
    144                 return [ret_val, true];
    145             }
    146             unlock( lock );
    147            
    148             return [ret_val, false];
    149         }
    150 
    151         bool register_select( future(T) & this, select_node & s ) with(this) {
    152             lock( lock );
    153 
    154             // check if we can complete operation. If so race to establish winner in special OR case
    155             if ( !s.park_counter && state != FUTURE_EMPTY ) {
    156                 if ( !__make_select_node_available( s ) ) { // we didn't win the race so give up on registering
    157                     unlock( lock );
    158                     return false;
    159                 }
    160             }
    161 
    162             // future not ready -> insert select node and return
    163             if( state == FUTURE_EMPTY ) {
    164                 insert_last( waiters, s );
    165                 unlock( lock );
    166                 return false;
    167             }
    168 
    169             __make_select_node_available( s );
    170             unlock( lock );
    171             return true;
    172         }
    173 
    174         bool unregister_select( future(T) & this, select_node & s ) with(this) {
    175             if ( ! s`isListed ) return false;
    176             lock( lock );
    177             if ( s`isListed ) remove( s );
    178             unlock( lock );
    179             return false;
    180         }
    181                
    182         void on_selected( future(T) & this, select_node & node ) {}
    183         }
    184 }
    185 
    186 //--------------------------------------------------------------------------------------------------------
    187 // These futures below do not support select statements so they may not have as many features as 'future'
    188 //  however the 'single_future' is cheap and cheerful and is most likely more performant than 'future'
    189 //  since it uses raw atomics and no locks
    190 //
    191 // As far as 'multi_future' goes I can't see many use cases as it will be less performant than 'future'
    192 //  since it is monitor based and also is not compatible with select statements
    193 //--------------------------------------------------------------------------------------------------------
    19420
    19521forall( T ) {
    196         struct single_future {
     22        struct future {
    19723                inline future_t;
    19824                T result;
     
    20127        static inline {
    20228                // Reset future back to original state
    203                 void reset(single_future(T) & this) { reset( (future_t&)this ); }
     29                void reset(future(T) & this) { reset( (future_t&)this ); }
    20430
    20531                // check if the future is available
    206                 bool available( single_future(T) & this ) { return available( (future_t&)this ); }
     32                bool available( future(T) & this ) { return available( (future_t&)this ); }
    20733
    20834                // Mark the future as abandoned, meaning it will be deleted by the server
    20935                // This doesn't work beause of the potential need for a destructor
    210                 void abandon( single_future(T) & this );
     36                void abandon( future(T) & this );
    21137
    21238                // Fulfil the future, returns whether or not someone was unblocked
    213                 thread$ * fulfil( single_future(T) & this, T result ) {
     39                thread$ * fulfil( future(T) & this, T result ) {
    21440                        this.result = result;
    21541                        return fulfil( (future_t&)this );
     
    21844                // Wait for the future to be fulfilled
    21945                // Also return whether the thread had to block or not
    220                 [T, bool] wait( single_future(T) & this ) {
     46                [T, bool] wait( future(T) & this ) {
    22147                        bool r = wait( (future_t&)this );
    22248                        return [this.result, r];
     
    22450
    22551                // Wait for the future to be fulfilled
    226                 T wait( single_future(T) & this ) {
     52                T wait( future(T) & this ) {
    22753                        [T, bool] tt;
    22854                        tt = wait(this);
  • libcfa/src/concurrency/invoke.h

    r24d6572 r34b4268  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar 14 13:39:31 2023
    13 // Update Count     : 59
    14 //
    15 
    16 // No not use #pragma once was this file is included twice in some places. It has its own guard system.
     12// Last Modified On : Tue Nov 29 20:42:21 2022
     13// Update Count     : 56
     14//
    1715
    1816#include "bits/containers.hfa"
     
    217215                struct __thread_user_link cltr_link;
    218216
     217                // used to store state between clh lock/unlock
     218                volatile bool * clh_prev;
     219
     220                // used to point to this thd's current clh node
     221                volatile bool * clh_node;
     222
    219223                struct processor * last_proc;
    220 
    221         // ptr used during handover between blocking lists to allow for stack allocation of intrusive nodes
    222         // main use case is wait-morphing to allow a different node to be used to block on condvar vs lock
    223         void * link_node;
    224224
    225225                PRNG_STATE_T random_state;                                              // fast random numbers
  • libcfa/src/concurrency/io.cfa

    r24d6572 r34b4268  
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819#if defined(__CFA_DEBUG__)
     
    8485        static io_context$ * __ioarbiter_allocate( io_arbiter$ & this, __u32 idxs[], __u32 want );
    8586        static void __ioarbiter_submit( io_context$ * , __u32 idxs[], __u32 have, bool lazy );
    86         static void __ioarbiter_flush ( io_context$ &, bool kernel );
     87        static void __ioarbiter_flush ( io_context$ & );
    8788        static inline void __ioarbiter_notify( io_context$ & ctx );
    8889//=============================================================================================
     
    9394        extern void __kernel_unpark( thread$ * thrd, unpark_hint );
    9495
    95         static inline void __post(oneshot & this, bool kernel, unpark_hint hint) {
    96                 thread$ * t = post( this, false );
    97                 if(kernel) __kernel_unpark( t, hint );
    98                 else unpark( t, hint );
    99         }
    100 
    101         // actual system call of io uring
    102         // wrap so everything that needs to happen around it is always done
    103         //   i.e., stats, book keeping, sqe reclamation, etc.
    10496        static void ioring_syscsll( struct io_context$ & ctx, unsigned int min_comp, unsigned int flags ) {
    10597                __STATS__( true, io.calls.flush++; )
    10698                int ret;
    10799                for() {
    108                         // do the system call in a loop, repeat on interrupts
    109100                        ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, min_comp, flags, (sigset_t *)0p, _NSIG / 8);
    110101                        if( ret < 0 ) {
     
    129120                /* paranoid */ verify( ctx.sq.to_submit >= ret );
    130121
    131                 // keep track of how many still need submitting
    132                 __atomic_fetch_sub(&ctx.sq.to_submit, ret, __ATOMIC_SEQ_CST);
     122                ctx.sq.to_submit -= ret;
    133123
    134124                /* paranoid */ verify( ctx.sq.to_submit <= *ctx.sq.num );
     
    139129                /* paranoid */ verify( ! __preemption_enabled() );
    140130
    141                 // mark that there is no pending io left
    142131                __atomic_store_n(&ctx.proc->io.pending, false, __ATOMIC_RELAXED);
    143132        }
    144133
    145         // try to acquire an io context for draining, helping means we never *need* to drain, we can always do it later
    146134        static bool try_acquire( io_context$ * ctx ) __attribute__((nonnull(1))) {
    147135                /* paranoid */ verify( ! __preemption_enabled() );
     
    150138
    151139                {
    152                         // if there is nothing to drain there is no point in acquiring anything
    153140                        const __u32 head = *ctx->cq.head;
    154141                        const __u32 tail = *ctx->cq.tail;
     
    157144                }
    158145
    159                 // try a simple spinlock acquire, it's likely there are completions to drain
    160                 if(!__atomic_try_acquire(&ctx->cq.try_lock)) {
    161                         // some other processor already has it
     146                // Drain the queue
     147                if(!__atomic_try_acquire(&ctx->cq.lock)) {
    162148                        __STATS__( false, io.calls.locked++; )
    163149                        return false;
    164150                }
    165151
    166                 // acquired!!
    167152                return true;
    168153        }
    169154
    170         // actually drain the completion
    171155        static bool __cfa_do_drain( io_context$ * ctx, cluster * cltr ) __attribute__((nonnull(1, 2))) {
    172156                /* paranoid */ verify( ! __preemption_enabled() );
    173157                /* paranoid */ verify( ready_schedule_islocked() );
    174                 /* paranoid */ verify( ctx->cq.try_lock == true );
    175 
    176                 // get all the invariants and initial state
     158                /* paranoid */ verify( ctx->cq.lock == true );
     159
    177160                const __u32 mask = *ctx->cq.mask;
    178161                const __u32 num  = *ctx->cq.num;
     
    183166                for() {
    184167                        // re-read the head and tail in case it already changed.
    185                         // count the difference between the two
    186168                        const __u32 head = *ctx->cq.head;
    187169                        const __u32 tail = *ctx->cq.tail;
     
    189171                        __STATS__( false, io.calls.drain++; io.calls.completed += count; )
    190172
    191                         // for everything between head and tail, drain it
    192173                        for(i; count) {
    193174                                unsigned idx = (head + i) & mask;
     
    196177                                /* paranoid */ verify(&cqe);
    197178
    198                                 // find the future in the completion
    199179                                struct io_future_t * future = (struct io_future_t *)(uintptr_t)cqe.user_data;
    200180                                // __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", &cqe, cqe.res, future );
    201181
    202                                 // don't directly fulfill the future, preemption is disabled so we need to use kernel_unpark
    203182                                __kernel_unpark( fulfil( *future, cqe.res, false ), UNPARK_LOCAL );
    204183                        }
    205184
    206                         // update the timestamps accordingly
    207                         // keep a local copy so we can update the relaxed copy
    208185                        ts_next = ctx->cq.ts = rdtscl();
    209186
     
    213190                        ctx->proc->idle_wctx.drain_time = ts_next;
    214191
    215                         // we finished draining the completions... unless the ring buffer was full and there are more secret completions in the kernel.
    216192                        if(likely(count < num)) break;
    217193
    218                         // the ring buffer was full, there could be more stuff in the kernel.
    219194                        ioring_syscsll( *ctx, 0, IORING_ENTER_GETEVENTS);
    220195                }
     
    224199                /* paranoid */ verify( ! __preemption_enabled() );
    225200
    226                 // everything is drained, we can release the lock
    227                 __atomic_unlock(&ctx->cq.try_lock);
    228 
    229                 // update the relaxed timestamp
     201                __atomic_unlock(&ctx->cq.lock);
     202
    230203                touch_tsc( cltr->sched.io.tscs, ctx->cq.id, ts_prev, ts_next, false );
    231204
     
    233206        }
    234207
    235         // call from a processor to flush
    236         // contains all the bookkeeping a proc must do, not just the barebones flushing logic
    237         void __cfa_do_flush( io_context$ & ctx, bool kernel ) {
    238                 /* paranoid */ verify( ! __preemption_enabled() );
    239 
    240                 // flush any external requests
    241                 ctx.sq.last_external = false; // clear the external bit, the arbiter will reset it if needed
    242                 __ioarbiter_flush( ctx, kernel );
    243 
    244                 // if submitting must be submitted, do the system call
    245                 if(ctx.sq.to_submit != 0) {
    246                         ioring_syscsll(ctx, 0, 0);
    247                 }
    248         }
    249 
    250         // call from a processor to drain
    251         // contains all the bookkeeping a proc must do, not just the barebones draining logic
    252208        bool __cfa_io_drain( struct processor * proc ) {
    253209                bool local = false;
    254210                bool remote = false;
    255211
    256                 // make sure no ones creates/destroys io contexts
    257212                ready_schedule_lock();
    258213
     
    262217                /* paranoid */ verify( ctx );
    263218
    264                 // Help if needed
    265219                with(cltr->sched) {
    266220                        const size_t ctxs_count = io.count;
     
    276230                        const unsigned long long ctsc = rdtscl();
    277231
    278                         // only help once every other time
    279                         // pick a target when not helping
    280232                        if(proc->io.target == UINT_MAX) {
    281233                                uint64_t chaos = __tls_rand();
    282                                 // choose who to help and whether to accept helping far processors
    283234                                unsigned ext = chaos & 0xff;
    284235                                unsigned other  = (chaos >> 8) % (ctxs_count);
    285236
    286                                 // if the processor is on the same cache line or is lucky ( 3 out of 256 odds ) help it
    287237                                if(ext < 3 || __atomic_load_n(&caches[other / __shard_factor.io].id, __ATOMIC_RELAXED) == this_cache) {
    288238                                        proc->io.target = other;
     
    290240                        }
    291241                        else {
    292                                 // a target was picked last time, help it
    293242                                const unsigned target = proc->io.target;
    294243                                /* paranoid */ verify( io.tscs[target].t.tv != ULLONG_MAX );
    295                                 // make sure the target hasn't stopped existing since last time
    296244                                HELP: if(target < ctxs_count) {
    297                                         // calculate it's age and how young it could be before we give up on helping
    298245                                        const __readyQ_avg_t cutoff = calc_cutoff(ctsc, ctx->cq.id, ctxs_count, io.data, io.tscs, __shard_factor.io, false);
    299246                                        const __readyQ_avg_t age = moving_average(ctsc, io.tscs[target].t.tv, io.tscs[target].t.ma, false);
    300247                                        __cfadbg_print_safe(io, "Kernel I/O: Help attempt on %u from %u, age %'llu vs cutoff %'llu, %s\n", target, ctx->cq.id, age, cutoff, age > cutoff ? "yes" : "no");
    301                                         // is the target older than the cutoff, recall 0 is oldest and bigger ints are younger
    302248                                        if(age <= cutoff) break HELP;
    303249
    304                                         // attempt to help the submission side
    305                                         __cfa_do_flush( *io.data[target], true );
    306 
    307                                         // attempt to help the completion side
    308                                         if(!try_acquire(io.data[target])) break HELP; // already acquire no help needed
    309 
    310                                         // actually help
     250                                        if(!try_acquire(io.data[target])) break HELP;
     251
    311252                                        if(!__cfa_do_drain( io.data[target], cltr )) break HELP;
    312253
    313                                         // track we did help someone
    314254                                        remote = true;
    315255                                        __STATS__( true, io.calls.helped++; )
    316256                                }
    317 
    318                                 // reset the target
    319257                                proc->io.target = UINT_MAX;
    320258                        }
    321259                }
     260
    322261
    323262                // Drain the local queue
     
    331270
    332271                ready_schedule_unlock();
    333 
    334                 // return true if some completion entry, local or remote, was drained
    335272                return local || remote;
    336273        }
    337274
    338 
    339 
    340         // call from a processor to flush
    341         // contains all the bookkeeping a proc must do, not just the barebones flushing logic
    342275        bool __cfa_io_flush( struct processor * proc ) {
    343276                /* paranoid */ verify( ! __preemption_enabled() );
     
    345278                /* paranoid */ verify( proc->io.ctx );
    346279
    347                 __cfa_do_flush( *proc->io.ctx, false );
    348 
    349                 // also drain since some stuff will immediately complete
     280                io_context$ & ctx = *proc->io.ctx;
     281
     282                __ioarbiter_flush( ctx );
     283
     284                if(ctx.sq.to_submit != 0) {
     285                        ioring_syscsll(ctx, 0, 0);
     286
     287                }
     288
    350289                return __cfa_io_drain( proc );
    351290        }
     
    454393        //=============================================================================================
    455394        // submission
    456         // barebones logic to submit a group of sqes
    457         static inline void __submit_only( struct io_context$ * ctx, __u32 idxs[], __u32 have, bool lock) {
    458                 if(!lock)
    459                         lock( ctx->ext_sq.lock __cfaabi_dbg_ctx2 );
     395        static inline void __submit_only( struct io_context$ * ctx, __u32 idxs[], __u32 have) {
    460396                // We can proceed to the fast path
    461397                // Get the right objects
     
    472408                // Make the sqes visible to the submitter
    473409                __atomic_store_n(sq.kring.tail, tail + have, __ATOMIC_RELEASE);
    474                 __atomic_fetch_add(&sq.to_submit, have, __ATOMIC_SEQ_CST);
    475 
    476                 // set the bit to mark things need to be flushed
     410                sq.to_submit += have;
     411
    477412                __atomic_store_n(&ctx->proc->io.pending, true, __ATOMIC_RELAXED);
    478413                __atomic_store_n(&ctx->proc->io.dirty  , true, __ATOMIC_RELAXED);
    479 
    480                 if(!lock)
    481                         unlock( ctx->ext_sq.lock );
    482         }
    483 
    484         // submission logic + maybe flushing
     414        }
     415
    485416        static inline void __submit( struct io_context$ * ctx, __u32 idxs[], __u32 have, bool lazy) {
    486417                __sub_ring_t & sq = ctx->sq;
    487                 __submit_only(ctx, idxs, have, false);
     418                __submit_only(ctx, idxs, have);
    488419
    489420                if(sq.to_submit > 30) {
     
    497428        }
    498429
    499         // call from a processor to flush
    500         // might require arbitration if the thread was migrated after the allocation
    501430        void cfa_io_submit( struct io_context$ * inctx, __u32 idxs[], __u32 have, bool lazy ) __attribute__((nonnull (1))) libcfa_public {
    502431                // __cfadbg_print_safe(io, "Kernel I/O : attempting to submit %u (%s)\n", have, lazy ? "lazy" : "eager");
     
    512441                if( ctx == inctx )              // We have the right instance?
    513442                {
    514                         // yes! fast submit
    515443                        __submit(ctx, idxs, have, lazy);
    516444
     
    579507                __atomic_store_n(&ctx.sq.free_ring.tail, ftail + count, __ATOMIC_SEQ_CST);
    580508
    581                 // notify the allocator that new allocations can be made
    582509                __ioarbiter_notify(ctx);
    583510
     
    630557        }
    631558
    632         // notify the arbiter that new allocations are available
    633559        static void __ioarbiter_notify( io_arbiter$ & this, io_context$ * ctx ) {
    634560                /* paranoid */ verify( !empty(this.pending.queue) );
    635                 /* paranoid */ verify( __preemption_enabled() );
    636 
    637                 // mutual exclusion is needed
     561
    638562                lock( this.pending.lock __cfaabi_dbg_ctx2 );
    639563                {
    640                         __cfadbg_print_safe(io, "Kernel I/O : notifying\n");
    641 
    642                         // as long as there are pending allocations try to satisfy them
    643                         // for simplicity do it in FIFO order
    644564                        while( !empty(this.pending.queue) ) {
    645                                 // get first pending allocs
     565                                __cfadbg_print_safe(io, "Kernel I/O : notifying\n");
    646566                                __u32 have = ctx->sq.free_ring.tail - ctx->sq.free_ring.head;
    647567                                __pending_alloc & pa = (__pending_alloc&)head( this.pending.queue );
    648568
    649                                 // check if we have enough to satisfy the request
    650569                                if( have > pa.want ) goto DONE;
    651 
    652                                 // if there are enough allocations it means we can drop the request
    653570                                drop( this.pending.queue );
    654571
    655572                                /* paranoid */__attribute__((unused)) bool ret =
    656573
    657                                 // actually do the alloc
    658574                                __alloc(ctx, pa.idxs, pa.want);
    659575
    660576                                /* paranoid */ verify( ret );
    661577
    662                                 // write out which context statisfied the request and post
    663                                 // this
    664578                                pa.ctx = ctx;
     579
    665580                                post( pa.waitctx );
    666581                        }
     
    670585                }
    671586                unlock( this.pending.lock );
    672 
    673                 /* paranoid */ verify( __preemption_enabled() );
    674         }
    675 
    676         // short hand to avoid the mutual exclusion of the pending is empty regardless
     587        }
     588
    677589        static void __ioarbiter_notify( io_context$ & ctx ) {
    678                 if(empty( ctx.arbiter->pending )) return;
    679                 __ioarbiter_notify( *ctx.arbiter, &ctx );
    680         }
    681 
    682         // Submit from outside the local processor: append to the outstanding list
     590                if(!empty( ctx.arbiter->pending )) {
     591                        __ioarbiter_notify( *ctx.arbiter, &ctx );
     592                }
     593        }
     594
     595        // Simply append to the pending
    683596        static void __ioarbiter_submit( io_context$ * ctx, __u32 idxs[], __u32 have, bool lazy ) {
    684597                __cfadbg_print_safe(io, "Kernel I/O : submitting %u from the arbiter to context %u\n", have, ctx->fd);
     
    686599                __cfadbg_print_safe(io, "Kernel I/O : waiting to submit %u\n", have);
    687600
    688                 // create the intrusive object to append
    689601                __external_io ei;
    690602                ei.idxs = idxs;
     
    692604                ei.lazy = lazy;
    693605
    694                 // enqueue the io
    695606                bool we = enqueue(ctx->ext_sq, (__outstanding_io&)ei);
    696607
    697                 // mark pending
    698608                __atomic_store_n(&ctx->proc->io.pending, true, __ATOMIC_SEQ_CST);
    699609
    700                 // if this is the first to be enqueued, signal the processor in an attempt to speed up flushing
    701                 // if it's not the first enqueue, a signal is already in transit
    702610                if( we ) {
    703611                        sigval_t value = { PREEMPT_IO };
    704612                        __cfaabi_pthread_sigqueue(ctx->proc->kernel_thread, SIGUSR1, value);
    705                         __STATS__( false, io.flush.signal += 1; )
    706                 }
    707                 __STATS__( false, io.submit.extr += 1; )
    708 
    709                 // to avoid dynamic allocation/memory reclamation headaches, wait for it to have been submitted
     613                }
     614
    710615                wait( ei.waitctx );
    711616
     
    713618        }
    714619
    715         // flush the io arbiter: move all external io operations to the submission ring
    716         static void __ioarbiter_flush( io_context$ & ctx, bool kernel ) {
    717                 // if there are no external operations just return
    718                 if(empty( ctx.ext_sq )) return;
    719 
    720                 // stats and logs
    721                 __STATS__( false, io.flush.external += 1; )
    722                 __cfadbg_print_safe(io, "Kernel I/O : arbiter flushing\n");
    723 
    724                 // this can happen from multiple processors, mutual exclusion is needed
    725                 lock( ctx.ext_sq.lock __cfaabi_dbg_ctx2 );
    726                 {
    727                         // pop each operation one at a time.
    728                         // There is no wait morphing because of the io sq ring
    729                         while( !empty(ctx.ext_sq.queue) ) {
    730                                 // drop the element from the queue
    731                                 __external_io & ei = (__external_io&)drop( ctx.ext_sq.queue );
    732 
    733                                 // submit it
    734                                 __submit_only(&ctx, ei.idxs, ei.have, true);
    735 
    736                                 // wake the thread that was waiting on it
    737                                 // since this can both be called from kernel and user, check the flag before posting
    738                                 __post( ei.waitctx, kernel, UNPARK_LOCAL );
     620        static void __ioarbiter_flush( io_context$ & ctx ) {
     621                if(!empty( ctx.ext_sq )) {
     622                        __STATS__( false, io.flush.external += 1; )
     623
     624                        __cfadbg_print_safe(io, "Kernel I/O : arbiter flushing\n");
     625
     626                        lock( ctx.ext_sq.lock __cfaabi_dbg_ctx2 );
     627                        {
     628                                while( !empty(ctx.ext_sq.queue) ) {
     629                                        __external_io & ei = (__external_io&)drop( ctx.ext_sq.queue );
     630
     631                                        __submit_only(&ctx, ei.idxs, ei.have);
     632
     633                                        post( ei.waitctx );
     634                                }
     635
     636                                ctx.ext_sq.empty = true;
    739637                        }
    740 
    741                         // mark the queue as empty
    742                         ctx.ext_sq.empty = true;
    743                         ctx.sq.last_external = true;
    744                 }
    745                 unlock(ctx.ext_sq.lock );
    746         }
    747 
    748         extern "C" {
    749                 // debug functions used for gdb
    750                 // io_uring doesn't yet support gdb soe the kernel-shared data structures aren't viewable in gdb
    751                 // these functions read the data that gdb can't and should be removed once the support is added
    752                 static __u32 __cfagdb_cq_head( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->cq.head; }
    753                 static __u32 __cfagdb_cq_tail( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->cq.tail; }
    754                 static __u32 __cfagdb_cq_mask( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->cq.mask; }
    755                 static __u32 __cfagdb_sq_head( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->sq.kring.head; }
    756                 static __u32 __cfagdb_sq_tail( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->sq.kring.tail; }
    757                 static __u32 __cfagdb_sq_mask( io_context$ * ctx ) __attribute__((nonnull(1),used,noinline)) { return *ctx->sq.mask; }
    758 
    759                 // fancier version that reads an sqe and copies it out.
    760                 static struct io_uring_sqe __cfagdb_sq_at( io_context$ * ctx, __u32 at ) __attribute__((nonnull(1),used,noinline)) {
    761                         __u32 ax = at & *ctx->sq.mask;
    762                         __u32 ix = ctx->sq.kring.array[ax];
    763                         return ctx->sq.sqes[ix];
     638                        unlock(ctx.ext_sq.lock );
    764639                }
    765640        }
  • libcfa/src/concurrency/io/call.cfa.in

    r24d6572 r34b4268  
    3131Prelude = """#define __cforall_thread__
    3232
    33 #include <unistd.h>
    34 #include <errno.h>
    35 #include <sys/socket.h>
    36 #include <time.hfa>
    37 
    3833#include "bits/defs.hfa"
    3934#include "kernel.hfa"
     
    4843        #include <assert.h>
    4944        #include <stdint.h>
     45        #include <errno.h>
    5046        #include <linux/io_uring.h>
     47
    5148        #include "kernel/fwd.hfa"
    5249
     
    8582// I/O Forwards
    8683//=============================================================================================
     84#include <time.hfa>
     85
     86// Some forward declarations
     87#include <errno.h>
     88#include <unistd.h>
    8789
    8890extern "C" {
     91        #include <asm/types.h>
     92        #include <sys/socket.h>
     93        #include <sys/syscall.h>
     94
    8995#if defined(CFA_HAVE_PREADV2)
    9096        struct iovec;
    91         extern ssize_t preadv2 (int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags);
     97        extern ssize_t preadv2 (int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
    9298#endif
    9399#if defined(CFA_HAVE_PWRITEV2)
    94100        struct iovec;
    95         extern ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags);
     101        extern ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
    96102#endif
    97103
     
    108114        struct msghdr;
    109115        struct sockaddr;
    110         extern ssize_t sendmsg(int sockfd, const struct msghdr * msg, int flags);
    111         extern ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags);
    112         extern ssize_t send(int sockfd, const void * buf, size_t len, int flags);
    113         extern ssize_t recv(int sockfd, void * buf, size_t len, int flags);
     116        extern ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
     117        extern ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
     118        extern ssize_t send(int sockfd, const void *buf, size_t len, int flags);
     119        extern ssize_t recv(int sockfd, void *buf, size_t len, int flags);
     120        extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
     121        extern int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    114122
    115123        extern int fallocate(int fd, int mode, off_t offset, off_t len);
    116124        extern int posix_fadvise(int fd, off_t offset, off_t len, int advice);
    117         extern int madvise(void * addr, size_t length, int advice);
    118 
    119         extern int openat(int dirfd, const char * pathname, int flags, mode_t mode);
     125        extern int madvise(void *addr, size_t length, int advice);
     126
     127        extern int openat(int dirfd, const char *pathname, int flags, mode_t mode);
    120128        extern int close(int fd);
    121129
    122         extern ssize_t read (int fd, void * buf, size_t count);
     130        extern ssize_t read (int fd, void *buf, size_t count);
    123131
    124132        struct epoll_event;
    125         extern int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event);
    126 
    127         extern ssize_t splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags);
     133        extern int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
     134
     135        extern ssize_t splice(int fd_in, __off64_t *off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags);
    128136        extern ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);
    129137}
     
    224232calls = [
    225233        # CFA_HAVE_IORING_OP_READV
    226         Call('READV', 'ssize_t preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', {
     234        Call('READV', 'ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)', {
    227235                'fd'  : 'fd',
    228                 'addr': '(typeof(sqe->addr))iov',
     236                'off' : 'offset',
     237                'addr': '(uintptr_t)iov',
    229238                'len' : 'iovcnt',
    230                 'off' : 'offset',
    231                 'rw_flags' : 'flags'
    232239        }, define = 'CFA_HAVE_PREADV2'),
    233240        # CFA_HAVE_IORING_OP_WRITEV
    234         Call('WRITEV', 'ssize_t pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags)', {
     241        Call('WRITEV', 'ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)', {
    235242                'fd'  : 'fd',
    236                 'addr': '(typeof(sqe->addr))iov',
    237                 'len' : 'iovcnt',
    238243                'off' : 'offset',
    239                 'rw_flags' : 'flags'
     244                'addr': '(uintptr_t)iov',
     245                'len' : 'iovcnt'
    240246        }, define = 'CFA_HAVE_PWRITEV2'),
    241247        # CFA_HAVE_IORING_OP_FSYNC
     
    244250        }),
    245251        # CFA_HAVE_IORING_OP_EPOLL_CTL
    246         Call('EPOLL_CTL', 'int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event)', {
     252        Call('EPOLL_CTL', 'int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)', {
    247253                'fd': 'epfd',
     254                'addr': 'fd',
    248255                'len': 'op',
    249                 'addr': 'fd',
    250                 'off': '(typeof(sqe->off))event'
     256                'off': '(uintptr_t)event'
    251257        }),
    252258        # CFA_HAVE_IORING_OP_SYNC_FILE_RANGE
     
    258264        }),
    259265        # CFA_HAVE_IORING_OP_SENDMSG
    260         Call('SENDMSG', 'ssize_t sendmsg(int sockfd, const struct msghdr * msg, int flags)', {
    261                 'fd': 'sockfd',
    262                 'addr': '(typeof(sqe->addr))(struct msghdr *)msg',
     266        Call('SENDMSG', 'ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)', {
     267                'fd': 'sockfd',
     268                'addr': '(uintptr_t)(struct msghdr *)msg',
    263269                'len': '1',
    264270                'msg_flags': 'flags'
    265271        }),
    266272        # CFA_HAVE_IORING_OP_RECVMSG
    267         Call('RECVMSG', 'ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags)', {
    268                 'fd': 'sockfd',
    269                 'addr': '(typeof(sqe->addr))(struct msghdr *)msg',
     273        Call('RECVMSG', 'ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)', {
     274                'fd': 'sockfd',
     275                'addr': '(uintptr_t)(struct msghdr *)msg',
    270276                'len': '1',
    271277                'msg_flags': 'flags'
    272278        }),
    273279        # CFA_HAVE_IORING_OP_SEND
    274         Call('SEND', 'ssize_t send(int sockfd, const void * buf, size_t len, int flags)', {
    275                 'fd': 'sockfd',
    276                 'addr': '(typeof(sqe->addr))buf',
     280        Call('SEND', 'ssize_t send(int sockfd, const void *buf, size_t len, int flags)', {
     281                'fd': 'sockfd',
     282                'addr': '(uintptr_t)buf',
    277283                'len': 'len',
    278284                'msg_flags': 'flags'
    279285        }),
    280286        # CFA_HAVE_IORING_OP_RECV
    281         Call('RECV', 'ssize_t recv(int sockfd, void * buf, size_t len, int flags)', {
    282                 'fd': 'sockfd',
    283                 'addr': '(typeof(sqe->addr))buf',
     287        Call('RECV', 'ssize_t recv(int sockfd, void *buf, size_t len, int flags)', {
     288                'fd': 'sockfd',
     289                'addr': '(uintptr_t)buf',
    284290                'len': 'len',
    285291                'msg_flags': 'flags'
    286292        }),
    287293        # CFA_HAVE_IORING_OP_ACCEPT
    288         Call('ACCEPT', 'int accept4(int sockfd, __SOCKADDR_ARG addr, socklen_t * restrict addrlen, int flags)', {
    289                 'fd': 'sockfd',
    290                 'addr': '(typeof(sqe->addr))&addr',
    291                 'addr2': '(typeof(sqe->addr2))addrlen',
     294        Call('ACCEPT', 'int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)', {
     295                'fd': 'sockfd',
     296                'addr': '(uintptr_t)addr',
     297                'addr2': '(uintptr_t)addrlen',
    292298                'accept_flags': 'flags'
    293299        }),
    294300        # CFA_HAVE_IORING_OP_CONNECT
    295         Call('CONNECT', 'int connect(int sockfd, __CONST_SOCKADDR_ARG addr, socklen_t addrlen)', {
    296                 'fd': 'sockfd',
    297                 'addr': '(typeof(sqe->addr))&addr',
     301        Call('CONNECT', 'int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)', {
     302                'fd': 'sockfd',
     303                'addr': '(uintptr_t)addr',
    298304                'off': 'addrlen'
    299305        }),
     
    301307        Call('FALLOCATE', 'int fallocate(int fd, int mode, off_t offset, off_t len)', {
    302308                'fd': 'fd',
     309                'addr': '(uintptr_t)len',
    303310                'len': 'mode',
    304                 'off': 'offset',
    305                 'addr': 'len'
     311                'off': 'offset'
    306312        }),
    307313        # CFA_HAVE_IORING_OP_FADVISE
     
    313319        }),
    314320        # CFA_HAVE_IORING_OP_MADVISE
    315         Call('MADVISE', 'int madvise(void * addr, size_t length, int advice)', {
    316                 'addr': '(typeof(sqe->addr))addr',
     321        Call('MADVISE', 'int madvise(void *addr, size_t length, int advice)', {
     322                'addr': '(uintptr_t)addr',
    317323                'len': 'length',
    318324                'fadvise_advice': 'advice'
    319325        }),
    320326        # CFA_HAVE_IORING_OP_OPENAT
    321         Call('OPENAT', 'int openat(int dirfd, const char * pathname, int flags, mode_t mode)', {
     327        Call('OPENAT', 'int openat(int dirfd, const char *pathname, int flags, mode_t mode)', {
    322328                'fd': 'dirfd',
    323                 'addr': '(typeof(sqe->addr))pathname',
    324                 'open_flags': 'flags;',
    325                 'len': 'mode'
     329                'addr': '(uintptr_t)pathname',
     330                'len': 'mode',
     331                'open_flags': 'flags;'
    326332        }),
    327333        # CFA_HAVE_IORING_OP_OPENAT2
    328         Call('OPENAT2', 'int openat2(int dirfd, const char * pathname, struct open_how * how, size_t size)', {
     334        Call('OPENAT2', 'int openat2(int dirfd, const char *pathname, struct open_how * how, size_t size)', {
    329335                'fd': 'dirfd',
    330                 'addr': '(typeof(sqe->addr))pathname',
    331                 'off': '(typeof(sqe->off))how',
    332                 'len': 'sizeof(*how)'
     336                'addr': 'pathname',
     337                'len': 'sizeof(*how)',
     338                'off': '(uintptr_t)how',
    333339        }, define = 'CFA_HAVE_OPENAT2'),
    334340        # CFA_HAVE_IORING_OP_CLOSE
     
    337343        }),
    338344        # CFA_HAVE_IORING_OP_STATX
    339         Call('STATX', 'int statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx * statxbuf)', {
     345        Call('STATX', 'int statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf)', {
    340346                'fd': 'dirfd',
    341                 'addr': '(typeof(sqe->addr))pathname',
    342                 'statx_flags': 'flags',
     347                'off': '(uintptr_t)statxbuf',
     348                'addr': 'pathname',
    343349                'len': 'mask',
    344                 'off': '(typeof(sqe->off))statxbuf'
     350                'statx_flags': 'flags'
    345351        }, define = 'CFA_HAVE_STATX'),
    346352        # CFA_HAVE_IORING_OP_READ
    347353        Call('READ', 'ssize_t read(int fd, void * buf, size_t count)', {
    348354                'fd': 'fd',
    349                 'addr': '(typeof(sqe->addr))buf',
     355                'addr': '(uintptr_t)buf',
    350356                'len': 'count'
    351357        }),
     
    353359        Call('WRITE', 'ssize_t write(int fd, void * buf, size_t count)', {
    354360                'fd': 'fd',
    355                 'addr': '(typeof(sqe->addr))buf',
     361                'addr': '(uintptr_t)buf',
    356362                'len': 'count'
    357363        }),
    358364        # CFA_HAVE_IORING_OP_SPLICE
    359         Call('SPLICE', 'ssize_t splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags)', {
     365        Call('SPLICE', 'ssize_t splice(int fd_in, __off64_t *off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags)', {
    360366                'splice_fd_in': 'fd_in',
    361                 'splice_off_in': 'off_in ? (typeof(sqe->splice_off_in))*off_in : (typeof(sqe->splice_off_in))-1',
     367                'splice_off_in': 'off_in ? (__u64)*off_in : (__u64)-1',
    362368                'fd': 'fd_out',
    363                 'off': 'off_out ? (typeof(sqe->off))*off_out : (typeof(sqe->off))-1',
     369                'off': 'off_out ? (__u64)*off_out : (__u64)-1',
    364370                'len': 'len',
    365371                'splice_flags': 'flags'
  • libcfa/src/concurrency/io/setup.cfa

    r24d6572 r34b4268  
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819#if defined(__CFA_DEBUG__)
     
    215216
    216217                // completion queue
    217                 cq.try_lock  = false;
     218                cq.lock      = false;
    218219                cq.id        = MAX;
    219220                cq.ts        = rdtscl();
  • libcfa/src/concurrency/io/types.hfa

    r24d6572 r34b4268  
    3737        //-----------------------------------------------------------------------
    3838        // Ring Data structure
    39         // represent the io_uring submission ring which contains operations that will be sent to io_uring for processing
    40         struct __sub_ring_t {
    41                 // lock needed because remote processors might need to flush the instance
    42                 __spinlock_t lock;
    43 
     39      struct __sub_ring_t {
    4440                struct {
    4541                        // Head and tail of the ring (associated with array)
     
    6258
    6359                // number of sqes to submit on next system call.
    64                 volatile __u32 to_submit;
     60                __u32 to_submit;
    6561
    6662                // number of entries and mask to go with it
     
    8177                void * ring_ptr;
    8278                size_t ring_sz;
    83 
    84                 // for debug purposes, whether or not the last flush was due to a arbiter flush
    85                 bool last_external;
    8679        };
    8780
    88         // represent the io_uring completion ring which contains operations that have completed
    8981        struct __cmp_ring_t {
    90                 // needed because remote processors can help drain the buffer
    91                 volatile bool try_lock;
     82                volatile bool lock;
    9283
    93                 // id of the ring, used for the helping/topology algorithms
    9484                unsigned id;
    9585
    96                 // timestamp from last time it was drained
    9786                unsigned long long ts;
    9887
     
    116105        };
    117106
    118         // struct representing an io operation that still needs processing
    119         // actual operations are expected to inherit from this
    120107        struct __outstanding_io {
    121                 // intrusive link fields
    122108                inline Colable;
    123 
    124                 // primitive on which to block until the io is processed
    125109                oneshot waitctx;
    126110        };
    127111        static inline __outstanding_io *& Next( __outstanding_io * n ) { return (__outstanding_io *)Next( (Colable *)n ); }
    128112
    129         // queue of operations that are outstanding
    130113        struct __outstanding_io_queue {
    131                 // spinlock for protection
    132                 // TODO: changing to a lock that blocks, I haven't examined whether it should be a kernel or user lock
    133114                __spinlock_t lock;
    134 
    135                 // the actual queue
    136115                Queue(__outstanding_io) queue;
    137 
    138                 // volatile used to avoid the need for taking the lock if it's empty
    139116                volatile bool empty;
    140117        };
    141118
    142         // struct representing an operation that was submitted
    143119        struct __external_io {
    144                 // inherits from outstanding io
    145120                inline __outstanding_io;
    146 
    147                 // pointer and count to an array of ids to be submitted
    148121                __u32 * idxs;
    149122                __u32 have;
    150 
    151                 // whether or not these can be accumulated before flushing the buffer
    152123                bool lazy;
    153124        };
    154125
    155         // complete io_context, contains all the data for io submission and completion
     126
    156127        struct __attribute__((aligned(64))) io_context$ {
    157                 // arbiter, used in cases where threads for migrated at unfortunate moments
    158128                io_arbiter$ * arbiter;
    159 
    160                 // which prcessor the context is tied to
    161129                struct processor * proc;
    162130
    163                 // queue of io submissions that haven't beeen processed.
    164131                __outstanding_io_queue ext_sq;
    165132
    166                 // io_uring ring data structures
    167133                struct __sub_ring_t sq;
    168134                struct __cmp_ring_t cq;
    169 
    170                 // flag the io_uring rings where created with
    171135                __u32 ring_flags;
    172 
    173                 // file descriptor that identifies the io_uring instance
    174136                int fd;
    175137        };
    176138
    177         // short hand to check when the io_context was last processed (io drained)
    178139        static inline unsigned long long ts(io_context$ *& this) {
    179140                const __u32 head = *this->cq.head;
    180141                const __u32 tail = *this->cq.tail;
    181142
    182                 // if there is no pending completions, just pretend it's infinetely recent
    183143                if(head == tail) return ULLONG_MAX;
    184144
     
    186146        }
    187147
    188         // structure represeting allocations that couldn't succeed locally
    189148        struct __pending_alloc {
    190                 // inherit from outstanding io
    191149                inline __outstanding_io;
    192 
    193                 // array and size of the desired allocation
    194150                __u32 * idxs;
    195151                __u32 want;
    196 
    197                 // output param, the context the io was allocated from
    198152                io_context$ * ctx;
    199153        };
    200154
    201         // arbiter that handles cases where the context tied to the local processor is unable to satisfy the io
    202155        monitor __attribute__((aligned(64))) io_arbiter$ {
    203                 // contains a queue of io for pending allocations
    204156                __outstanding_io_queue pending;
    205157        };
  • libcfa/src/concurrency/iofwd.hfa

    r24d6572 r34b4268  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu Apr 23 17:31:00 2020
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 13 23:54:57 2023
    13 // Update Count     : 1
     11// Last Modified By :
     12// Last Modified On :
     13// Update Count     :
    1414//
    1515
     
    1717
    1818#include <unistd.h>
    19 #include <sys/socket.h>
    20 
    2119extern "C" {
    2220        #include <asm/types.h>
     
    5048typedef __off64_t off64_t;
    5149
     50struct cluster;
     51struct io_context$;
     52
     53struct iovec;
     54struct msghdr;
     55struct sockaddr;
     56struct statx;
    5257struct epoll_event;
     58
     59struct io_uring_sqe;
    5360
    5461//-----------------------------------------------------------------------
     
    8188// synchronous calls
    8289#if defined(CFA_HAVE_PREADV2)
    83         extern ssize_t cfa_preadv2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
     90        extern ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
    8491#endif
    8592#if defined(CFA_HAVE_PWRITEV2)
    86         extern ssize_t cfa_pwritev2(int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
     93        extern ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
    8794#endif
    8895extern int cfa_fsync(int fd, __u64 submit_flags);
    89 extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event * event, __u64 submit_flags);
     96extern int cfa_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event, __u64 submit_flags);
    9097extern int cfa_sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags, __u64 submit_flags);
    91 extern  ssize_t cfa_sendmsg(int sockfd, const struct msghdr * msg, int flags, __u64 submit_flags);
    92 extern ssize_t cfa_recvmsg(int sockfd, struct msghdr * msg, int flags, __u64 submit_flags);
    93 extern ssize_t cfa_send(int sockfd, const void * buf, size_t len, int flags, __u64 submit_flags);
    94 extern ssize_t cfa_recv(int sockfd, void * buf, size_t len, int flags, __u64 submit_flags);
    95 extern int cfa_accept4(int sockfd, __SOCKADDR_ARG addr, socklen_t * restrict addrlen, int flags, __u64 submit_flags);
    96 extern int cfa_connect(int sockfd, __CONST_SOCKADDR_ARG addr, socklen_t addrlen, __u64 submit_flags);
     98extern  ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags, __u64 submit_flags);
     99extern ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags, __u64 submit_flags);
     100extern ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags, __u64 submit_flags);
     101extern ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags, __u64 submit_flags);
     102extern int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, __u64 submit_flags);
     103extern int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, __u64 submit_flags);
    97104extern int cfa_fallocate(int fd, int mode, off_t offset, off_t len, __u64 submit_flags);
    98105extern int cfa_posix_fadvise(int fd, off_t offset, off_t len, int advice, __u64 submit_flags);
    99 extern int cfa_madvise(void * addr, size_t length, int advice, __u64 submit_flags);
    100 extern int cfa_openat(int dirfd, const char * pathname, int flags, mode_t mode, __u64 submit_flags);
     106extern int cfa_madvise(void *addr, size_t length, int advice, __u64 submit_flags);
     107extern int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode, __u64 submit_flags);
    101108#if defined(CFA_HAVE_OPENAT2)
    102         extern int cfa_openat2(int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags);
     109        extern int cfa_openat2(int dirfd, const char *pathname, struct open_how * how, size_t size, __u64 submit_flags);
    103110#endif
    104111extern int cfa_close(int fd, __u64 submit_flags);
    105112#if defined(CFA_HAVE_STATX)
    106         extern int cfa_statx(int dirfd, const char * pathname, int flags, unsigned int mask, struct statx * statxbuf, __u64 submit_flags);
     113        extern int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, __u64 submit_flags);
    107114#endif
    108115extern ssize_t cfa_read(int fd, void * buf, size_t count, __u64 submit_flags);
    109116extern ssize_t cfa_write(int fd, void * buf, size_t count, __u64 submit_flags);
    110 extern ssize_t cfa_splice(int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags, __u64 submit_flags);
     117extern ssize_t cfa_splice(int fd_in, __off64_t *off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags, __u64 submit_flags);
    111118extern ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags, __u64 submit_flags);
    112119
     
    114121// asynchronous calls
    115122#if defined(CFA_HAVE_PREADV2)
    116         extern void async_preadv2(io_future_t & future, int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
     123        extern void async_preadv2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
    117124#endif
    118125#if defined(CFA_HAVE_PWRITEV2)
    119         extern void async_pwritev2(io_future_t & future, int fd, const struct iovec * iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
     126        extern void async_pwritev2(io_future_t & future, int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags, __u64 submit_flags);
    120127#endif
    121128extern void async_fsync(io_future_t & future, int fd, __u64 submit_flags);
    122 extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event * event, __u64 submit_flags);
     129extern void async_epoll_ctl(io_future_t & future, int epfd, int op, int fd, struct epoll_event *event, __u64 submit_flags);
    123130extern void async_sync_file_range(io_future_t & future, int fd, off64_t offset, off64_t nbytes, unsigned int flags, __u64 submit_flags);
    124 extern void async_sendmsg(io_future_t & future, int sockfd, const struct msghdr * msg, int flags, __u64 submit_flags);
    125 extern void async_recvmsg(io_future_t & future, int sockfd, struct msghdr * msg, int flags, __u64 submit_flags);
    126 extern void async_send(io_future_t & future, int sockfd, const void * buf, size_t len, int flags, __u64 submit_flags);
    127 extern void async_recv(io_future_t & future, int sockfd, void * buf, size_t len, int flags, __u64 submit_flags);
    128 extern void async_accept4(io_future_t & future, int sockfd, __SOCKADDR_ARG addr, socklen_t * restrict addrlen, int flags, __u64 submit_flags);
    129 extern void async_connect(io_future_t & future, int sockfd, __CONST_SOCKADDR_ARG addr, socklen_t addrlen, __u64 submit_flags);
     131extern void async_sendmsg(io_future_t & future, int sockfd, const struct msghdr *msg, int flags, __u64 submit_flags);
     132extern void async_recvmsg(io_future_t & future, int sockfd, struct msghdr *msg, int flags, __u64 submit_flags);
     133extern void async_send(io_future_t & future, int sockfd, const void *buf, size_t len, int flags, __u64 submit_flags);
     134extern void async_recv(io_future_t & future, int sockfd, void *buf, size_t len, int flags, __u64 submit_flags);
     135extern void async_accept4(io_future_t & future, int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags, __u64 submit_flags);
     136extern void async_connect(io_future_t & future, int sockfd, const struct sockaddr *addr, socklen_t addrlen, __u64 submit_flags);
    130137extern void async_fallocate(io_future_t & future, int fd, int mode, off_t offset, off_t len, __u64 submit_flags);
    131138extern void async_posix_fadvise(io_future_t & future, int fd, off_t offset, off_t len, int advice, __u64 submit_flags);
    132 extern void async_madvise(io_future_t & future, void * addr, size_t length, int advice, __u64 submit_flags);
    133 extern void async_openat(io_future_t & future, int dirfd, const char * pathname, int flags, mode_t mode, __u64 submit_flags);
     139extern void async_madvise(io_future_t & future, void *addr, size_t length, int advice, __u64 submit_flags);
     140extern void async_openat(io_future_t & future, int dirfd, const char *pathname, int flags, mode_t mode, __u64 submit_flags);
    134141#if defined(CFA_HAVE_OPENAT2)
    135         extern void async_openat2(io_future_t & future, int dirfd, const char * pathname, struct open_how * how, size_t size, __u64 submit_flags);
     142        extern void async_openat2(io_future_t & future, int dirfd, const char *pathname, struct open_how * how, size_t size, __u64 submit_flags);
    136143#endif
    137144extern void async_close(io_future_t & future, int fd, __u64 submit_flags);
    138145#if defined(CFA_HAVE_STATX)
    139         extern void async_statx(io_future_t & future, int dirfd, const char * pathname, int flags, unsigned int mask, struct statx * statxbuf, __u64 submit_flags);
     146        extern void async_statx(io_future_t & future, int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf, __u64 submit_flags);
    140147#endif
    141148void async_read(io_future_t & future, int fd, void * buf, size_t count, __u64 submit_flags);
    142149extern void async_write(io_future_t & future, int fd, void * buf, size_t count, __u64 submit_flags);
    143 extern void async_splice(io_future_t & future, int fd_in, __off64_t * off_in, int fd_out, __off64_t * off_out, size_t len, unsigned int flags, __u64 submit_flags);
     150extern void async_splice(io_future_t & future, int fd_in, __off64_t *off_in, int fd_out, __off64_t *off_out, size_t len, unsigned int flags, __u64 submit_flags);
    144151extern void async_tee(io_future_t & future, int fd_in, int fd_out, size_t len, unsigned int flags, __u64 submit_flags);
    145152
  • libcfa/src/concurrency/kernel.cfa

    r24d6572 r34b4268  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan  9 08:42:05 2023
    13 // Update Count     : 77
     12// Last Modified On : Wed Nov 30 18:14:08 2022
     13// Update Count     : 76
    1414//
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819// #define __CFA_DEBUG_PRINT_RUNTIME_CORE__
     
    257258                __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this);
    258259        }
    259 
    260         __cfa_io_flush( this );
    261         __cfa_io_drain( this );
    262260
    263261        post( this->terminated );
  • libcfa/src/concurrency/kernel/cluster.cfa

    r24d6572 r34b4268  
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819#include "bits/defs.hfa"
     
    6869        return max_cores_l;
    6970}
     71
     72#if   defined(CFA_HAVE_LINUX_LIBRSEQ)
     73        // No forward declaration needed
     74        #define __kernel_rseq_register rseq_register_current_thread
     75        #define __kernel_rseq_unregister rseq_unregister_current_thread
     76#elif defined(CFA_HAVE_LINUX_RSEQ_H)
     77        static void __kernel_raw_rseq_register  (void);
     78        static void __kernel_raw_rseq_unregister(void);
     79
     80        #define __kernel_rseq_register __kernel_raw_rseq_register
     81        #define __kernel_rseq_unregister __kernel_raw_rseq_unregister
     82#else
     83        // No forward declaration needed
     84        // No initialization needed
     85        static inline void noop(void) {}
     86
     87        #define __kernel_rseq_register noop
     88        #define __kernel_rseq_unregister noop
     89#endif
    7090
    7191//=======================================================================
     
    91111// Lock-Free registering/unregistering of threads
    92112unsigned register_proc_id( void ) with(__scheduler_lock.lock) {
     113        __kernel_rseq_register();
     114
    93115        bool * handle = (bool *)&kernelTLS().sched_lock;
    94116
     
    140162
    141163        __atomic_store_n(cell, 0p, __ATOMIC_RELEASE);
     164
     165        __kernel_rseq_unregister();
    142166}
    143167
     
    481505        /* paranoid */ verify( mock_head(this)    == this.l.prev );
    482506}
     507
     508#if   defined(CFA_HAVE_LINUX_LIBRSEQ)
     509        // No definition needed
     510#elif defined(CFA_HAVE_LINUX_RSEQ_H)
     511
     512        #if defined( __x86_64 ) || defined( __i386 )
     513                #define RSEQ_SIG        0x53053053
     514        #elif defined( __ARM_ARCH )
     515                #ifdef __ARMEB__
     516                #define RSEQ_SIG    0xf3def5e7      /* udf    #24035    ; 0x5de3 (ARMv6+) */
     517                #else
     518                #define RSEQ_SIG    0xe7f5def3      /* udf    #24035    ; 0x5de3 */
     519                #endif
     520        #endif
     521
     522        extern void __disable_interrupts_hard();
     523        extern void __enable_interrupts_hard();
     524
     525        static void __kernel_raw_rseq_register  (void) {
     526                /* paranoid */ verify( __cfaabi_rseq.cpu_id == RSEQ_CPU_ID_UNINITIALIZED );
     527
     528                // int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), 0, (sigset_t *)0p, _NSIG / 8);
     529                int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), 0, RSEQ_SIG);
     530                if(ret != 0) {
     531                        int e = errno;
     532                        switch(e) {
     533                        case EINVAL: abort("KERNEL ERROR: rseq register invalid argument");
     534                        case ENOSYS: abort("KERNEL ERROR: rseq register no supported");
     535                        case EFAULT: abort("KERNEL ERROR: rseq register with invalid argument");
     536                        case EBUSY : abort("KERNEL ERROR: rseq register already registered");
     537                        case EPERM : abort("KERNEL ERROR: rseq register sig  argument  on unregistration does not match the signature received on registration");
     538                        default: abort("KERNEL ERROR: rseq register unexpected return %d", e);
     539                        }
     540                }
     541        }
     542
     543        static void __kernel_raw_rseq_unregister(void) {
     544                /* paranoid */ verify( __cfaabi_rseq.cpu_id >= 0 );
     545
     546                // int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), RSEQ_FLAG_UNREGISTER, (sigset_t *)0p, _NSIG / 8);
     547                int ret = syscall(__NR_rseq, &__cfaabi_rseq, sizeof(struct rseq), RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
     548                if(ret != 0) {
     549                        int e = errno;
     550                        switch(e) {
     551                        case EINVAL: abort("KERNEL ERROR: rseq unregister invalid argument");
     552                        case ENOSYS: abort("KERNEL ERROR: rseq unregister no supported");
     553                        case EFAULT: abort("KERNEL ERROR: rseq unregister with invalid argument");
     554                        case EBUSY : abort("KERNEL ERROR: rseq unregister already registered");
     555                        case EPERM : abort("KERNEL ERROR: rseq unregister sig  argument  on unregistration does not match the signature received on registration");
     556                        default: abort("KERNEL ERROR: rseq unregisteunexpected return %d", e);
     557                        }
     558                }
     559        }
     560#else
     561        // No definition needed
     562#endif
  • libcfa/src/concurrency/kernel/cluster.hfa

    r24d6572 r34b4268  
    4040
    4141// convert to log2 scale but using double
    42 static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { if(unlikely(0 == intsc)) return 0.0; else return log2((__readyQ_avg_t)intsc); }
     42static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { if(unlikely(0 == intsc)) return 0.0; else return log2(intsc); }
    4343
    4444#define warn_large_before warnf( !strict || old_avg < 35.0, "Suspiciously large previous average: %'lf, %'" PRId64 "ms \n", old_avg, program()`ms )
     
    146146}
    147147
    148 const static struct {
    149         unsigned readyq;
    150         unsigned io;
     148static struct {
     149        const unsigned readyq;
     150        const unsigned io;
    151151} __shard_factor = { 2, 1 };
    152152
  • libcfa/src/concurrency/kernel/private.hfa

    r24d6572 r34b4268  
    1010// Created On       : Mon Feb 13 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar  2 16:04:46 2023
    13 // Update Count     : 11
     12// Last Modified On : Wed Aug 12 08:21:33 2020
     13// Update Count     : 9
    1414//
    1515
     
    2929
    3030extern "C" {
     31#if   defined(CFA_HAVE_LINUX_LIBRSEQ)
     32        #include <rseq/rseq.h>
     33#elif defined(CFA_HAVE_LINUX_RSEQ_H)
     34        #include <linux/rseq.h>
     35#else
     36        #ifndef _GNU_SOURCE
     37        #error kernel/private requires gnu_source
     38        #endif
    3139        #include <sched.h>
     40#endif
    3241}
    3342
     
    101110// Hardware
    102111
     112#if   defined(CFA_HAVE_LINUX_LIBRSEQ)
     113        // No data needed
     114#elif defined(CFA_HAVE_LINUX_RSEQ_H)
     115        extern "Cforall" {
     116                extern __attribute__((aligned(64))) __thread volatile struct rseq __cfaabi_rseq;
     117        }
     118#else
     119        // No data needed
     120#endif
     121
    103122static inline int __kernel_getcpu() {
    104123        /* paranoid */ verify( ! __preemption_enabled() );
     124#if   defined(CFA_HAVE_LINUX_LIBRSEQ)
     125        return rseq_current_cpu();
     126#elif defined(CFA_HAVE_LINUX_RSEQ_H)
     127        int r = __cfaabi_rseq.cpu_id;
     128        /* paranoid */ verify( r >= 0 );
     129        return r;
     130#else
    105131        return sched_getcpu();
     132#endif
    106133}
    107134
  • libcfa/src/concurrency/kernel/startup.cfa

    r24d6572 r34b4268  
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819// #define __CFA_DEBUG_PRINT_RUNTIME_CORE__
    1920
    2021// C Includes
    21 #include <errno.h>                                                                              // errno
     22#include <errno.h>                                      // errno
    2223#include <signal.h>
    23 #include <string.h>                                                                             // strerror
    24 #include <unistd.h>
    25 #include <limits.h>                                                                             // PTHREAD_STACK_MIN
     24#include <string.h>                                     // strerror
     25#include <unistd.h>                                     // sysconf
     26
    2627extern "C" {
    27         #include <sys/eventfd.h>                                                        // eventfd
    28         #include <sys/mman.h>                                                           // mprotect
    29         #include <sys/resource.h>                                                       // getrlimit
     28        #include <limits.h>                             // PTHREAD_STACK_MIN
     29        #include <unistd.h>                             // syscall
     30        #include <sys/eventfd.h>                        // eventfd
     31        #include <sys/mman.h>                           // mprotect
     32        #include <sys/resource.h>                       // getrlimit
    3033}
    3134
     
    3336#include "kernel/private.hfa"
    3437#include "iofwd.hfa"
    35 #include "startup.hfa"                                                                  // STARTUP_PRIORITY_XXX
     38#include "startup.hfa"                                  // STARTUP_PRIORITY_XXX
    3639#include "limits.hfa"
    3740#include "math.hfa"
     
    147150__scheduler_RWLock_t __scheduler_lock @= { 0 };
    148151
     152#if   defined(CFA_HAVE_LINUX_LIBRSEQ)
     153        // No data needed
     154#elif defined(CFA_HAVE_LINUX_RSEQ_H)
     155        extern "Cforall" {
     156                __attribute__((aligned(64))) __thread volatile struct rseq __cfaabi_rseq @= {
     157                        .cpu_id : RSEQ_CPU_ID_UNINITIALIZED,
     158                };
     159        }
     160#else
     161        // No data needed
     162#endif
     163
    149164//-----------------------------------------------------------------------------
    150165// Struct to steal stack
  • libcfa/src/concurrency/locks.cfa

    r24d6572 r34b4268  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // locks.cfa -- LIBCFATHREAD
     7// locks.hfa -- LIBCFATHREAD
    88// Runtime locks that used with the runtime thread system.
    99//
     
    1616
    1717#define __cforall_thread__
     18#define _GNU_SOURCE
    1819
    1920#include "locks.hfa"
     
    7980        // lock is held by some other thread
    8081        if ( owner != 0p && owner != thrd ) {
    81         select_node node;
    82                 insert_last( blocked_threads, node );
     82                insert_last( blocked_threads, *thrd );
    8383                wait_count++;
    8484                unlock( lock );
    8585                park( );
    86         return;
    87         } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread
     86        }
     87        // multi acquisition lock is held by current thread
     88        else if ( owner == thrd && multi_acquisition ) {
    8889                recursion_count++;
    89         } else {  // lock isn't held
     90                unlock( lock );
     91        }
     92        // lock isn't held
     93        else {
    9094                owner = thrd;
    9195                recursion_count = 1;
    92         }
    93     unlock( lock );
     96                unlock( lock );
     97        }
    9498}
    9599
     
    114118}
    115119
    116 static inline void pop_node( blocking_lock & this ) with( this ) {
    117     __handle_waituntil_OR( blocked_threads );
    118     select_node * node = &try_pop_front( blocked_threads );
    119     if ( node ) {
    120         wait_count--;
    121         owner = node->blocked_thread;
    122         recursion_count = 1;
    123         // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
    124         wake_one( blocked_threads, *node );
    125     } else {
    126         owner = 0p;
    127         recursion_count = 0;
    128     }
     120static void pop_and_set_new_owner( blocking_lock & this ) with( this ) {
     121        thread$ * t = &try_pop_front( blocked_threads );
     122        owner = t;
     123        recursion_count = ( t ? 1 : 0 );
     124        if ( t ) wait_count--;
     125        unpark( t );
    129126}
    130127
     
    138135        recursion_count--;
    139136        if ( recursion_count == 0 ) {
    140                 pop_node( this );
     137                pop_and_set_new_owner( this );
    141138        }
    142139        unlock( lock );
     
    151148        // lock held
    152149        if ( owner != 0p ) {
    153                 insert_last( blocked_threads, *(select_node *)t->link_node );
     150                insert_last( blocked_threads, *t );
    154151                wait_count++;
     152                unlock( lock );
    155153        }
    156154        // lock not held
     
    159157                recursion_count = 1;
    160158                unpark( t );
    161         }
    162     unlock( lock );
    163 }
    164 
    165 size_t on_wait( blocking_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) with( this ) {
     159                unlock( lock );
     160        }
     161}
     162
     163size_t on_wait( blocking_lock & this ) with( this ) {
    166164        lock( lock __cfaabi_dbg_ctx2 );
    167165        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
     
    170168        size_t ret = recursion_count;
    171169
    172         pop_node( this );
    173 
    174     select_node node;
    175     active_thread()->link_node = (void *)&node;
     170        pop_and_set_new_owner( this );
    176171        unlock( lock );
    177 
    178     pre_park_then_park( pp_fn, pp_datum );
    179 
    180172        return ret;
    181173}
     
    184176        recursion_count = recursion;
    185177}
    186 
    187 // waituntil() support
    188 bool register_select( blocking_lock & this, select_node & node ) with(this) {
    189     lock( lock __cfaabi_dbg_ctx2 );
    190         thread$ * thrd = active_thread();
    191 
    192         // single acquisition lock is held by current thread
    193         /* paranoid */ verifyf( owner != thrd || multi_acquisition, "Single acquisition lock holder (%p) attempted to reacquire the lock %p resulting in a deadlock.", owner, &this );
    194 
    195     if ( !node.park_counter && ( (owner == thrd && multi_acquisition) || owner == 0p ) ) { // OR special case
    196         if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering
    197            unlock( lock );
    198            return false;
    199         }
    200     }
    201 
    202         // lock is held by some other thread
    203         if ( owner != 0p && owner != thrd ) {
    204                 insert_last( blocked_threads, node );
    205                 wait_count++;
    206                 unlock( lock );
    207         return false;
    208         } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread
    209                 recursion_count++;
    210         } else {  // lock isn't held
    211                 owner = thrd;
    212                 recursion_count = 1;
    213         }
    214 
    215     if ( node.park_counter ) __make_select_node_available( node );
    216     unlock( lock );
    217     return true;
    218 }
    219 
    220 bool unregister_select( blocking_lock & this, select_node & node ) with(this) {
    221     lock( lock __cfaabi_dbg_ctx2 );
    222     if ( node`isListed ) {
    223         remove( node );
    224         wait_count--;
    225         unlock( lock );
    226         return false;
    227     }
    228    
    229     if ( owner == active_thread() ) {
    230         /* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to unlock owner lock %p in waituntil unregister, which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count );
    231         // if recursion count is zero release lock and set new owner if one is waiting
    232         recursion_count--;
    233         if ( recursion_count == 0 ) {
    234             pop_node( this );
    235         }
    236     }
    237         unlock( lock );
    238     return false;
    239 }
    240 
    241 void on_selected( blocking_lock & this, select_node & node ) {}
    242178
    243179//-----------------------------------------------------------------------------
     
    376312        int counter( condition_variable(L) & this ) with(this) { return count; }
    377313
    378         static void enqueue_thread( condition_variable(L) & this, info_thread(L) * i ) with(this) {
     314        static size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) {
    379315                // add info_thread to waiting queue
    380316                insert_last( blocked_threads, *i );
    381317                count++;
    382         }
    383 
    384     static size_t block_and_get_recursion( info_thread(L) & i, __cfa_pre_park pp_fn, void * pp_datum ) {
    385         size_t recursion_count = 0;
    386                 if ( i.lock ) // if lock was passed get recursion count to reset to after waking thread
    387                         recursion_count = on_wait( *i.lock, pp_fn, pp_datum ); // this call blocks
    388                 else
    389             pre_park_then_park( pp_fn, pp_datum );
    390         return recursion_count;
    391     }
    392     static size_t block_and_get_recursion( info_thread(L) & i ) { return block_and_get_recursion( i, pre_park_noop, 0p ); }
     318                size_t recursion_count = 0;
     319                if (i->lock) {
     320                        // if lock was passed get recursion count to reset to after waking thread
     321                        recursion_count = on_wait( *i->lock );
     322                }
     323                return recursion_count;
     324        }
    393325
    394326        // helper for wait()'s' with no timeout
    395327        static void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) {
    396328                lock( lock __cfaabi_dbg_ctx2 );
    397         enqueue_thread( this, &i );
     329                size_t recursion_count = queue_and_get_recursion(this, &i);
    398330                unlock( lock );
    399331
    400332                // blocks here
    401         size_t recursion_count = block_and_get_recursion( i );
     333                park( );
    402334
    403335                // resets recursion count here after waking
    404                 if ( i.lock ) on_wakeup( *i.lock, recursion_count );
     336                if (i.lock) on_wakeup(*i.lock, recursion_count);
    405337        }
    406338
     
    409341                queue_info_thread( this, i );
    410342
    411     static void cond_alarm_register( void * node_ptr ) { register_self( (alarm_node_t *)node_ptr ); }
    412 
    413343        // helper for wait()'s' with a timeout
    414344        static void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
    415345                lock( lock __cfaabi_dbg_ctx2 );
    416         enqueue_thread( this, &info );
     346                size_t recursion_count = queue_and_get_recursion(this, &info);
    417347                alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info };
    418348                unlock( lock );
    419349
    420                 // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock
    421         size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) );
    422                 // park();
     350                // registers alarm outside cond lock to avoid deadlock
     351                register_self( &node_wrap.alarm_node );
     352
     353                // blocks here
     354                park();
    423355
    424356                // unregisters alarm so it doesn't go off if this happens first
     
    426358
    427359                // resets recursion count here after waking
    428                 if ( info.lock ) on_wakeup( *info.lock, recursion_count );
     360                if (info.lock) on_wakeup(*info.lock, recursion_count);
    429361        }
    430362
     
    486418                info_thread( L ) i = { active_thread(), info, &l };
    487419                insert_last( blocked_threads, i );
    488                 size_t recursion_count = on_wait( *i.lock, pre_park_noop, 0p ); // blocks here
    489                 // park( );
     420                size_t recursion_count = on_wait( *i.lock );
     421                park( );
    490422                on_wakeup(*i.lock, recursion_count);
    491423        }
     
    528460        bool empty ( pthread_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; }
    529461
     462        static size_t queue_and_get_recursion( pthread_cond_var(L) & this, info_thread(L) * i ) with(this) {
     463                // add info_thread to waiting queue
     464                insert_last( blocked_threads, *i );
     465                size_t recursion_count = 0;
     466                recursion_count = on_wait( *i->lock );
     467                return recursion_count;
     468        }
     469       
    530470        static void queue_info_thread_timeout( pthread_cond_var(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) {
    531471                lock( lock __cfaabi_dbg_ctx2 );
    532         insert_last( blocked_threads, info );
     472                size_t recursion_count = queue_and_get_recursion(this, &info);
    533473                pthread_alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info };
    534474                unlock( lock );
    535475
    536                 // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock
    537         size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) );
    538 
    539                 // unregisters alarm so it doesn't go off if signal happens first
     476                // registers alarm outside cond lock to avoid deadlock
     477                register_self( &node_wrap.alarm_node );
     478
     479                // blocks here
     480                park();
     481
     482                // unregisters alarm so it doesn't go off if this happens first
    540483                unregister_self( &node_wrap.alarm_node );
    541484
    542485                // resets recursion count here after waking
    543                 if ( info.lock ) on_wakeup( *info.lock, recursion_count );
     486                if (info.lock) on_wakeup(*info.lock, recursion_count);
    544487        }
    545488
     
    551494                lock( lock __cfaabi_dbg_ctx2 );
    552495                info_thread( L ) i = { active_thread(), info, &l };
    553         insert_last( blocked_threads, i );
    554                 unlock( lock );
    555 
    556         // blocks here
    557                 size_t recursion_count = block_and_get_recursion( i );
    558 
    559                 on_wakeup( *i.lock, recursion_count );
     496                size_t recursion_count = queue_and_get_recursion(this, &i);
     497                unlock( lock );
     498                park( );
     499                on_wakeup(*i.lock, recursion_count);
    560500        }
    561501
     
    645585        return thrd != 0p;
    646586}
    647 
  • libcfa/src/concurrency/locks.hfa

    r24d6572 r34b4268  
    3030#include "time.hfa"
    3131
    32 #include "select.hfa"
    33 
    3432#include <fstream.hfa>
     33
    3534
    3635// futex headers
     
    3938#include <unistd.h>
    4039
    41 typedef void (*__cfa_pre_park)( void * );
    42 
    43 static inline void pre_park_noop( void * ) {}
    44 
    45 //-----------------------------------------------------------------------------
    46 // is_blocking_lock
    47 forall( L & | sized(L) )
    48 trait is_blocking_lock {
    49         // For synchronization locks to use when acquiring
    50         void on_notify( L &, struct thread$ * );
    51 
    52         // For synchronization locks to use when releasing
    53         size_t on_wait( L &, __cfa_pre_park pp_fn, void * pp_datum );
    54 
    55         // to set recursion count after getting signalled;
    56         void on_wakeup( L &, size_t recursion );
    57 };
    58 
    59 static inline void pre_park_then_park( __cfa_pre_park pp_fn, void * pp_datum ) {
    60     pp_fn( pp_datum );
    61     park();
    62 }
    63 
    64 // macros for default routine impls for is_blocking_lock trait that do not wait-morph
    65 
    66 #define DEFAULT_ON_NOTIFY( lock_type ) \
    67     static inline void on_notify( lock_type & this, thread$ * t ){ unpark(t); }
    68 
    69 #define DEFAULT_ON_WAIT( lock_type ) \
    70     static inline size_t on_wait( lock_type & this, __cfa_pre_park pp_fn, void * pp_datum ) { \
    71         unlock( this ); \
    72         pre_park_then_park( pp_fn, pp_datum ); \
    73         return 0; \
    74     }
    75 
    76 // on_wakeup impl if lock should be reacquired after waking up
    77 #define DEFAULT_ON_WAKEUP_REACQ( lock_type ) \
    78     static inline void on_wakeup( lock_type & this, size_t recursion ) { lock( this ); }
    79 
    80 // on_wakeup impl if lock will not be reacquired after waking up
    81 #define DEFAULT_ON_WAKEUP_NO_REACQ( lock_type ) \
    82     static inline void on_wakeup( lock_type & this, size_t recursion ) {}
    83 
    84 
     40// undef to make a number of the locks not reacquire upon waking from a condlock
     41#define REACQ 1
    8542
    8643//-----------------------------------------------------------------------------
     
    10966static inline bool   try_lock ( single_acquisition_lock & this ) { return try_lock( (blocking_lock &)this ); }
    11067static inline void   unlock   ( single_acquisition_lock & this ) { unlock  ( (blocking_lock &)this ); }
    111 static inline size_t on_wait  ( single_acquisition_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) { return on_wait ( (blocking_lock &)this, pp_fn, pp_datum ); }
     68static inline size_t on_wait  ( single_acquisition_lock & this ) { return on_wait ( (blocking_lock &)this ); }
    11269static inline void   on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    11370static inline void   on_notify( single_acquisition_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
    114 static inline bool   register_select( single_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    115 static inline bool   unregister_select( single_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); }
    116 static inline void   on_selected( single_acquisition_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); }
    11771
    11872//----------
     
    12680static inline bool   try_lock ( owner_lock & this ) { return try_lock( (blocking_lock &)this ); }
    12781static inline void   unlock   ( owner_lock & this ) { unlock  ( (blocking_lock &)this ); }
    128 static inline size_t on_wait  ( owner_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) { return on_wait ( (blocking_lock &)this, pp_fn, pp_datum ); }
     82static inline size_t on_wait  ( owner_lock & this ) { return on_wait ( (blocking_lock &)this ); }
    12983static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    13084static inline void   on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
    131 static inline bool   register_select( owner_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    132 static inline bool   unregister_select( owner_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); }
    133 static inline void   on_selected( owner_lock & this, select_node & node ) { on_selected( (blocking_lock &)this, node ); }
    13485
    13586//-----------------------------------------------------------------------------
     
    176127static inline void ?{}(mcs_spin_node & this) { this.next = 0p; this.locked = true; }
    177128
     129static inline mcs_spin_node * volatile & ?`next ( mcs_spin_node * node ) {
     130        return node->next;
     131}
     132
    178133struct mcs_spin_lock {
    179134        mcs_spin_queue queue;
     
    181136
    182137static inline void lock(mcs_spin_lock & l, mcs_spin_node & n) {
    183     n.locked = true;
    184138        mcs_spin_node * prev = __atomic_exchange_n(&l.queue.tail, &n, __ATOMIC_SEQ_CST);
    185         if( prev == 0p ) return;
     139        n.locked = true;
     140        if(prev == 0p) return;
    186141        prev->next = &n;
    187         while( __atomic_load_n(&n.locked, __ATOMIC_RELAXED) ) Pause();
     142        while(__atomic_load_n(&n.locked, __ATOMIC_RELAXED)) Pause();
    188143}
    189144
     
    191146        mcs_spin_node * n_ptr = &n;
    192147        if (__atomic_compare_exchange_n(&l.queue.tail, &n_ptr, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) return;
    193         while (__atomic_load_n(&n.next, __ATOMIC_RELAXED) == 0p) Pause();
     148        while (__atomic_load_n(&n.next, __ATOMIC_RELAXED) == 0p) {}
    194149        n.next->locked = false;
    195150}
     
    198153// futex_mutex
    199154
     155// - No cond var support
    200156// - Kernel thd blocking alternative to the spinlock
    201157// - No ownership (will deadlock on reacq)
    202 // - no reacq on wakeup
    203158struct futex_mutex {
    204159        // lock state any state other than UNLOCKED is locked
     
    214169}
    215170
    216 static inline void ?{}( futex_mutex & this ) with(this) { val = 0; }
    217 
    218 static inline bool internal_try_lock( futex_mutex & this, int & compare_val) with(this) {
     171static inline void  ?{}( futex_mutex & this ) with(this) { val = 0; }
     172
     173static inline bool internal_try_lock(futex_mutex & this, int & compare_val) with(this) {
    219174        return __atomic_compare_exchange_n((int*)&val, (int*)&compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
    220175}
    221176
    222 static inline int internal_exchange( futex_mutex & this ) with(this) {
     177static inline int internal_exchange(futex_mutex & this) with(this) {
    223178        return __atomic_exchange_n((int*)&val, 2, __ATOMIC_ACQUIRE);
    224179}
    225180
    226181// if this is called recursively IT WILL DEADLOCK!!!!!
    227 static inline void lock( futex_mutex & this ) with(this) {
     182static inline void lock(futex_mutex & this) with(this) {
    228183        int state;
    229184
    230         for( int spin = 4; spin < 1024; spin += spin) {
    231                 state = 0;
    232                 // if unlocked, lock and return
    233                 if (internal_try_lock(this, state)) return;
    234                 if (2 == state) break;
    235                 for (int i = 0; i < spin; i++) Pause();
    236         }
     185       
     186        // // linear backoff omitted for now
     187        // for( int spin = 4; spin < 1024; spin += spin) {
     188        //      state = 0;
     189        //      // if unlocked, lock and return
     190        //      if (internal_try_lock(this, state)) return;
     191        //      if (2 == state) break;
     192        //      for (int i = 0; i < spin; i++) Pause();
     193        // }
     194
     195        // no contention try to acquire
     196        if (internal_try_lock(this, state)) return;
    237197       
    238198        // if not in contended state, set to be in contended state
     
    247207
    248208static inline void unlock(futex_mutex & this) with(this) {
    249         // if uncontended do atomic unlock and then return
    250     if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return;
     209        // if uncontended do atomice unlock and then return
     210        if (__atomic_fetch_sub(&val, 1, __ATOMIC_RELEASE) == 1) return; // TODO: try acq/rel
    251211       
    252212        // otherwise threads are blocked so we must wake one
     213        __atomic_store_n((int *)&val, 0, __ATOMIC_RELEASE);
    253214        futex((int *)&val, FUTEX_WAKE, 1);
    254215}
    255216
    256 DEFAULT_ON_NOTIFY( futex_mutex )
    257 DEFAULT_ON_WAIT( futex_mutex )
    258 DEFAULT_ON_WAKEUP_NO_REACQ( futex_mutex )
    259 
    260 //-----------------------------------------------------------------------------
    261 // go_mutex
    262 
    263 // - Kernel thd blocking alternative to the spinlock
    264 // - No ownership (will deadlock on reacq)
    265 // - Golang's flavour of mutex
    266 // - Impl taken from Golang: src/runtime/lock_futex.go
    267 struct go_mutex {
    268         // lock state any state other than UNLOCKED is locked
    269         // enum LockState { UNLOCKED = 0, LOCKED = 1, SLEEPING = 2 };
    270        
    271         // stores a lock state
    272         int val;
    273 };
    274 static inline void  ?{}( go_mutex & this ) with(this) { val = 0; }
    275 // static inline void ?{}( go_mutex & this, go_mutex this2 ) = void; // these don't compile correctly at the moment so they should be omitted
    276 // static inline void ?=?( go_mutex & this, go_mutex this2 ) = void;
    277 
    278 static inline bool internal_try_lock(go_mutex & this, int & compare_val, int new_val ) with(this) {
    279         return __atomic_compare_exchange_n((int*)&val, (int*)&compare_val, new_val, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
    280 }
    281 
    282 static inline int internal_exchange(go_mutex & this, int swap ) with(this) {
    283         return __atomic_exchange_n((int*)&val, swap, __ATOMIC_ACQUIRE);
    284 }
    285 
    286 // if this is called recursively IT WILL DEADLOCK!!!!!
    287 static inline void lock( go_mutex & this ) with( this ) {
    288         int state, init_state;
    289 
    290     // speculative grab
    291     state = internal_exchange(this, 1);
    292     if ( !state ) return; // state == 0
    293     init_state = state;
    294     for (;;) {
    295         for( int i = 0; i < 4; i++ ) {
    296             while( !val ) { // lock unlocked
    297                 state = 0;
    298                 if ( internal_try_lock( this, state, init_state ) ) return;
    299             }
    300             for (int i = 0; i < 30; i++) Pause();
    301         }
    302 
    303         while( !val ) { // lock unlocked
    304             state = 0;
    305             if ( internal_try_lock( this, state, init_state ) ) return;
    306         }
    307         sched_yield();
    308        
    309         // if not in contended state, set to be in contended state
    310         state = internal_exchange( this, 2 );
    311         if ( !state ) return; // state == 0
    312         init_state = 2;
    313         futex( (int*)&val, FUTEX_WAIT, 2 ); // if val is not 2 this returns with EWOULDBLOCK
    314     }
    315 }
    316 
    317 static inline void unlock( go_mutex & this ) with(this) {
    318         // if uncontended do atomic unlock and then return
    319     if ( __atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1 ) return;
    320        
    321         // otherwise threads are blocked so we must wake one
    322         futex( (int *)&val, FUTEX_WAKE, 1 );
    323 }
    324 
    325 DEFAULT_ON_NOTIFY( go_mutex )
    326 DEFAULT_ON_WAIT( go_mutex )
    327 DEFAULT_ON_WAKEUP_NO_REACQ( go_mutex )
    328 
    329 //-----------------------------------------------------------------------------
    330 // Exponential backoff then block lock
    331 struct exp_backoff_then_block_lock {
     217static inline void on_notify( futex_mutex & f, thread$ * t){ unpark(t); }
     218static inline size_t on_wait( futex_mutex & f ) {unlock(f); return 0;}
     219
     220// to set recursion count after getting signalled;
     221static inline void on_wakeup( futex_mutex & f, size_t recursion ) {}
     222
     223//-----------------------------------------------------------------------------
     224// CLH Spinlock
     225// - No recursive acquisition
     226// - Needs to be released by owner
     227
     228struct clh_lock {
     229        volatile bool * volatile tail;
     230};
     231
     232static inline void  ?{}( clh_lock & this ) { this.tail = malloc(); *this.tail = true; }
     233static inline void ^?{}( clh_lock & this ) { free(this.tail); }
     234
     235static inline void lock(clh_lock & l) {
     236        thread$ * curr_thd = active_thread();
     237        *(curr_thd->clh_node) = false;
     238        volatile bool * prev = __atomic_exchange_n((bool **)(&l.tail), (bool *)(curr_thd->clh_node), __ATOMIC_SEQ_CST);
     239        while(!__atomic_load_n(prev, __ATOMIC_ACQUIRE)) Pause();
     240        curr_thd->clh_prev = prev;
     241}
     242
     243static inline void unlock(clh_lock & l) {
     244        thread$ * curr_thd = active_thread();
     245        __atomic_store_n(curr_thd->clh_node, true, __ATOMIC_RELEASE);
     246        curr_thd->clh_node = curr_thd->clh_prev;
     247}
     248
     249static inline void on_notify(clh_lock & this, struct thread$ * t ) { unpark(t); }
     250static inline size_t on_wait(clh_lock & this) { unlock(this); return 0; }
     251static inline void on_wakeup(clh_lock & this, size_t recursion ) {
     252        #ifdef REACQ
     253        lock(this);
     254        #endif
     255}
     256
     257
     258//-----------------------------------------------------------------------------
     259// Linear backoff Spinlock
     260struct linear_backoff_then_block_lock {
    332261        // Spin lock used for mutual exclusion
    333262        __spinlock_t spinlock;
     
    340269};
    341270
    342 static inline void  ?{}( exp_backoff_then_block_lock & this ) {
     271static inline void  ?{}( linear_backoff_then_block_lock & this ) {
    343272        this.spinlock{};
    344273        this.blocked_threads{};
    345274        this.lock_value = 0;
    346275}
    347 static inline void ?{}( exp_backoff_then_block_lock & this, exp_backoff_then_block_lock this2 ) = void;
    348 static inline void ?=?( exp_backoff_then_block_lock & this, exp_backoff_then_block_lock this2 ) = void;
    349 
    350 static inline void  ^?{}( exp_backoff_then_block_lock & this ){}
    351 
    352 static inline bool internal_try_lock( exp_backoff_then_block_lock & this, size_t & compare_val ) with(this) {
    353         return __atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
    354 }
    355 
    356 static inline bool try_lock( exp_backoff_then_block_lock & this ) { size_t compare_val = 0; return internal_try_lock( this, compare_val ); }
    357 
    358 static inline bool try_lock_contention( exp_backoff_then_block_lock & this ) with(this) {
    359         return !__atomic_exchange_n( &lock_value, 2, __ATOMIC_ACQUIRE );
    360 }
    361 
    362 static inline bool block( exp_backoff_then_block_lock & this ) with(this) {
    363     lock( spinlock __cfaabi_dbg_ctx2 );
    364     if (__atomic_load_n( &lock_value, __ATOMIC_SEQ_CST) != 2) {
    365         unlock( spinlock );
    366         return true;
    367     }
    368     insert_last( blocked_threads, *active_thread() );
    369     unlock( spinlock );
     276static inline void ^?{}( linear_backoff_then_block_lock & this ) {}
     277// static inline void ?{}( linear_backoff_then_block_lock & this, linear_backoff_then_block_lock this2 ) = void;
     278// static inline void ?=?( linear_backoff_then_block_lock & this, linear_backoff_then_block_lock this2 ) = void;
     279
     280static inline bool internal_try_lock(linear_backoff_then_block_lock & this, size_t & compare_val) with(this) {
     281        if (__atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
     282                return true;
     283        }
     284        return false;
     285}
     286
     287static inline bool try_lock(linear_backoff_then_block_lock & this) { size_t compare_val = 0; return internal_try_lock(this, compare_val); }
     288
     289static inline bool try_lock_contention(linear_backoff_then_block_lock & this) with(this) {
     290        if (__atomic_exchange_n(&lock_value, 2, __ATOMIC_ACQUIRE) == 0) {
     291                return true;
     292        }
     293        return false;
     294}
     295
     296static inline bool block(linear_backoff_then_block_lock & this) with(this) {
     297        lock( spinlock __cfaabi_dbg_ctx2 ); // TODO change to lockfree queue (MPSC)
     298        if (lock_value != 2) {
     299                unlock( spinlock );
     300                return true;
     301        }
     302        insert_last( blocked_threads, *active_thread() );
     303        unlock( spinlock );
    370304        park( );
    371305        return true;
    372306}
    373307
    374 static inline void lock( exp_backoff_then_block_lock & this ) with(this) {
     308static inline void lock(linear_backoff_then_block_lock & this) with(this) {
    375309        size_t compare_val = 0;
    376310        int spin = 4;
    377 
    378311        // linear backoff
    379312        for( ;; ) {
     
    391324}
    392325
    393 static inline void unlock( exp_backoff_then_block_lock & this ) with(this) {
     326static inline void unlock(linear_backoff_then_block_lock & this) with(this) {
    394327    if (__atomic_exchange_n(&lock_value, 0, __ATOMIC_RELEASE) == 1) return;
    395     lock( spinlock __cfaabi_dbg_ctx2 );
    396     thread$ * t = &try_pop_front( blocked_threads );
    397     unlock( spinlock );
    398     unpark( t );
    399 }
    400 
    401 DEFAULT_ON_NOTIFY( exp_backoff_then_block_lock )
    402 DEFAULT_ON_WAIT( exp_backoff_then_block_lock )
    403 DEFAULT_ON_WAKEUP_REACQ( exp_backoff_then_block_lock )
     328        lock( spinlock __cfaabi_dbg_ctx2 );
     329        thread$ * t = &try_pop_front( blocked_threads );
     330        unlock( spinlock );
     331        unpark( t );
     332}
     333
     334static inline void on_notify(linear_backoff_then_block_lock & this, struct thread$ * t ) { unpark(t); }
     335static inline size_t on_wait(linear_backoff_then_block_lock & this) { unlock(this); return 0; }
     336static inline void on_wakeup(linear_backoff_then_block_lock & this, size_t recursion ) {
     337        #ifdef REACQ
     338        lock(this);
     339        #endif
     340}
    404341
    405342//-----------------------------------------------------------------------------
     
    431368
    432369// if this is called recursively IT WILL DEADLOCK!!!!!
    433 static inline void lock( fast_block_lock & this ) with(this) {
     370static inline void lock(fast_block_lock & this) with(this) {
    434371        lock( lock __cfaabi_dbg_ctx2 );
    435372        if ( held ) {
     
    443380}
    444381
    445 static inline void unlock( fast_block_lock & this ) with(this) {
     382static inline void unlock(fast_block_lock & this) with(this) {
    446383        lock( lock __cfaabi_dbg_ctx2 );
    447384        /* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this );
     
    452389}
    453390
    454 static inline void on_notify( fast_block_lock & this, struct thread$ * t ) with(this) {
    455     lock( lock __cfaabi_dbg_ctx2 );
    456     insert_last( blocked_threads, *t );
    457     unlock( lock );
    458 }
    459 DEFAULT_ON_WAIT( fast_block_lock )
    460 DEFAULT_ON_WAKEUP_NO_REACQ( fast_block_lock )
     391static inline void on_notify(fast_block_lock & this, struct thread$ * t ) with(this) {
     392        #ifdef REACQ
     393                lock( lock __cfaabi_dbg_ctx2 );
     394                insert_last( blocked_threads, *t );
     395                unlock( lock );
     396        #else
     397                unpark(t);
     398        #endif
     399}
     400static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; }
     401static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { }
    461402
    462403//-----------------------------------------------------------------------------
     
    469410struct simple_owner_lock {
    470411        // List of blocked threads
    471         dlist( select_node ) blocked_threads;
     412        dlist( thread$ ) blocked_threads;
    472413
    473414        // Spin lock used for mutual exclusion
     
    490431static inline void ?=?( simple_owner_lock & this, simple_owner_lock this2 ) = void;
    491432
    492 static inline void lock( simple_owner_lock & this ) with(this) {
    493         if ( owner == active_thread() ) {
     433static inline void lock(simple_owner_lock & this) with(this) {
     434        if (owner == active_thread()) {
    494435                recursion_count++;
    495436                return;
     
    497438        lock( lock __cfaabi_dbg_ctx2 );
    498439
    499         if ( owner != 0p ) {
    500         select_node node;
    501                 insert_last( blocked_threads, node );
     440        if (owner != 0p) {
     441                insert_last( blocked_threads, *active_thread() );
    502442                unlock( lock );
    503443                park( );
     
    509449}
    510450
    511 static inline void pop_node( simple_owner_lock & this ) with(this) {
    512     __handle_waituntil_OR( blocked_threads );
    513     select_node * node = &try_pop_front( blocked_threads );
    514     if ( node ) {
    515         owner = node->blocked_thread;
    516         recursion_count = 1;
    517         // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
    518         wake_one( blocked_threads, *node );
    519     } else {
    520         owner = 0p;
    521         recursion_count = 0;
    522     }
    523 }
    524 
    525 static inline void unlock( simple_owner_lock & this ) with(this) {
     451// TODO: fix duplicate def issue and bring this back
     452// void pop_and_set_new_owner( simple_owner_lock & this ) with( this ) {
     453        // thread$ * t = &try_pop_front( blocked_threads );
     454        // owner = t;
     455        // recursion_count = ( t ? 1 : 0 );
     456        // unpark( t );
     457// }
     458
     459static inline void unlock(simple_owner_lock & this) with(this) {
    526460        lock( lock __cfaabi_dbg_ctx2 );
    527461        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
     
    530464        recursion_count--;
    531465        if ( recursion_count == 0 ) {
    532                 pop_node( this );
     466                // pop_and_set_new_owner( this );
     467                thread$ * t = &try_pop_front( blocked_threads );
     468                owner = t;
     469                recursion_count = ( t ? 1 : 0 );
     470                unpark( t );
    533471        }
    534472        unlock( lock );
    535473}
    536474
    537 static inline void on_notify( simple_owner_lock & this, thread$ * t ) with(this) {
     475static inline void on_notify(simple_owner_lock & this, struct thread$ * t ) with(this) {
    538476        lock( lock __cfaabi_dbg_ctx2 );
    539477        // lock held
    540478        if ( owner != 0p ) {
    541                 insert_last( blocked_threads, *(select_node *)t->link_node );
     479                insert_last( blocked_threads, *t );
    542480        }
    543481        // lock not held
     
    550488}
    551489
    552 static inline size_t on_wait( simple_owner_lock & this, __cfa_pre_park pp_fn, void * pp_datum ) with(this) {
     490static inline size_t on_wait(simple_owner_lock & this) with(this) {
    553491        lock( lock __cfaabi_dbg_ctx2 );
    554492        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
     
    557495        size_t ret = recursion_count;
    558496
    559         pop_node( this );
    560 
    561     select_node node;
    562     active_thread()->link_node = (void *)&node;
     497        // pop_and_set_new_owner( this );
     498
     499        thread$ * t = &try_pop_front( blocked_threads );
     500        owner = t;
     501        recursion_count = ( t ? 1 : 0 );
     502        unpark( t );
     503
    563504        unlock( lock );
    564 
    565     pre_park_then_park( pp_fn, pp_datum );
    566 
    567505        return ret;
    568506}
    569507
    570 static inline void on_wakeup( simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; }
    571 
    572 // waituntil() support
    573 static inline bool register_select( simple_owner_lock & this, select_node & node ) with(this) {
    574     lock( lock __cfaabi_dbg_ctx2 );
    575 
    576     // check if we can complete operation. If so race to establish winner in special OR case
    577     if ( !node.park_counter && ( owner == active_thread() || owner == 0p ) ) {
    578         if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering
    579            unlock( lock );
    580            return false;
    581         }
    582     }
    583 
    584     if ( owner == active_thread() ) {
    585                 recursion_count++;
    586         if ( node.park_counter ) __make_select_node_available( node );
    587         unlock( lock );
    588                 return true;
    589         }
    590 
    591     if ( owner != 0p ) {
    592                 insert_last( blocked_threads, node );
    593                 unlock( lock );
    594                 return false;
    595         }
    596    
    597         owner = active_thread();
    598         recursion_count = 1;
    599 
    600     if ( node.park_counter ) __make_select_node_available( node );
    601     unlock( lock );
    602     return true;
    603 }
    604 
    605 static inline bool unregister_select( simple_owner_lock & this, select_node & node ) with(this) {
    606     lock( lock __cfaabi_dbg_ctx2 );
    607     if ( node`isListed ) {
    608         remove( node );
    609         unlock( lock );
    610         return false;
    611     }
    612 
    613     if ( owner == active_thread() ) {
    614         recursion_count--;
    615         if ( recursion_count == 0 ) {
    616             pop_node( this );
    617         }
    618     }
    619     unlock( lock );
    620     return false;
    621 }
    622 
    623 static inline void on_selected( simple_owner_lock & this, select_node & node ) {}
    624 
     508static inline void on_wakeup(simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; }
    625509
    626510//-----------------------------------------------------------------------------
     
    637521        // flag showing if lock is held
    638522        volatile bool held;
     523
     524        #ifdef __CFA_DEBUG__
     525        // for deadlock detection
     526        struct thread$ * owner;
     527        #endif
    639528};
    640529
     
    647536static inline void ?=?( spin_queue_lock & this, spin_queue_lock this2 ) = void;
    648537
    649 // if this is called recursively IT WILL DEADLOCK!
    650 static inline void lock( spin_queue_lock & this ) with(this) {
     538// if this is called recursively IT WILL DEADLOCK!!!!!
     539static inline void lock(spin_queue_lock & this) with(this) {
    651540        mcs_spin_node node;
    652541        lock( lock, node );
     
    656545}
    657546
    658 static inline void unlock( spin_queue_lock & this ) with(this) {
     547static inline void unlock(spin_queue_lock & this) with(this) {
    659548        __atomic_store_n(&held, false, __ATOMIC_RELEASE);
    660549}
    661550
    662 DEFAULT_ON_NOTIFY( spin_queue_lock )
    663 DEFAULT_ON_WAIT( spin_queue_lock )
    664 DEFAULT_ON_WAKEUP_REACQ( spin_queue_lock )
     551static inline void on_notify(spin_queue_lock & this, struct thread$ * t ) {
     552        unpark(t);
     553}
     554static inline size_t on_wait(spin_queue_lock & this) { unlock(this); return 0; }
     555static inline void on_wakeup(spin_queue_lock & this, size_t recursion ) {
     556        #ifdef REACQ
     557        lock(this);
     558        #endif
     559}
     560
    665561
    666562//-----------------------------------------------------------------------------
     
    688584
    689585// if this is called recursively IT WILL DEADLOCK!!!!!
    690 static inline void lock( mcs_block_spin_lock & this ) with(this) {
     586static inline void lock(mcs_block_spin_lock & this) with(this) {
    691587        mcs_node node;
    692588        lock( lock, node );
     
    700596}
    701597
    702 DEFAULT_ON_NOTIFY( mcs_block_spin_lock )
    703 DEFAULT_ON_WAIT( mcs_block_spin_lock )
    704 DEFAULT_ON_WAKEUP_REACQ( mcs_block_spin_lock )
     598static inline void on_notify(mcs_block_spin_lock & this, struct thread$ * t ) { unpark(t); }
     599static inline size_t on_wait(mcs_block_spin_lock & this) { unlock(this); return 0; }
     600static inline void on_wakeup(mcs_block_spin_lock & this, size_t recursion ) {
     601        #ifdef REACQ
     602        lock(this);
     603        #endif
     604}
    705605
    706606//-----------------------------------------------------------------------------
     
    728628
    729629// if this is called recursively IT WILL DEADLOCK!!!!!
    730 static inline void lock( block_spin_lock & this ) with(this) {
     630static inline void lock(block_spin_lock & this) with(this) {
    731631        lock( lock );
    732632        while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause();
     
    735635}
    736636
    737 static inline void unlock( block_spin_lock & this ) with(this) {
     637static inline void unlock(block_spin_lock & this) with(this) {
    738638        __atomic_store_n(&held, false, __ATOMIC_RELEASE);
    739639}
    740640
    741 static inline void on_notify( block_spin_lock & this, struct thread$ * t ) with(this.lock) {
     641static inline void on_notify(block_spin_lock & this, struct thread$ * t ) with(this.lock) {
     642  #ifdef REACQ
    742643        // first we acquire internal fast_block_lock
    743644        lock( lock __cfaabi_dbg_ctx2 );
     
    751652        unlock( lock );
    752653
     654  #endif
    753655        unpark(t);
    754 }
    755 DEFAULT_ON_WAIT( block_spin_lock )
    756 static inline void on_wakeup( block_spin_lock & this, size_t recursion ) with(this) {
     656       
     657}
     658static inline size_t on_wait(block_spin_lock & this) { unlock(this); return 0; }
     659static inline void on_wakeup(block_spin_lock & this, size_t recursion ) with(this) {
     660  #ifdef REACQ
    757661        // now we acquire the entire block_spin_lock upon waking up
    758662        while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause();
    759663        __atomic_store_n(&held, true, __ATOMIC_RELEASE);
    760664        unlock( lock ); // Now we release the internal fast_spin_lock
    761 }
     665  #endif
     666}
     667
     668//-----------------------------------------------------------------------------
     669// is_blocking_lock
     670trait is_blocking_lock(L & | sized(L)) {
     671        // For synchronization locks to use when acquiring
     672        void on_notify( L &, struct thread$ * );
     673
     674        // For synchronization locks to use when releasing
     675        size_t on_wait( L & );
     676
     677        // to set recursion count after getting signalled;
     678        void on_wakeup( L &, size_t recursion );
     679};
    762680
    763681//-----------------------------------------------------------------------------
     
    767685forall(L & | is_blocking_lock(L)) {
    768686        struct info_thread;
     687
     688        // // for use by sequence
     689        // info_thread(L) *& Back( info_thread(L) * this );
     690        // info_thread(L) *& Next( info_thread(L) * this );
    769691}
    770692
  • libcfa/src/concurrency/monitor.cfa

    r24d6572 r34b4268  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Feb 19 17:00:59 2023
    13 // Update Count     : 12
     12// Last Modified On : Wed Dec  4 07:55:14 2019
     13// Update Count     : 10
    1414//
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819#include "monitor.hfa"
  • libcfa/src/concurrency/monitor.hfa

    r24d6572 r34b4268  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:29:21 2023
    13 // Update Count     : 12
     12// Last Modified On : Wed Dec  4 07:55:32 2019
     13// Update Count     : 11
    1414//
    1515
     
    2222#include "stdlib.hfa"
    2323
    24 forall( T & )
    25 trait is_monitor {
     24trait is_monitor(T &) {
    2625        monitor$ * get_monitor( T & );
    2726        void ^?{}( T & mutex );
  • libcfa/src/concurrency/mutex.cfa

    r24d6572 r34b4268  
    1212// Created On       : Fri May 25 01:37:11 2018
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Sun Feb 19 17:01:36 2023
    15 // Update Count     : 3
     14// Last Modified On : Wed Dec  4 09:16:39 2019
     15// Update Count     : 1
    1616//
    1717
    1818#define __cforall_thread__
     19#define _GNU_SOURCE
    1920
    2021#include "mutex.hfa"
  • libcfa/src/concurrency/mutex.hfa

    r24d6572 r34b4268  
    1212// Created On       : Fri May 25 01:24:09 2018
    1313// Last Modified By : Peter A. Buhr
    14 // Last Modified On : Thu Feb  2 11:46:08 2023
    15 // Update Count     : 2
     14// Last Modified On : Wed Dec  4 09:16:53 2019
     15// Update Count     : 1
    1616//
    1717
     
    7070void unlock(recursive_mutex_lock & this) __attribute__((deprecated("use concurrency/locks.hfa instead")));
    7171
    72 forall( L & | sized(L) )
    73 trait is_lock {
     72trait is_lock(L & | sized(L)) {
    7473        void lock  (L &);
    7574        void unlock(L &);
  • libcfa/src/concurrency/mutex_stmt.hfa

    r24d6572 r34b4268  
    1 #pragma once
    2 
    31#include "bits/algorithm.hfa"
    42#include "bits/defs.hfa"
     
    64//-----------------------------------------------------------------------------
    75// is_lock
    8 forall(L & | sized(L))
    9 trait is_lock {
     6trait is_lock(L & | sized(L)) {
    107        // For acquiring a lock
    118        void lock( L & );
     
    1411        void unlock( L & );
    1512};
     13
    1614
    1715struct __mutex_stmt_lock_guard {
     
    2624    // Sort locks based on address
    2725    __libcfa_small_sort(this.lockarr, count);
     26
     27    // acquire locks in order
     28    // for ( size_t i = 0; i < count; i++ ) {
     29    //     lock(*this.lockarr[i]);
     30    // }
     31}
     32
     33static inline void ^?{}( __mutex_stmt_lock_guard & this ) with(this) {
     34    // for ( size_t i = count; i > 0; i-- ) {
     35    //     unlock(*lockarr[i - 1]);
     36    // }
    2837}
    2938
    3039forall(L & | is_lock(L)) {
    31     static inline void * __get_mutexstmt_lock_ptr( L & this ) { return &this; }
    32     static inline L __get_mutexstmt_lock_type( L & this ) {}
    33     static inline L __get_mutexstmt_lock_type( L * this ) {}
     40
     41    struct scoped_lock {
     42        L * internal_lock;
     43    };
     44
     45    static inline void ?{}( scoped_lock(L) & this, L & internal_lock ) {
     46        this.internal_lock = &internal_lock;
     47        lock(internal_lock);
     48    }
     49   
     50    static inline void ^?{}( scoped_lock(L) & this ) with(this) {
     51        unlock(*internal_lock);
     52    }
     53
     54    static inline void * __get_mutexstmt_lock_ptr( L & this ) {
     55        return &this;
     56    }
     57
     58    static inline L __get_mutexstmt_lock_type( L & this );
     59
     60    static inline L __get_mutexstmt_lock_type( L * this );
    3461}
  • libcfa/src/concurrency/preemption.cfa

    r24d6572 r34b4268  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan  9 08:42:59 2023
    13 // Update Count     : 60
     12// Last Modified On : Thu Feb 17 11:18:57 2022
     13// Update Count     : 59
    1414//
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819// #define __CFA_DEBUG_PRINT_PREEMPTION__
     
    117118                __cfadbg_print_buffer_decl( preemption, " KERNEL: preemption tick %lu\n", currtime.tn);
    118119                Duration period = node->period;
    119                 if( period == 0 ) {
     120                if( period == 0) {
    120121                        node->set = false;                  // Node is one-shot, just mark it as not pending
    121122                }
  • libcfa/src/concurrency/pthread.cfa

    r24d6572 r34b4268  
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819#include <signal.h>
     
    3435struct pthread_values{
    3536        inline Seqable;
    36         void * value;
     37        void* value;
    3738        bool in_use;
    3839};
     
    5051struct pthread_keys {
    5152        bool in_use;
    52         void (* destructor)( void * );
     53        void (*destructor)( void * );
    5354        Sequence(pthread_values) threads;
    5455};
    5556
    56 static void ?{}(pthread_keys& k) {
     57static void ?{}(pthread_keys& k){
    5758        k.threads{};
    5859}
     
    6162static pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));
    6263
    63 static void init_pthread_storage() {
    64         for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) {
     64static void init_pthread_storage(){
     65        for (int i = 0; i < PTHREAD_KEYS_MAX; i++){
    6566                cfa_pthread_keys_storage[i]{};
    6667        }
     
    9596
    9697/* condvar helper routines */
    97 static void init(pthread_cond_t * pcond) {
     98static void init(pthread_cond_t* pcond){
    9899        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
    99         cfa2pthr_cond_var_t * _cond = (cfa2pthr_cond_var_t *)pcond;
     100        cfa2pthr_cond_var_t* _cond = (cfa2pthr_cond_var_t*)pcond;
    100101        ?{}(*_cond);
    101102}
    102103
    103 static cfa2pthr_cond_var_t * get(pthread_cond_t * pcond) {
     104static cfa2pthr_cond_var_t* get(pthread_cond_t* pcond){
    104105        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
    105         return (cfa2pthr_cond_var_t *)pcond;
    106 }
    107 
    108 static void destroy(pthread_cond_t * cond) {
     106        return (cfa2pthr_cond_var_t*)pcond;
     107}
     108
     109static void destroy(pthread_cond_t* cond){
    109110        static_assert(sizeof(pthread_cond_t) >= sizeof(cfa2pthr_cond_var_t),"sizeof(pthread_t) < sizeof(cfa2pthr_cond_var_t)");
    110111        ^?{}(*get(cond));
     
    115116
    116117/* mutex helper routines */
    117 static void mutex_check(pthread_mutex_t * t) {
     118static void mutex_check(pthread_mutex_t* t){
    118119        // Use double check to improve performance.
    119120        // Check is safe on x86; volatile prevents compiler reordering
    120         volatile pthread_mutex_t * const mutex_ = t;
     121        volatile pthread_mutex_t *const mutex_ = t;
    121122
    122123        // SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h
     
    135136
    136137
    137 static void init(pthread_mutex_t * plock) {
     138static void init(pthread_mutex_t* plock){
    138139        static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
    139         simple_owner_lock * _lock = (simple_owner_lock *)plock;
     140        simple_owner_lock* _lock = (simple_owner_lock*)plock;
    140141        ?{}(*_lock);
    141142}
    142143
    143 static simple_owner_lock * get(pthread_mutex_t * plock) {
     144static simple_owner_lock* get(pthread_mutex_t* plock){
    144145        static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
    145         return (simple_owner_lock *)plock;
    146 }
    147 
    148 static void destroy(pthread_mutex_t * plock) {
     146        return (simple_owner_lock*)plock;
     147}
     148
     149static void destroy(pthread_mutex_t* plock){
    149150        static_assert(sizeof(pthread_mutex_t) >= sizeof(simple_owner_lock),"sizeof(pthread_mutex_t) < sizeof(simple_owner_lock)");
    150151        ^?{}(*get(plock));
     
    152153
    153154//######################### Attr helpers #########################
    154 typedef struct cfaPthread_attr_t {                                              // thread attributes
     155struct cfaPthread_attr_t {                                                              // thread attributes
    155156                int contentionscope;
    156157                int detachstate;
    157158                size_t stacksize;
    158                 void * stackaddr;
     159                void *stackaddr;
    159160                int policy;
    160161                int inheritsched;
    161162                struct sched_param param;
    162 } cfaPthread_attr_t;
    163 
    164 static const cfaPthread_attr_t default_attrs {
     163} typedef cfaPthread_attr_t;
     164
     165static const cfaPthread_attr_t default_attrs{
    165166        0,
    166167        0,
    167         65_000,
    168         NULL,
     168        (size_t)65000,
     169        (void *)NULL,
    169170        0,
    170171        0,
     
    172173};
    173174
    174 static cfaPthread_attr_t * get(const pthread_attr_t * attr) {
    175         static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t), "sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)");
    176         return (cfaPthread_attr_t *)attr;
     175static cfaPthread_attr_t* get(const pthread_attr_t* attr){
     176        static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t),"sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)");
     177        return (cfaPthread_attr_t*)attr;
    177178}
    178179
     
    189190
    190191        // pthreads return value
    191         void * joinval;
     192        void *joinval;
    192193
    193194        // pthread attributes
    194195        pthread_attr_t pthread_attr;
    195196
    196         void *(* start_routine)(void *);
    197         void * start_arg;
     197        void *(*start_routine)(void *);
     198        void *start_arg;
    198199
    199200        // thread local data
    200         pthread_values * pthreadData;
     201        pthread_values* pthreadData;
    201202
    202203        // flag used for tryjoin
     
    206207/* thread part routines */
    207208//  cfaPthread entry point
    208 void main(cfaPthread & _thread) with(_thread) {
    209         joinval = start_routine(start_arg);
     209void main(cfaPthread& _thread) with(_thread){
     210        joinval =  start_routine(start_arg);
    210211        isTerminated = true;
    211212}
    212213
    213 static cfaPthread * lookup( pthread_t p ) {
    214         static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *),"sizeof(pthread_t) < sizeof(cfaPthread *)");
    215         return (cfaPthread *)p;
    216 }
    217 
    218 static void pthread_deletespecific_( pthread_values * values )  { // see uMachContext::invokeTask
    219         pthread_values * value;
    220         pthread_keys * key;
     214static cfaPthread *lookup( pthread_t p ){
     215        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");
     216        return (cfaPthread*)p;
     217}
     218
     219static void pthread_deletespecific_( pthread_values* values )  { // see uMachContext::invokeTask
     220        pthread_values* value;
     221        pthread_keys* key;
    221222        bool destcalled = true;
    222         if (values != NULL) {
     223        if (values != NULL){
    223224                for ( int attempts = 0; attempts < PTHREAD_DESTRUCTOR_ITERATIONS && destcalled ; attempts += 1 ) {
    224225                        destcalled = false;
    225226                        lock(key_lock);
    226                         for ( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) {
     227                        for (int i = 0; i < PTHREAD_KEYS_MAX; i++){
    227228                                // for each valid key
    228                                 if ( values[i].in_use) {
     229                                if ( values[i].in_use){
    229230                                        value = &values[i];
    230231                                        key = &cfa_pthread_keys[i];
     
    233234                                        // if  a  key  value  has  a  non-NULL  destructor pointer,  and  the  thread  has  a  non-NULL  value associated with that key,
    234235                                        // the value of the key is set to NULL, and then the function pointed to is called with the previously associated value as its sole argument.
    235                                         if (value->value != NULL && key->destructor != NULL) {
     236                                        if (value->value != NULL && key->destructor != NULL){
    236237                                                unlock(key_lock);
    237238                                                key->destructor(value->value); // run destructor
     
    248249}
    249250
    250 static void ^?{}(cfaPthread & mutex t) {
     251static void ^?{}(cfaPthread & mutex t){
    251252        // delete pthread local storage
    252253        pthread_values * values = t.pthreadData;
     
    254255}
    255256
    256 static void ?{}(cfaPthread & t, pthread_t * _thread, const pthread_attr_t * _attr,void *(* start_routine)(void *), void * arg) {
    257         static_assert(sizeof(pthread_t) >= sizeof(cfaPthread *), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread *)");
     257static void ?{}(cfaPthread &t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) {
     258        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread*)");
    258259
    259260        // set up user thread stackSize
     
    277278        //######################### Pthread Attrs #########################
    278279
    279         int pthread_attr_init(pthread_attr_t * attr) libcfa_public __THROW {
    280                 cfaPthread_attr_t * _attr = get(attr);
     280        int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW {
     281                cfaPthread_attr_t* _attr = get(attr);
    281282                ?{}(*_attr, default_attrs);
    282283                return 0;
    283284        }
    284         int pthread_attr_destroy(pthread_attr_t * attr) libcfa_public __THROW {
     285        int pthread_attr_destroy(pthread_attr_t *attr) libcfa_public __THROW {
    285286                ^?{}(*get(attr));
    286287                return 0;
    287288        }
    288289
    289         int pthread_attr_setscope( pthread_attr_t * attr, int contentionscope ) libcfa_public __THROW {
     290        int pthread_attr_setscope( pthread_attr_t *attr, int contentionscope ) libcfa_public __THROW {
    290291                get( attr )->contentionscope = contentionscope;
    291292                return 0;
    292293        } // pthread_attr_setscope
    293294
    294         int pthread_attr_getscope( const pthread_attr_t * attr, int * contentionscope ) libcfa_public __THROW {
     295        int pthread_attr_getscope( const pthread_attr_t *attr, int *contentionscope ) libcfa_public __THROW {
    295296                *contentionscope = get( attr )->contentionscope;
    296297                return 0;
    297298        } // pthread_attr_getscope
    298299
    299         int pthread_attr_setdetachstate( pthread_attr_t * attr, int detachstate ) libcfa_public __THROW {
     300        int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate ) libcfa_public __THROW {
    300301                get( attr )->detachstate = detachstate;
    301302                return 0;
    302303        } // pthread_attr_setdetachstate
    303304
    304         int pthread_attr_getdetachstate( const pthread_attr_t * attr, int * detachstate ) libcfa_public __THROW {
     305        int pthread_attr_getdetachstate( const pthread_attr_t *attr, int *detachstate ) libcfa_public __THROW {
    305306                *detachstate = get( attr )->detachstate;
    306307                return 0;
    307308        } // pthread_attr_getdetachstate
    308309
    309         int pthread_attr_setstacksize( pthread_attr_t * attr, size_t stacksize ) libcfa_public __THROW {
     310        int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize ) libcfa_public __THROW {
    310311                get( attr )->stacksize = stacksize;
    311312                return 0;
    312313        } // pthread_attr_setstacksize
    313314
    314         int pthread_attr_getstacksize( const pthread_attr_t * attr, size_t * stacksize ) libcfa_public __THROW {
     315        int pthread_attr_getstacksize( const pthread_attr_t *attr, size_t *stacksize ) libcfa_public __THROW {
    315316                *stacksize = get( attr )->stacksize;
    316317                return 0;
     
    325326        } // pthread_attr_setguardsize
    326327
    327         int pthread_attr_setstackaddr( pthread_attr_t * attr, void * stackaddr ) libcfa_public __THROW {
     328        int pthread_attr_setstackaddr( pthread_attr_t *attr, void *stackaddr ) libcfa_public __THROW {
    328329                get( attr )->stackaddr = stackaddr;
    329330                return 0;
    330331        } // pthread_attr_setstackaddr
    331332
    332         int pthread_attr_getstackaddr( const pthread_attr_t * attr, void ** stackaddr ) libcfa_public __THROW {
     333        int pthread_attr_getstackaddr( const pthread_attr_t *attr, void **stackaddr ) libcfa_public __THROW {
    333334                *stackaddr = get( attr )->stackaddr;
    334335                return 0;
    335336        } // pthread_attr_getstackaddr
    336337
    337         int pthread_attr_setstack( pthread_attr_t * attr, void * stackaddr, size_t stacksize ) libcfa_public __THROW {
     338        int pthread_attr_setstack( pthread_attr_t *attr, void *stackaddr, size_t stacksize ) libcfa_public __THROW {
    338339                get( attr )->stackaddr = stackaddr;
    339340                get( attr )->stacksize = stacksize;
     
    341342        } // pthread_attr_setstack
    342343
    343         int pthread_attr_getstack( const pthread_attr_t * attr, void ** stackaddr, size_t * stacksize ) libcfa_public __THROW {
     344        int pthread_attr_getstack( const pthread_attr_t *attr, void **stackaddr, size_t *stacksize ) libcfa_public __THROW {
    344345                *stackaddr = get( attr )->stackaddr;
    345346                *stacksize = get( attr )->stacksize;
     
    350351        // already running thread threadID. It shall be called on unitialized attr
    351352        // and destroyed with pthread_attr_destroy when no longer needed.
    352         int pthread_getattr_np( pthread_t threadID, pthread_attr_t * attr ) libcfa_public __THROW { // GNU extension
     353        int pthread_getattr_np( pthread_t threadID, pthread_attr_t *attr ) libcfa_public __THROW { // GNU extension
    353354                check_nonnull(attr);
    354355
     
    362363        //######################### Threads #########################
    363364
    364         int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(* start_routine)(void *), void * arg) libcfa_public __THROW {
    365                 cfaPthread * t = alloc();
     365        int pthread_create(pthread_t * _thread, const pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) libcfa_public __THROW {
     366                cfaPthread *t = alloc();
    366367                (*t){_thread, attr, start_routine, arg};
    367368                return 0;
    368369        }
    369370
    370         int pthread_join(pthread_t _thread, void ** value_ptr) libcfa_public __THROW {
     371
     372        int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
    371373                // if thread is invalid
    372374                if (_thread == NULL) return EINVAL;
     
    374376
    375377                // get user thr pointer
    376                 cfaPthread * p = lookup(_thread);
     378                cfaPthread* p = lookup(_thread);
    377379                try {
    378380                        join(*p);
     
    387389        }
    388390
    389         int pthread_tryjoin_np(pthread_t _thread, void ** value_ptr) libcfa_public __THROW {
     391        int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
    390392                // if thread is invalid
    391393                if (_thread == NULL) return EINVAL;
    392394                if (_thread == pthread_self()) return EDEADLK;
    393395
    394                 cfaPthread * p = lookup(_thread);
     396                cfaPthread* p = lookup(_thread);
    395397
    396398                // thread not finished ?
     
    410412        void pthread_exit(void * status) libcfa_public __THROW {
    411413                pthread_t pid = pthread_self();
    412                 cfaPthread * _thread = (cfaPthread *)pid;
     414                cfaPthread* _thread = (cfaPthread*)pid;
    413415                _thread->joinval = status;  // set return value
    414416                _thread->isTerminated = 1;  // set terminated flag
     
    424426        //######################### Mutex #########################
    425427
    426         int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t * attr) libcfa_public __THROW {
     428        int pthread_mutex_init(pthread_mutex_t *_mutex, const pthread_mutexattr_t *attr) libcfa_public __THROW {
    427429                check_nonnull(_mutex);
    428430                init(_mutex);
     
    433435        int pthread_mutex_destroy(pthread_mutex_t *_mutex) libcfa_public __THROW {
    434436                check_nonnull(_mutex);
    435                 simple_owner_lock * _lock = get(_mutex);
    436                 if (_lock->owner != NULL) {
     437                simple_owner_lock* _lock = get(_mutex);
     438                if (_lock->owner != NULL){
    437439                        return EBUSY;
    438440                }
     
    444446                check_nonnull(_mutex);
    445447                mutex_check(_mutex);
    446                 simple_owner_lock * _lock = get(_mutex);
     448                simple_owner_lock* _lock = get(_mutex);
    447449                lock(*_lock);
    448450                return 0;
     
    451453        int pthread_mutex_unlock(pthread_mutex_t *_mutex) libcfa_public __THROW {
    452454                check_nonnull(_mutex);
    453                 simple_owner_lock * _lock = get(_mutex);
    454                 if (_lock->owner != active_thread()) {
     455                simple_owner_lock* _lock = get(_mutex);
     456                if (_lock->owner != active_thread()){
    455457                        return EPERM;
    456458                } // current thread does not hold the mutex
     
    461463        int pthread_mutex_trylock(pthread_mutex_t *_mutex) libcfa_public __THROW {
    462464                check_nonnull(_mutex);
    463                 simple_owner_lock * _lock = get(_mutex);
    464                 if (_lock->owner != active_thread() && _lock->owner != NULL) {
     465                simple_owner_lock* _lock = get(_mutex);
     466                if (_lock->owner != active_thread() && _lock->owner != NULL){
    465467                        return EBUSY;
    466468                }   // if mutex is owned
     
    472474
    473475        /* conditional variable routines */
    474         int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr) libcfa_public __THROW {
     476        int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) libcfa_public __THROW {
    475477                check_nonnull(cond);
    476478                init(cond);
     
    478480        }  //pthread_cond_init
    479481
    480         int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t *_mutex) libcfa_public __THROW {
     482        int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *_mutex) libcfa_public __THROW {
    481483                check_nonnull(_mutex);
    482484                check_nonnull(cond);
     
    492494        } // pthread_cond_timedwait
    493495
    494         int pthread_cond_signal(pthread_cond_t * cond) libcfa_public __THROW {
     496        int pthread_cond_signal(pthread_cond_t *cond) libcfa_public __THROW {
    495497                check_nonnull(cond);
    496498                return notify_one(*get(cond));
    497499        } // pthread_cond_signal
    498500
    499         int pthread_cond_broadcast(pthread_cond_t * cond) libcfa_public __THROW {
     501        int pthread_cond_broadcast(pthread_cond_t *cond) libcfa_public __THROW {
    500502                check_nonnull(cond);
    501503                return notify_all(*get(cond));
    502504        } // pthread_cond_broadcast
    503505
    504         int pthread_cond_destroy(pthread_cond_t * cond) libcfa_public __THROW {
     506        int pthread_cond_destroy(pthread_cond_t *cond) libcfa_public __THROW {
    505507                check_nonnull(cond);
    506508                destroy(cond);
     
    512514        //######################### Local storage #########################
    513515
    514         int pthread_once(pthread_once_t * once_control, void (* init_routine)(void)) libcfa_public __THROW {
     516        int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) libcfa_public __THROW {
    515517                static_assert(sizeof(pthread_once_t) >= sizeof(int),"sizeof(pthread_once_t) < sizeof(int)");
    516518                check_nonnull(once_control);
     
    525527        } // pthread_once
    526528
    527         int pthread_key_create( pthread_key_t * key, void (* destructor)( void * ) ) libcfa_public __THROW {
     529        int pthread_key_create( pthread_key_t *key, void (*destructor)( void * ) ) libcfa_public __THROW {
    528530                lock(key_lock);
    529531                for ( int i = 0; i < PTHREAD_KEYS_MAX; i += 1 ) {
     
    560562        }   // pthread_key_delete
    561563
    562         int pthread_setspecific( pthread_key_t key, const void * value ) libcfa_public __THROW {
     564        int pthread_setspecific( pthread_key_t key, const void *value ) libcfa_public __THROW {
    563565                // get current thread
    564                 cfaPthread * t = lookup(pthread_self());
     566                cfaPthread* t = lookup(pthread_self());
    565567                // if current thread's pthreadData is NULL; initialize it
    566                 pthread_values * values;
    567                 if (t->pthreadData == NULL) {
     568                pthread_values* values;
     569                if (t->pthreadData == NULL){
    568570                        values = anew( PTHREAD_KEYS_MAX);
    569571                        t->pthreadData = values;
    570                         for ( int i = 0;i < PTHREAD_KEYS_MAX; i++ ) {
     572                        for (int i = 0;i < PTHREAD_KEYS_MAX; i++){
    571573                                t->pthreadData[i].in_use = false;
    572574                        }   // for
     
    591593        } //pthread_setspecific
    592594
    593         void * pthread_getspecific(pthread_key_t key) libcfa_public __THROW {
     595        void* pthread_getspecific(pthread_key_t key) libcfa_public __THROW {
    594596                if (key >= PTHREAD_KEYS_MAX || ! cfa_pthread_keys[key].in_use) return NULL;
    595597
    596598                // get current thread
    597                 cfaPthread * t = lookup(pthread_self());
     599                cfaPthread* t = lookup(pthread_self());
    598600                if (t->pthreadData == NULL) return NULL;
    599601                lock(key_lock);
    600                 pthread_values & entry = ((pthread_values *)t->pthreadData)[key];
     602                pthread_values &entry = ((pthread_values *)t->pthreadData)[key];
    601603                if ( ! entry.in_use ) {
    602604                        unlock( key_lock );
    603605                        return NULL;
    604606                } // if
    605                 void * value = entry.value;
     607                void *value = entry.value;
    606608                unlock(key_lock);
    607609
     
    873875        //######################### Parallelism #########################
    874876
    875         // int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
    876         //      abort( "pthread_setaffinity_np" );
    877         // } // pthread_setaffinity_np
    878 
    879         // int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
    880         //      abort( "pthread_getaffinity_np" );
    881         // } // pthread_getaffinity_np
    882 
    883         // int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
    884         //      abort( "pthread_attr_setaffinity_np" );
    885         // } // pthread_attr_setaffinity_np
    886 
    887         // int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
    888         //      abort( "pthread_attr_getaffinity_np" );
    889         // } // pthread_attr_getaffinity_np
     877        int pthread_setaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
     878                abort( "pthread_setaffinity_np" );
     879        } // pthread_setaffinity_np
     880
     881        int pthread_getaffinity_np( pthread_t /* __th */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
     882                abort( "pthread_getaffinity_np" );
     883        } // pthread_getaffinity_np
     884
     885        int pthread_attr_setaffinity_np( pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, __const cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
     886                abort( "pthread_attr_setaffinity_np" );
     887        } // pthread_attr_setaffinity_np
     888
     889        int pthread_attr_getaffinity_np( __const pthread_attr_t * /* __attr */, size_t /* __cpusetsize */, cpu_set_t * /* __cpuset */ ) libcfa_public __THROW {
     890                abort( "pthread_attr_getaffinity_np" );
     891        } // pthread_attr_getaffinity_np
    890892
    891893        //######################### Cancellation #########################
     
    904906        } // pthread_cancel
    905907
    906         int pthread_setcancelstate( int state, int * oldstate ) libcfa_public __THROW {
     908        int pthread_setcancelstate( int state, int *oldstate ) libcfa_public __THROW {
    907909                abort("pthread_setcancelstate not implemented");
    908910                return 0;
    909911        } // pthread_setcancelstate
    910912
    911         int pthread_setcanceltype( int type, int * oldtype ) libcfa_public __THROW {
     913        int pthread_setcanceltype( int type, int *oldtype ) libcfa_public __THROW {
    912914                abort("pthread_setcanceltype not implemented");
    913915                return 0;
     
    916918
    917919#pragma GCC diagnostic pop
     920
  • libcfa/src/concurrency/ready_queue.cfa

    r24d6572 r34b4268  
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819// #define __CFA_DEBUG_PRINT_READY_QUEUE__
  • libcfa/src/concurrency/thread.cfa

    r24d6572 r34b4268  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan  9 08:42:33 2023
    13 // Update Count     : 103
     12// Last Modified On : Sun Dec 11 20:56:54 2022
     13// Update Count     : 102
    1414//
    1515
    1616#define __cforall_thread__
     17#define _GNU_SOURCE
    1718
    1819#include "thread.hfa"
     
    5354        preferred = ready_queue_new_preferred();
    5455        last_proc = 0p;
    55     link_node = 0p;
    5656        PRNG_SET_SEED( random_state, __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl() );
    5757        #if defined( __CFA_WITH_VERIFY__ )
     
    6060        #endif
    6161
     62        clh_node = malloc( );
     63        *clh_node = false;
     64
    6265        doregister(curr_cluster, this);
    6366        monitors{ &self_mon_p, 1, (fptr_t)0 };
     
    6871                canary = 0xDEADDEADDEADDEADp;
    6972        #endif
     73        free(clh_node);
    7074        unregister(curr_cluster, this);
    7175        ^self_cor{};
  • libcfa/src/concurrency/thread.hfa

    r24d6572 r34b4268  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:27:59 2023
    13 // Update Count     : 37
     12// Last Modified On : Tue Nov 22 22:18:34 2022
     13// Update Count     : 35
    1414//
    1515
     
    2727//-----------------------------------------------------------------------------
    2828// thread trait
    29 forall( T & )
    30 trait is_thread {
     29trait is_thread(T &) {
    3130        void ^?{}(T& mutex this);
    3231        void main(T& this);
  • libcfa/src/containers/array.hfa

    r24d6572 r34b4268  
    99
    1010
    11 //
    12 // The `array` macro is the public interface.
    13 // It computes the type of a dense (trivially strided) array.
    14 // All user-declared objects are dense arrays.
    15 //
    16 // The `arpk` (ARray with PacKing info explicit) type is, generally, a slice with _any_ striding.
    17 // This type is meant for internal use.
    18 // CFA programmers should not instantiate it directly, nor access its field.
    19 // CFA programmers should call ?[?] on it.
    20 // Yet user-given `array(stuff)` expands to `arpk(stuff')`.
    21 // The comments here explain the resulting internals.
    22 //
    23 // Just as a plain-C "multidimesional" array is really array-of-array-of-...,
    24 // so does arpk generally show up as arpk-of-arpk-of...
    25 //
    26 // In the example of `array(float, 3, 4, 5) a;`,
    27 // `typeof(a)` is an `arpk` instantiation.
    28 // These comments explain _its_ arguments, i.e. those of the topmost `arpk` level.
    29 //
    30 // [N]    : the number of elements in `a`; 3 in the example
    31 // S      : carries the stride size (distance in bytes between &myA[0] and &myA[1]), in sizeof(S);
    32 //          same as Timmed when striding is trivial, same as Timmed in the example
    33 // Timmed : (T-immediate) the inner type; conceptually, `typeof(a)` is "arpk of Timmed";
    34 //          array(float, 4, 5) in the example
    35 // Tbase  : (T-base) the deepest element type that is not arpk; float in the example
    36 //
     11//
     12// Single-dim array sruct (with explicit packing and atom)
     13//
     14
    3715forall( [N], S & | sized(S), Timmed &, Tbase & ) {
    38 
    39     //
    40     // Single-dim array sruct (with explicit packing and atom)
    41     //
    4216    struct arpk {
    4317        S strides[N];
  • libcfa/src/containers/list.hfa

    r24d6572 r34b4268  
    99// Author           : Michael Brooks
    1010// Created On       : Wed Apr 22 18:00:00 2020
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:32:26 2023
    13 // Update Count     : 2
     11// Last Modified By : Michael Brooks
     12// Last Modified On : Wed Apr 22 18:00:00 2020
     13// Update Count     : 1
    1414//
    1515
     
    2323};
    2424
    25 forall( tOuter &, tMid &, tInner & )
    26 trait embedded {
     25trait embedded( tOuter &, tMid &, tInner & ) {
    2726    tytagref( tMid, tInner ) ?`inner( tOuter & );
    2827};
     
    3231static inline tytagref(void, T) ?`inner ( T & this ) { tytagref( void, T ) ret = {this}; return ret; }
    3332
    34 
    35 //
    36 // P9_EMBEDDED: Use on every case of plan-9 inheritance, to make "implements embedded" be a closure of plan-9 inheritance.
    37 //
    38 // struct foo {
    39 //    int a, b, c;
    40 //    inline (bar);
    41 // };
    42 // P9_EMBEDDED( foo, bar )
    43 //
    44 
    45 // usual version, for structs that are top-level declarations
    46 #define P9_EMBEDDED(        derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, static ) P9_EMBEDDED_BDY_( immedBase )
    47 
    48 // special version, for structs that are declared in functions
    49 #define P9_EMBEDDED_INFUNC( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase,        ) P9_EMBEDDED_BDY_( immedBase )
    50 
    51 // forward declarations of both the above; generally not needed
    52 // may help you control where the P9_EMBEEDED cruft goes, in case "right after the stuct" isn't where you want it
    53 #define P9_EMBEDDED_FWD(        derived, immedBase )      P9_EMBEDDED_DECL_( derived, immedBase, static ) ;
    54 #define P9_EMBEDDED_FWD_INFUNC( derived, immedBase ) auto P9_EMBEDDED_DECL_( derived, immedBase,        ) ;
    55 
    56 // private helpers
    57 #define P9_EMBEDDED_DECL_( derived, immedBase, STORAGE ) \
    58     forall( Tbase &, TdiscardPath & | { tytagref( TdiscardPath, Tbase ) ?`inner( immedBase & ); } ) \
    59     STORAGE inline tytagref(immedBase, Tbase) ?`inner( derived & this )
    60    
    61 #define P9_EMBEDDED_BDY_( immedBase ) { \
     33// use this on every case of plan-9 inheritance, to make embedded a closure of plan-9 inheritance
     34#define P9_EMBEDDED( derived, immedBase ) \
     35forall( Tbase &, TdiscardPath & | { tytagref( TdiscardPath, Tbase ) ?`inner( immedBase & ); } ) \
     36    static inline tytagref(immedBase, Tbase) ?`inner( derived & this ) { \
    6237        immedBase & ib = this; \
    6338        Tbase & b = ib`inner; \
  • libcfa/src/containers/vector.hfa

    r24d6572 r34b4268  
    1010// Created On       : Tue Jul  5 18:00:07 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:41:24 2023
    13 // Update Count     : 5
     12// Last Modified On : Wed Jun 17 11:02:46 2020
     13// Update Count     : 4
    1414//
    1515
     
    5050//------------------------------------------------------------------------------
    5151//Declaration
    52 forall( T, allocator_t )
    53 trait allocator_c {
     52trait allocator_c(T, allocator_t)
     53{
    5454        void realloc_storage(allocator_t*, size_t);
    5555        T* data(allocator_t*);
  • libcfa/src/containers/vector2.hfa

    r24d6572 r34b4268  
    99// Author           : Michael Brooks
    1010// Created On       : Thu Jun 23 22:00:00 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar 14 08:40:53 2023
    13 // Update Count     : 2
    14 //
    15 
    16 #pragma once
     11// Last Modified By : Michael Brooks
     12// Last Modified On : Thu Jun 23 22:00:00 2021
     13// Update Count     : 1
     14//
    1715
    1816#include <stdlib.hfa>
  • libcfa/src/exception.h

    r24d6572 r34b4268  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:11:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:20:19 2023
    13 // Update Count     : 13
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Apr  8 15:20:00 2021
     13// Update Count     : 12
    1414//
    1515
     
    101101// implemented in the .c file either so they all have to be inline.
    102102
    103 forall( exceptT &, virtualT & )
    104 trait is_exception {
     103trait is_exception(exceptT &, virtualT &) {
    105104        /* The first field must be a pointer to a virtual table.
    106105         * That virtual table must be a decendent of the base exception virtual table.
     
    110109};
    111110
    112 forall( exceptT &, virtualT & | is_exception(exceptT, virtualT) )
    113 trait is_termination_exception {
     111trait is_termination_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
    114112        void defaultTerminationHandler(exceptT &);
    115113};
    116114
    117 forall( exceptT &, virtualT & | is_exception(exceptT, virtualT) )
    118 trait is_resumption_exception {
     115trait is_resumption_exception(exceptT &, virtualT & | is_exception(exceptT, virtualT)) {
    119116        void defaultResumptionHandler(exceptT &);
    120117};
  • libcfa/src/heap.cfa

    r24d6572 r34b4268  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 30 08:37:37 2022
    13 // Update Count     : 1605
     12// Last Modified On : Sun Oct 30 20:56:20 2022
     13// Update Count     : 1584
    1414//
    1515
     
    1717#include <string.h>                                                                             // memset, memcpy
    1818#include <limits.h>                                                                             // ULONG_MAX
     19#include <stdlib.h>                                                                             // EXIT_FAILURE
    1920#include <errno.h>                                                                              // errno, ENOMEM, EINVAL
    20 #include <unistd.h>                                                                             // STDERR_FILENO, sbrk, sysconf, write
     21#include <unistd.h>                                                                             // STDERR_FILENO, sbrk, sysconf
     22#include <malloc.h>                                                                             // memalign, malloc_usable_size
    2123#include <sys/mman.h>                                                                   // mmap, munmap
    2224extern "C" {
     
    2426} // extern "C"
    2527
    26 #include "heap.hfa"
    2728#include "bits/align.hfa"                                                               // libAlign
    2829#include "bits/defs.hfa"                                                                // likely, unlikely
     
    139140#endif
    140141
    141 typedef volatile uintptr_t SpinLock_t;
     142typedef volatile uintptr_t SpinLock_t CALIGN;                   // aligned addressable word-size
    142143
    143144static inline __attribute__((always_inline)) void lock( volatile SpinLock_t & slock ) {
     
    146147
    147148        for ( unsigned int i = 1;; i += 1 ) {
    148           if ( slock == 0 && __atomic_test_and_set( &slock, __ATOMIC_ACQUIRE ) == 0 ) break; // Fence
     149          if ( slock == 0 && __atomic_test_and_set( &slock, __ATOMIC_SEQ_CST ) == 0 ) break; // Fence
    149150                for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause(); // exponential spin
    150151                spin += spin;                                                                   // powers of 2
     
    155156
    156157static inline __attribute__((always_inline)) void unlock( volatile SpinLock_t & slock ) {
    157         __atomic_clear( &slock, __ATOMIC_RELEASE );                     // Fence
     158        __atomic_clear( &slock, __ATOMIC_SEQ_CST );                     // Fence
    158159} // spin_unlock
    159160
     
    260261        static_assert( libAlign() >= sizeof( Storage ), "minimum alignment < sizeof( Storage )" );
    261262
    262         struct CALIGN FreeHeader {
    263                 size_t blockSize CALIGN;                                                // size of allocations on this list
     263        struct __attribute__(( aligned (8) )) FreeHeader {
     264                size_t blockSize __attribute__(( aligned(8) )); // size of allocations on this list
    264265                #ifdef OWNERSHIP
    265266                #ifdef RETURNSPIN
     
    283284
    284285        #ifdef __CFA_DEBUG__
    285         ptrdiff_t allocUnfreed;                                                         // running total of allocations minus frees; can be negative
     286        int64_t allocUnfreed;                                                           // running total of allocations minus frees; can be negative
    286287        #endif // __CFA_DEBUG__
    287288
     
    368369// Thread-local storage is allocated lazily when the storage is accessed.
    369370static __thread size_t PAD1 CALIGN TLSMODEL __attribute__(( unused )); // protect false sharing
    370 static __thread Heap * heapManager CALIGN TLSMODEL;
     371static __thread Heap * volatile heapManager CALIGN TLSMODEL;
    371372static __thread size_t PAD2 CALIGN TLSMODEL __attribute__(( unused )); // protect further false sharing
    372373
     
    442443                // 12K ~= 120K byte superblock.  Where 128-heap superblock handles a medium sized multi-processor server.
    443444                size_t remaining = heapManagersStorageEnd - heapManagersStorage; // remaining free heaps in superblock
    444                 if ( ! heapManagersStorage || remaining == 0 ) {
     445                if ( ! heapManagersStorage || remaining != 0 ) {
    445446                        // Each block of heaps is a multiple of the number of cores on the computer.
    446447                        int HeapDim = get_nprocs();                                     // get_nprocs_conf does not work
     
    561562                // allocUnfreed is set to 0 when a heap is created and it accumulates any unfreed storage during its multiple thread
    562563                // usages.  At the end, add up each heap allocUnfreed value across all heaps to get the total unfreed storage.
    563                 ptrdiff_t allocUnfreed = 0;
     564                int64_t allocUnfreed = 0;
    564565                for ( Heap * heap = heapMaster.heapManagersList; heap; heap = heap->nextHeapManager ) {
    565566                        allocUnfreed += heap->allocUnfreed;
     
    571572                        char helpText[512];
    572573                        __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    573                                                                                 "CFA warning (UNIX pid:%ld) : program terminating with %td(%#tx) bytes of storage allocated but not freed.\n"
     574                                                                                "CFA warning (UNIX pid:%ld) : program terminating with %ju(0x%jx) bytes of storage allocated but not freed.\n"
    574575                                                                                "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    575576                                                                                (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid
     
    805806
    806807        ptrdiff_t rem = heapRemaining - size;
    807         if ( unlikely( rem < 0 ) ) {                                            // negative ?
     808        if ( unlikely( rem < 0 ) ) {
    808809                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    809810
     
    841842        ptrdiff_t rem = heapReserve - size;
    842843
    843         if ( unlikely( rem < 0 ) ) {                                            // negative ?
     844        if ( unlikely( rem < 0 ) ) {                                            // negative
    844845                // If the size requested is bigger than the current remaining reserve, use the current reserve to populate
    845846                // smaller freeLists, and increase the reserve.
     
    847848                rem = heapReserve;                                                              // positive
    848849
    849                 if ( (unsigned int)rem >= bucketSizes[0] ) {    // minimal size ? otherwise ignore
     850                if ( rem >= bucketSizes[0] ) {                                  // minimal size ? otherwise ignore
    850851                        size_t bucket;
    851852                        #ifdef FASTLOOKUP
     
    856857                        Heap.FreeHeader * freeHead = &(freeLists[bucket]);
    857858
    858                         // The remaining storage may not be bucket size, whereas all other allocations are. Round down to previous
     859                        // The remaining storage many not be bucket size, whereas all other allocations are. Round down to previous
    859860                        // bucket size in this case.
    860861                        if ( unlikely( freeHead->blockSize > (size_t)rem ) ) freeHead -= 1;
     
    949950                block = freeHead->freeList;                                             // remove node from stack
    950951                if ( unlikely( block == 0p ) ) {                                // no free block ?
    951                         // Freelist for this size is empty, so check return list (OWNERSHIP), or carve it out of the heap if there
     952                        // Freelist for this size is empty, so check return list (OWNERSHIP), carve it out of the heap, if there
    952953                        // is enough left, or get some more heap storage and carve it off.
    953954                        #ifdef OWNERSHIP
     
    11141115                        while ( ! __atomic_compare_exchange_n( &freeHead->returnList, &header->kind.real.next, (Heap.Storage *)header,
    11151116                                                                                                   false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) );
    1116 
    1117                         #ifdef __STATISTICS__
    1118                         stats.return_pushes += 1;
    1119                         stats.return_storage_request += rsize;
    1120                         stats.return_storage_alloc += size;
    1121                         #endif // __STATISTICS__
    11221117                        #endif // RETURNSPIN
    11231118                } // if
     
    11301125                freeHead->freeList = (Heap.Storage *)header;
    11311126                #endif // ! OWNERSHIP
     1127
     1128                #ifdef __U_STATISTICS__
     1129                stats.return_pushes += 1;
     1130                stats.return_storage_request += rsize;
     1131                stats.return_storage_alloc += size;
     1132                #endif // __U_STATISTICS__
    11321133
    11331134                // OK TO BE PREEMPTED HERE AS heapManager IS NO LONGER ACCESSED.
     
    11791180
    11801181#ifdef __STATISTICS__
    1181 static void incCalls( size_t statName ) libcfa_nopreempt {
     1182static void incCalls( intptr_t statName ) libcfa_nopreempt {
    11821183        heapManager->stats.counters[statName].calls += 1;
    11831184} // incCalls
    11841185
    1185 static void incZeroCalls( size_t statName ) libcfa_nopreempt {
     1186static void incZeroCalls( intptr_t statName ) libcfa_nopreempt {
    11861187        heapManager->stats.counters[statName].calls_0 += 1;
    11871188} // incZeroCalls
     
    14551456        // 0p, no operation is performed.
    14561457        void free( void * addr ) libcfa_public {
     1458//              verify( heapManager );
     1459
    14571460          if ( unlikely( addr == 0p ) ) {                                       // special case
    14581461                        #ifdef __STATISTICS__
  • libcfa/src/interpose.cfa

    r24d6572 r34b4268  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 27 21:09:03 2023
    13 // Update Count     : 196
    14 //
    15 
     12// Last Modified On : Fri Mar 13 17:35:37 2020
     13// Update Count     : 178
     14//
     15
     16#include <stdarg.h>                                                                             // va_start, va_end
    1617#include <stdio.h>
     18#include <string.h>                                                                             // strlen
    1719#include <unistd.h>                                                                             // _exit, getpid
     20#define __USE_GNU
     21#include <signal.h>
     22#undef __USE_GNU
    1823extern "C" {
    1924#include <dlfcn.h>                                                                              // dlopen, dlsym
     
    2126}
    2227
     28#include "bits/debug.hfa"
    2329#include "bits/defs.hfa"
    2430#include "bits/signal.hfa"                                                              // sigHandler_?
     
    3642
    3743typedef void (* generic_fptr_t)(void);
    38 
    3944static generic_fptr_t do_interpose_symbol( void * library, const char symbol[], const char version[] ) {
     45        const char * error;
     46
    4047        union { generic_fptr_t fptr; void * ptr; } originalFunc;
    4148
    4249        #if defined( _GNU_SOURCE )
    43         if ( version ) {
    44                 originalFunc.ptr = dlvsym( library, symbol, version );
    45         } else {
     50                if ( version ) {
     51                        originalFunc.ptr = dlvsym( library, symbol, version );
     52                } else {
     53                        originalFunc.ptr = dlsym( library, symbol );
     54                }
     55        #else
    4656                originalFunc.ptr = dlsym( library, symbol );
     57        #endif // _GNU_SOURCE
     58
     59        error = dlerror();
     60        if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
     61
     62        return originalFunc.fptr;
     63}
     64
     65static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
     66        const char * error;
     67
     68        static void * library;
     69        static void * pthread_library;
     70        if ( ! library ) {
     71                #if defined( RTLD_NEXT )
     72                        library = RTLD_NEXT;
     73                #else
     74                        // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
     75                        library = dlopen( "libc.so.6", RTLD_LAZY );
     76                        error = dlerror();
     77                        if ( error ) {
     78                                abort( "interpose_symbol : failed to open libc, %s\n", error );
     79                        }
     80                #endif
    4781        } // if
    48         #else
    49         originalFunc.ptr = dlsym( library, symbol );
    50         #endif // _GNU_SOURCE
    51 
    52         if ( ! originalFunc.ptr ) {                                                     // == nullptr
    53                 abort( "interpose_symbol : internal error, %s\n", dlerror() );
     82        if ( ! pthread_library ) {
     83                #if defined( RTLD_NEXT )
     84                        pthread_library = RTLD_NEXT;
     85                #else
     86                        // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
     87                        pthread_library = dlopen( "libpthread.so", RTLD_LAZY );
     88                        error = dlerror();
     89                        if ( error ) {
     90                                abort( "interpose_symbol : failed to open libpthread, %s\n", error );
     91                        }
     92                #endif
    5493        } // if
    55         return originalFunc.fptr;
    56 }
    57 
    58 static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
    59         void * library;
    60 
    61         #if defined( RTLD_NEXT )
    62         library = RTLD_NEXT;
    63         #else
    64         // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
    65         library = dlopen( "libc.so.6", RTLD_LAZY );
    66         if ( ! library ) {                                                                      // == nullptr
    67                 abort( "interpose_symbol : failed to open libc, %s\n", dlerror() );
    68         } // if
    69         #endif // RTLD_NEXT
    70 
    71         return do_interpose_symbol( library, symbol, version );
     94
     95        return do_interpose_symbol(library, symbol, version);
    7296}
    7397
     
    99123                preload_libgcc();
    100124
    101                 #pragma GCC diagnostic push
    102                 #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
     125#pragma GCC diagnostic push
     126#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
    103127                INTERPOSE_LIBC( abort, version );
    104128                INTERPOSE_LIBC( exit , version );
    105                 #pragma GCC diagnostic pop
     129#pragma GCC diagnostic pop
    106130
    107131                if(__cfathreadabi_interpose_startup) __cfathreadabi_interpose_startup( do_interpose_symbol );
    108 
    109                 // SKULLDUGGERY: In Ubuntu 22.04, someone augmented signal.h to allow SIGSTKSZ to be "sysconf(_SC_SIGSTKSZ)" in
    110                 // sigstksz.h, as well as 8192 in sigstack.h. HOWEVER, they forgot to provide a mechanism to tell signal.h to
    111                 // use sigstack.h rather than sigstksz.h. (I'm not happy.) By undefining _GNU_SOURCE before signal.h and
    112                 // redefining it afterwards, you can get 8192, but then nothing works correctly inside of signal.h without
    113                 // _GNU_SOURCE defined.  So what is needed is a way to get signal.h to use sigstack.h WITH _GNU_SOURCE defined.
    114                 // Basically something is wrong with features.h and its use in signal.h.
    115 
    116                 #undef SIGSTKSZ
    117                 #define SIGSTKSZ 8192
    118132
    119133                // As a precaution (and necessity), errors that result in termination are delivered on a separate stack because
     
    281295        va_start( args, fmt );
    282296        __abort( false, fmt, args );
    283         // CONTROL NEVER REACHES HERE!
     297    // CONTROL NEVER REACHES HERE!
    284298        va_end( args );
    285299}
    286300
    287301void abort( bool signalAbort, const char fmt[], ... ) {
    288         va_list args;
    289         va_start( args, fmt );
    290         __abort( signalAbort, fmt, args );
    291         // CONTROL NEVER REACHES HERE!
    292         va_end( args );
     302    va_list args;
     303    va_start( args, fmt );
     304    __abort( signalAbort, fmt, args );
     305    // CONTROL NEVER REACHES HERE!
     306    va_end( args );
    293307}
    294308
  • libcfa/src/interpose_thread.cfa

    r24d6572 r34b4268  
    1414//
    1515
    16 // BUG in 32-bit gcc with interpose: fixed in >= gcc-9.5, gcc-10.4, gcc-12.2
    17 #ifdef __i386__                                                                                 // 32-bit architecture
    18 #undef _GNU_SOURCE
    19 #endif // __i386__
    20 
     16#include <stdarg.h>                                                                             // va_start, va_end
     17#include <stdio.h>
     18#include <string.h>                                                                             // strlen
    2119#include <signal.h>
    2220#include <pthread.h>
    23 #include <signal.h>
    2421extern "C" {
    2522#include <dlfcn.h>                                                                              // dlopen, dlsym
     23#include <execinfo.h>                                                                   // backtrace, messages
    2624}
    2725
     26#include "bits/debug.hfa"
    2827#include "bits/defs.hfa"
     28#include <assert.h>
    2929
    3030//=============================================================================================
     
    3434typedef void (* generic_fptr_t)(void);
    3535
    36 generic_fptr_t libcfa_public interpose_symbol(
     36generic_fptr_t interpose_symbol(
    3737        generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ),
    3838        const char symbol[],
    3939        const char version[]
    40 ) {
    41         void * library;
     40) libcfa_public {
     41        const char * error;
    4242
    43         #if defined( RTLD_NEXT )
    44         library = RTLD_NEXT;
    45         #else
    46         // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
    47         library = dlopen( "libpthread.so", RTLD_LAZY );
    48         if ( ! library ) {                                                                      // == nullptr
    49                 abort( "interpose_symbol : failed to open libpthread, %s\n", dlerror() );
     43        static void * library;
     44        if ( ! library ) {
     45                #if defined( RTLD_NEXT )
     46                        library = RTLD_NEXT;
     47                #else
     48                        // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
     49                        library = dlopen( "libpthread.so", RTLD_LAZY );
     50                        error = dlerror();
     51                        if ( error ) {
     52                                abort( "interpose_symbol : failed to open libpthread, %s\n", error );
     53                        }
     54                #endif
    5055        } // if
    51         #endif // RTLD_NEXT
    5256
    53         return do_interpose_symbol( library, symbol, version );
     57        return do_interpose_symbol(library, symbol, version);
    5458}
    5559
     
    7983#pragma GCC diagnostic push
    8084#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
    81                 INTERPOSE( pthread_create, version );
    82                 INTERPOSE( pthread_join, version );
    83                 INTERPOSE( pthread_self, version );
    84                 INTERPOSE( pthread_attr_init, version );
    85                 INTERPOSE( pthread_attr_destroy, version );
    86                 INTERPOSE( pthread_attr_setstack, version );
    87                 INTERPOSE( pthread_attr_getstacksize, version );
    88                 INTERPOSE( pthread_sigmask, version );
    89                 INTERPOSE( pthread_sigqueue, version );
    90                 INTERPOSE( pthread_once, version );
     85                INTERPOSE( pthread_create , version );
     86                INTERPOSE( pthread_join , version );
     87                INTERPOSE( pthread_self , version );
     88                INTERPOSE( pthread_attr_init , version );
     89                INTERPOSE( pthread_attr_destroy , version );
     90                INTERPOSE( pthread_attr_setstack , version );
     91                INTERPOSE( pthread_attr_getstacksize , version );
     92                INTERPOSE( pthread_sigmask , version );
     93                INTERPOSE( pthread_sigqueue , version );
     94                INTERPOSE( pthread_once , version );
    9195#pragma GCC diagnostic pop
    9296        }
  • libcfa/src/iostream.cfa

    r24d6572 r34b4268  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan  9 09:27:58 2023
    13 // Update Count     : 1361
     12// Last Modified On : Sat Aug 27 15:04:15 2022
     13// Update Count     : 1358
    1414//
    1515
     
    667667                        } /* if */ \
    668668                        if ( ! f.flags.nobsdp || (exp10 < SUFFIXES_START) || (exp10 > SUFFIXES_END) ) { \
    669                                 len2 = snprintf( &buf[len], size - len, "e%d", (int)exp10 /* ambiguity with function exp10 */ ); \
     669                                len2 = snprintf( &buf[len], size - len, "e%d", exp10 ); \
    670670                        } else { \
    671671                                len2 = snprintf( &buf[len], size - len, "%s", suffixes[(exp10 - SUFFIXES_START) / 3] ); \
  • libcfa/src/iostream.hfa

    r24d6572 r34b4268  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:25:39 2023
    13 // Update Count     : 410
     12// Last Modified On : Sun Oct 10 10:02:07 2021
     13// Update Count     : 407
    1414//
    1515
     
    2222
    2323
    24 forall( ostype & )
    25 trait basic_ostream {
     24trait basic_ostream( ostype & ) {
    2625        // private
    2726        bool sepPrt$( ostype & );                                                       // get separator state (on/off)
     
    5251}; // basic_ostream
    5352       
    54 forall( ostype & | basic_ostream( ostype ) )
    55 trait ostream {
     53trait ostream( ostype & | basic_ostream( ostype ) ) {
    5654        bool fail( ostype & );                                                          // operation failed?
    5755        void clear( ostype & );
     
    6260}; // ostream
    6361
    64 // forall( T )
    65 // trait writeable {
     62// trait writeable( T ) {
    6663//      forall( ostype & | ostream( ostype ) ) ostype & ?|?( ostype &, T );
    6764// }; // writeable
    6865
    69 forall( T, ostype & | ostream( ostype ) )
    70         trait writeable {
     66trait writeable( T, ostype & | ostream( ostype ) ) {
    7167        ostype & ?|?( ostype &, T );
    7268}; // writeable
     
    294290
    295291
    296 forall( istype & )
    297 trait basic_istream {
     292trait basic_istream( istype & ) {
    298293        // private
    299294        bool getANL$( istype & );                                                       // get scan newline (on/off)
     
    307302}; // basic_istream
    308303
    309 forall( istype & | basic_istream( istype ) )
    310 trait istream {
     304trait istream( istype & | basic_istream( istype ) ) {
    311305        bool fail( istype & );
    312306        void clear( istype & );
     
    316310}; // istream
    317311
    318 forall( T )
    319 trait readable {
     312trait readable( T ) {
    320313        forall( istype & | istream( istype ) ) istype & ?|?( istype &, T );
    321314}; // readable
  • libcfa/src/iterator.hfa

    r24d6572 r34b4268  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:21:50 2023
    13 // Update Count     : 11
     12// Last Modified On : Fri Jul  7 08:37:25 2017
     13// Update Count     : 10
    1414//
    1515
     
    1717
    1818// An iterator can be used to traverse a data structure.
    19 forall( iterator_type, elt_type )
    20 trait iterator {
     19trait iterator( iterator_type, elt_type ) {
    2120        // point to the next element
    2221//      iterator_type ?++( iterator_type & );
     
    3231};
    3332
    34 forall( iterator_type, collection_type, elt_type | iterator( iterator_type, elt_type ) )
    35         trait iterator_for {
     33trait iterator_for( iterator_type, collection_type, elt_type | iterator( iterator_type, elt_type ) ) {
    3634//      [ iterator_type begin, iterator_type end ] get_iterators( collection_type );
    3735        iterator_type begin( collection_type );
  • libcfa/src/limits.cfa

    r24d6572 r34b4268  
    1010// Created On       : Wed Apr  6 18:06:52 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb 17 12:25:39 2023
    13 // Update Count     : 87
     12// Last Modified On : Thu Mar  1 16:22:51 2018
     13// Update Count     : 74
    1414//
    1515
    1616#include <limits.h>
    1717#include <float.h>
     18#define __USE_GNU                                                                               // get M_* constants
    1819#include <math.h>
    1920#include <complex.h>
  • libcfa/src/math.trait.hfa

    r24d6572 r34b4268  
    1010// Created On       : Fri Jul 16 15:40:52 2021
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:36:56 2023
    13 // Update Count     : 20
     12// Last Modified On : Tue Jul 20 17:47:19 2021
     13// Update Count     : 19
    1414//
    1515
    1616#pragma once
    1717
    18 forall( U )
    19 trait Not {
     18trait Not( U ) {
    2019        void ?{}( U &, zero_t );
    2120        int !?( U );
    2221}; // Not
    2322
    24 forall( T | Not( T ) )
    25 trait Equality {
     23trait Equality( T | Not( T ) ) {
    2624        int ?==?( T, T );
    2725        int ?!=?( T, T );
    2826}; // Equality
    2927
    30 forall( U | Equality( U ) )
    31 trait Relational {
     28trait Relational( U | Equality( U ) ) {
    3229        int ?<?( U, U );
    3330        int ?<=?( U, U );
     
    3633}; // Relational
    3734
    38 forall ( T )
    39 trait Signed {
     35trait Signed( T ) {
    4036        T +?( T );
    4137        T -?( T );
     
    4339}; // Signed
    4440
    45 forall( U | Signed( U ) )
    46 trait Additive {
     41trait Additive( U | Signed( U ) ) {
    4742        U ?+?( U, U );
    4843        U ?-?( U, U );
     
    5146}; // Additive
    5247
    53 forall( T | Additive( T ) )
    54 trait Incdec {
     48trait Incdec( T | Additive( T ) ) {
    5549        void ?{}( T &, one_t );
    5650        // T ?++( T & );
     
    6054}; // Incdec
    6155
    62 forall( U | Incdec( U ) )
    63 trait Multiplicative {
     56trait Multiplicative( U | Incdec( U ) ) {
    6457        U ?*?( U, U );
    6558        U ?/?( U, U );
     
    6861}; // Multiplicative
    6962
    70 forall( T | Relational( T ) | Multiplicative( T ) )
    71 trait Arithmetic {
     63trait Arithmetic( T | Relational( T ) | Multiplicative( T ) ) {
    7264}; // Arithmetic
    7365
  • libcfa/src/stdlib.cfa

    r24d6572 r34b4268  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 16 16:31:34 2023
    13 // Update Count     : 633
     12// Last Modified On : Fri Dec  9 15:11:30 2022
     13// Update Count     : 631
    1414//
    1515
     
    2020//---------------------------------------
    2121
     22#define _XOPEN_SOURCE 600                                                               // posix_memalign, *rand48
    2223#include <string.h>                                                                             // memcpy, memset
    2324//#include <math.h>                                                                             // fabsf, fabs, fabsl
  • libcfa/src/stdlib.hfa

    r24d6572 r34b4268  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 11:30:04 2023
    13 // Update Count     : 766
     12// Last Modified On : Sun Dec 11 18:25:53 2022
     13// Update Count     : 765
    1414//
    1515
     
    367367
    368368        char random( void ) { return (unsigned long int)random(); }
    369         char random( char u ) { return (unsigned long int)random( (unsigned long int)u ); } // [0,u)
     369        char random( char u ) { return random( (unsigned long int)u ); } // [0,u)
    370370        char random( char l, char u ) { return random( (unsigned long int)l, (unsigned long int)u ); } // [l,u)
    371371        int random( void ) { return (long int)random(); }
    372         int random( int u ) { return (long int)random( (long int)u ); } // [0,u]
     372        int random( int u ) { return random( (long int)u ); } // [0,u]
    373373        int random( int l, int u ) { return random( (long int)l, (long int)u ); } // [l,u)
    374374        unsigned int random( void ) { return (unsigned long int)random(); }
    375         unsigned int random( unsigned int u ) { return (unsigned long int)random( (unsigned long int)u ); } // [0,u]
     375        unsigned int random( unsigned int u ) { return random( (unsigned long int)u ); } // [0,u]
    376376        unsigned int random( unsigned int l, unsigned int u ) { return random( (unsigned long int)l, (unsigned long int)u ); } // [l,u)
    377377} // distribution
     
    404404//   calls( sprng );
    405405
    406 forall( PRNG &, R )
    407 trait basic_prng {
     406trait basic_prng( PRNG &, R ) {
    408407        void set_seed( PRNG & prng, R seed );                           // set seed
    409408        R get_seed( PRNG & prng );                                                      // get seed
  • libcfa/src/vec/vec.hfa

    r24d6572 r34b4268  
    1818#include <math.hfa>
    1919
    20 forall(T)
    21 trait fromint {
     20trait fromint(T) {
    2221    void ?{}(T&, int);
    2322};
    24 forall(T)
    25 trait zeroinit {
     23trait zeroinit(T) {
    2624    void ?{}(T&, zero_t);
    2725};
    28 forall(T)
    29 trait zero_assign {
     26trait zero_assign(T) {
    3027    T ?=?(T&, zero_t);
    3128};
    32 forall(T)
    33 trait subtract {
     29trait subtract(T) {
    3430    T ?-?(T, T);
    3531};
    36 forall(T)
    37 trait negate {
     32trait negate(T) {
    3833    T -?(T);
    3934};
    40 forall(T)
    41 trait add {
     35trait add(T) {
    4236    T ?+?(T, T);
    4337};
    44 forall(T)
    45 trait multiply {
     38trait multiply(T) {
    4639    T ?*?(T, T);
    4740};
    48 forall(T)
    49 trait divide {
     41trait divide(T) {
    5042    T ?/?(T, T);
    5143};
    52 forall(T)
    53 trait lessthan {
     44trait lessthan(T) {
    5445    int ?<?(T, T);
    5546};
    56 forall(T)
    57 trait equality {
     47trait equality(T) {
    5848    int ?==?(T, T);
    5949};
    60 forall(T)
    61 trait sqrt {
     50trait sqrt(T) {
    6251    T sqrt(T);
    6352};
  • src/AST/Attribute.hpp

    r24d6572 r34b4268  
    2727class Expr;
    2828
    29 /// An entry in an attribute list: `__attribute__(( ... ))`
    3029class Attribute final : public Node {
    3130public:
  • src/AST/Convert.cpp

    r24d6572 r34b4268  
    559559                auto stmt = new SuspendStmt();
    560560                stmt->then   = get<CompoundStmt>().accept1( node->then   );
    561                 switch (node->kind) {
     561                switch(node->type) {
    562562                        case ast::SuspendStmt::None     : stmt->type = SuspendStmt::None     ; break;
    563563                        case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break;
     
    565565                }
    566566                return stmtPostamble( stmt, node );
    567         }
    568 
    569     const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
    570                 // There is no old-AST WhenClause, so this should never be called.
    571                 assert( !node );
    572                 return nullptr;
    573567        }
    574568
     
    579573                for ( auto clause : node->clauses ) {
    580574                        stmt->clauses.push_back({{
    581                                         get<Expression>().accept1( clause->target ),
     575                                        get<Expression>().accept1( clause->target_func ),
    582576                                        get<Expression>().acceptL( clause->target_args ),
    583577                                },
    584578                                get<Statement>().accept1( clause->stmt ),
    585                                 get<Expression>().accept1( clause->when_cond ),
     579                                get<Expression>().accept1( clause->cond ),
    586580                        });
    587581                }
     
    600594        const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    601595                // There is no old-AST WaitForClause, so this should never be called.
    602                 assert( !node );
    603                 return nullptr;
    604         }
    605 
    606     const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
    607         // There is no old-AST WaitUntilStmt, so this should never be called.
    608596                assert( !node );
    609597                return nullptr;
     
    16951683                        GET_ACCEPT_V(attributes, Attribute),
    16961684                        { old->get_funcSpec().val },
    1697                         (old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs
     1685                        old->type->isVarArgs
    16981686                };
    16991687
     
    20011989                        GET_ACCEPT_1(else_, Stmt),
    20021990                        GET_ACCEPT_V(initialization, Stmt),
    2003                         (old->isDoWhile) ? ast::DoWhile : ast::While,
     1991                        old->isDoWhile,
    20041992                        GET_LABELS_V(old->labels)
    20051993                );
     
    21432131        virtual void visit( const SuspendStmt * old ) override final {
    21442132                if ( inCache( old ) ) return;
    2145                 ast::SuspendStmt::Kind type;
     2133                ast::SuspendStmt::Type type;
    21462134                switch (old->type) {
    21472135                        case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
     
    21702158                        auto clause = new ast::WaitForClause( old->location );
    21712159
    2172                         clause->target = GET_ACCEPT_1(clauses[i].target.function, Expr);
     2160                        clause->target_func = GET_ACCEPT_1(clauses[i].target.function, Expr);
    21732161                        clause->target_args = GET_ACCEPT_V(clauses[i].target.arguments, Expr);
    21742162                        clause->stmt = GET_ACCEPT_1(clauses[i].statement, Stmt);
    2175                         clause->when_cond = GET_ACCEPT_1(clauses[i].condition, Expr);
     2163                        clause->cond = GET_ACCEPT_1(clauses[i].condition, Expr);
    21762164
    21772165                        stmt->clauses.push_back( clause );
  • src/AST/Create.cpp

    r24d6572 r34b4268  
    2020#include "AST/Decl.hpp"
    2121#include "AST/Type.hpp"
    22 #include "Common/Iterate.hpp"
    2322
    2423namespace ast {
  • src/AST/Decl.cpp

    r24d6572 r34b4268  
    2020#include <unordered_map>
    2121
    22 #include "Common/Eval.h"       // for eval
     22#include "Common/utility.h"
    2323
    2424#include "Fwd.hpp"             // for UniqueId
     
    5757        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    5858        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
    59         std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs )
     59        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
    6060: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ),
    6161        type_params(std::move(forall)), assertions(),
    6262        params(std::move(params)), returns(std::move(returns)), stmts( stmts ) {
    63         FunctionType * ftype = new FunctionType( isVarArgs );
     63        FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
    6464        for (auto & param : this->params) {
    6565                ftype->params.emplace_back(param->get_type());
     
    8181        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    8282        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
    83         std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs )
     83        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
    8484: DeclWithType( location, name, storage, linkage, std::move(attrs), fs ),
    8585                type_params( std::move( forall) ), assertions( std::move( assertions ) ),
    8686                params( std::move(params) ), returns( std::move(returns) ),
    8787                type( nullptr ), stmts( stmts ) {
    88         FunctionType * type = new FunctionType( isVarArgs );
     88        FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs );
    8989        for ( auto & param : this->params ) {
    9090                type->params.emplace_back( param->get_type() );
  • src/AST/Decl.hpp

    r24d6572 r34b4268  
    1010// Created On       : Thu May 9 10:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Apr  5 10:42:00 2023
    13 // Update Count     : 35
     12// Last Modified On : Thu Nov 24  9:44:00 2022
     13// Update Count     : 34
    1414//
    1515
     
    122122};
    123123
    124 /// Function variable arguments flag
    125 enum ArgumentFlag { FixedArgs, VariableArgs };
    126 
    127124/// Object declaration `int foo()`
    128125class FunctionDecl : public DeclWithType {
     
    147144                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    148145                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
    149                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
     146                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
    150147
    151148        FunctionDecl( const CodeLocation & location, const std::string & name,
     
    153150                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    154151                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
    155                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
     152                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
    156153
    157154        const Type * get_type() const override;
     
    316313public:
    317314        bool isTyped; // isTyped indicated if the enum has a declaration like:
    318         // enum (type_optional) Name {...}
     315        // enum (type_optional) Name {...} 
    319316        ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum
    320317        enum class EnumHiding { Visible, Hide } hide;
     
    374371};
    375372
    376 /// Assembly declaration: `asm ... ( "..." : ... )`
    377373class AsmDecl : public Decl {
    378374public:
  • src/AST/Expr.cpp

    r24d6572 r34b4268  
    3030#include "Common/SemanticError.h"
    3131#include "GenPoly/Lvalue.h"        // for referencesPermissable
    32 #include "ResolvExpr/Unify.h"      // for extractResultType
     32#include "ResolvExpr/typeops.h"    // for extractResultType
    3333#include "Tuples/Tuples.h"         // for makeTupleType
    3434
  • src/AST/Expr.hpp

    r24d6572 r34b4268  
    256256};
    257257
    258 /// A name qualified by a namespace or type.
    259258class QualifiedNameExpr final : public Expr {
    260259public:
     
    262261        std::string name;
    263262
    264         QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n )
     263        QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 
    265264        : Expr( loc ), type_decl( d ), name( n ) {}
    266265
     
    632631};
    633632
    634 /// A name that refers to a generic dimension parameter.
    635633class DimensionExpr final : public Expr {
    636634public:
     
    922920};
    923921
     922
    924923}
    925924
  • src/AST/Fwd.hpp

    r24d6572 r34b4268  
    1515
    1616#pragma once
    17 
    18 template<typename> struct bitfield;
    1917
    2018#include "AST/Node.hpp"
     
    5856class FinallyClause;
    5957class SuspendStmt;
    60 class WhenClause;
    6158class WaitForStmt;
    6259class WaitForClause;
    63 class WaitUntilStmt;
    6460class WithStmt;
    6561class DeclStmt;
     
    151147class TranslationGlobal;
    152148
    153 // For the following types, only use the using type.
    154 namespace CV {
    155         struct qualifier_flags;
    156         using Qualifiers = bitfield<qualifier_flags>;
    157149}
    158 namespace Function {
    159         struct spec_flags;
    160         using Specs = bitfield<spec_flags>;
    161 }
    162 namespace Storage {
    163         struct class_flags;
    164         using Classes = bitfield<class_flags>;
    165 }
    166 namespace Linkage {
    167         struct spec_flags;
    168         using Spec = bitfield<spec_flags>;
    169 }
    170 
    171 }
  • src/AST/Init.hpp

    r24d6572 r34b4268  
    117117        ptr<Init> init;
    118118
    119         ConstructorInit(
     119        ConstructorInit( 
    120120                const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init )
    121121        : Init( loc, MaybeConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
  • src/AST/Inspect.cpp

    r24d6572 r34b4268  
    1010// Created On       : Fri Jun 24 13:16:31 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 14 15:09:00 2023
    13 // Update Count     : 4
     12// Last Modified On : Mon Oct  3 11:04:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    168168}
    169169
    170 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
    171         return obj && obj->name.empty() && obj->bitfieldWidth;
    172 }
    173 
    174170} // namespace ast
  • src/AST/Inspect.hpp

    r24d6572 r34b4268  
    1010// Created On       : Fri Jun 24 13:16:31 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 14 15:09:00 2023
    13 // Update Count     : 3
     12// Last Modified On : Thr Sep 22 13:44:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    3838const ApplicationExpr * isIntrinsicCallExpr( const Expr * expr );
    3939
    40 /// Returns true if obj's name is the empty string and it has a bitfield width.
    41 bool isUnnamedBitfield( const ObjectDecl * obj );
    42 
    4340}
  • src/AST/Node.cpp

    r24d6572 r34b4268  
    174174template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >;
    175175template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >;
    176 template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::weak >;
    177 template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::strong >;
    178176template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
    179177template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
    180178template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::weak >;
    181179template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::strong >;
    182 template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::weak >;
    183 template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::strong >;
    184180template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >;
    185181template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >;
  • src/AST/Node.hpp

    r24d6572 r34b4268  
    1919#include <cstddef>     // for nullptr_t
    2020#include <iosfwd>
     21#include <type_traits> // for remove_reference
    2122
    2223#include "Common/ErrorObjects.h"  // for SemanticErrorException
     
    3536        Node(const Node&) : strong_count(0), weak_count(0) {}
    3637        Node(Node&&) : strong_count(0), weak_count(0) {}
    37         Node& operator=(const Node&) = delete;
    38         Node& operator=(Node&&) = delete;
     38        Node& operator= (const Node&) = delete;
     39        Node& operator= (Node&&) = delete;
    3940        virtual ~Node() {}
    4041
  • src/AST/ParseNode.hpp

    r24d6572 r34b4268  
    4040        template<typename node_t>
    4141        friend node_t * mutate(const node_t * node);
    42         template<typename node_t>
    43         friend node_t * shallowCopy(const node_t * node);
    4442};
    4543
  • src/AST/Pass.hpp

    r24d6572 r34b4268  
    6666//
    6767// Other Special Members:
    68 // | beginScope            - A method with no parameters or return value, called each time the
    69 //                           visitor enters a block.
    70 // | endScope              - A method with no parameters or return value, called each time the
    71 //                           visitor leaves a block.
    7268// | result                - Either a method that takes no parameters or a field. If a method (or
    7369//                           callable field) get_result calls it, otherwise the value is returned.
     
    8682        {
    8783                // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor
    88                 type * const * visitor = __pass::visitor( core, 0 );
    89                 if ( visitor ) {
     84                type * const * visitor = __pass::visitor(core, 0);
     85                if(visitor) {
    9086                        *const_cast<type **>( visitor ) = this;
    9187                }
     
    9894
    9995        /// If the core defines a result, call it if possible, otherwise return it.
    100         inline auto get_result() -> decltype( __pass::result::get( core, '0' ) ) {
    101                 return __pass::result::get( core, '0' );
     96        inline auto get_result() -> decltype( __pass::get_result( core, '0' ) ) {
     97                return __pass::get_result( core, '0' );
    10298        }
    10399
     
    162158        const ast::FinallyClause *    visit( const ast::FinallyClause        * ) override final;
    163159        const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
    164     const ast::WhenClause *       visit( const ast::WhenClause           * ) override final;
    165160        const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
    166161        const ast::WaitForClause *    visit( const ast::WaitForClause        * ) override final;
    167     const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) override final;
    168162        const ast::Decl *             visit( const ast::WithStmt             * ) override final;
    169163        const ast::NullStmt *         visit( const ast::NullStmt             * ) override final;
  • src/AST/Pass.impl.hpp

    r24d6572 r34b4268  
    2020#include <unordered_map>
    2121
    22 #include "AST/Copy.hpp"
    2322#include "AST/TranslationUnit.hpp"
    2423#include "AST/TypeSubstitution.hpp"
     
    4645
    4746#ifdef PEDANTIC_PASS_ASSERT
    48 #define __pedantic_pass_assert(...) assert(__VA_ARGS__)
     47#define __pedantic_pass_assert(...) assert (__VA_ARGS__)
    4948#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
    5049#else
     
    125124                        return !new_val.empty();
    126125                }
     126        }
     127
     128        template< typename node_t >
     129        template< typename object_t, typename super_t, typename field_t >
     130        void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field ) {
     131                object->*field = value;
    127132        }
    128133
     
    228233
    229234                return {true, compound};
     235        }
     236
     237        template< template <class...> class container_t >
     238        template< typename object_t, typename super_t, typename field_t >
     239        void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
     240                auto & container = object->*field;
     241                __pedantic_pass_assert( container.size() <= values.size() );
     242
     243                auto cit = enumerate(container).begin();
     244
     245                container_t<ptr<Stmt>> nvals;
     246                for (delta & d : values) {
     247                        if ( d.is_old ) {
     248                                __pedantic_pass_assert( cit.idx <= d.old_idx );
     249                                std::advance( cit, d.old_idx - cit.idx );
     250                                nvals.push_back( std::move( (*cit).val) );
     251                        } else {
     252                                nvals.push_back( std::move(d.new_val) );
     253                        }
     254                }
     255
     256                container = std::move(nvals);
     257        }
     258
     259        template< template <class...> class container_t >
     260        template< template <class...> class incontainer_t >
     261        void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Stmt>> * stmts ) {
     262                if (!stmts || stmts->empty()) return;
     263
     264                std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ),
     265                        [](ast::ptr<ast::Stmt>& stmt) -> delta {
     266                                return delta( stmt.release(), -1, false );
     267                        });
     268                stmts->clear();
     269                differs = true;
     270        }
     271
     272        template< template<class...> class container_t >
     273        template< template<class...> class incontainer_t >
     274        void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Decl>> * decls ) {
     275                if (!decls || decls->empty()) return;
     276
     277                std::transform(decls->begin(), decls->end(), std::back_inserter( values ),
     278                        [](ast::ptr<ast::Decl>& decl) -> delta {
     279                                auto loc = decl->location;
     280                                auto stmt = new DeclStmt( loc, decl.release() );
     281                                return delta( stmt, -1, false );
     282                        });
     283                decls->clear();
     284                differs = true;
    230285        }
    231286
     
    297352
    298353                return new_kids;
     354        }
     355
     356        template< template <class...> class container_t, typename node_t >
     357        template< typename object_t, typename super_t, typename field_t >
     358        void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
     359                auto & container = object->*field;
     360                __pedantic_pass_assert( container.size() == values.size() );
     361
     362                for(size_t i = 0; i < container.size(); i++) {
     363                        // Take all the elements that are different in 'values'
     364                        // and swap them into 'container'
     365                        if( values[i] != nullptr ) swap(container[i], values[i]);
     366                }
     367
     368                // Now the original containers should still have the unchanged values
     369                // but also contain the new values
    299370        }
    300371
     
    765836                        if ( enterScope ) {
    766837                                __pass::symtab::enter(core, 0);
     838                                __pass::scope::enter(core, 0);
    767839                        }
    768840                }, [this, leaveScope = !this->atFunctionTop]() {
    769841                        if ( leaveScope ) {
    770842                                __pass::symtab::leave(core, 0);
     843                                __pass::scope::leave(core, 0);
    771844                        }
    772845                });
     
    9941067
    9951068//--------------------------------------------------------------------------
    996 // WhenClause
    997 template< typename core_t >
    998 const ast::WhenClause * ast::Pass< core_t >::visit( const ast::WhenClause * node ) {
    999         VISIT_START( node );
    1000 
    1001         if ( __visit_children() ) {
    1002                 maybe_accept( node, &WhenClause::target );
    1003                 maybe_accept( node, &WhenClause::stmt );
    1004                 maybe_accept( node, &WhenClause::when_cond );
    1005         }
    1006 
    1007         VISIT_END( WhenClause, node );
    1008 }
    1009 
    1010 //--------------------------------------------------------------------------
    10111069// WaitForStmt
    10121070template< typename core_t >
     
    10331091
    10341092        if ( __visit_children() ) {
    1035                 maybe_accept( node, &WaitForClause::target );
     1093                maybe_accept( node, &WaitForClause::target_func );
    10361094                maybe_accept( node, &WaitForClause::target_args );
    10371095                maybe_accept( node, &WaitForClause::stmt );
    1038                 maybe_accept( node, &WaitForClause::when_cond );
     1096                maybe_accept( node, &WaitForClause::cond );
    10391097        }
    10401098
    10411099        VISIT_END( WaitForClause, node );
    1042 }
    1043 
    1044 //--------------------------------------------------------------------------
    1045 // WaitUntilStmt
    1046 template< typename core_t >
    1047 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitUntilStmt * node ) {
    1048         VISIT_START( node );
    1049 
    1050         if ( __visit_children() ) {
    1051                 maybe_accept( node, &WaitUntilStmt::clauses );
    1052                 maybe_accept( node, &WaitUntilStmt::timeout_time );
    1053                 maybe_accept( node, &WaitUntilStmt::timeout_stmt );
    1054                 maybe_accept( node, &WaitUntilStmt::timeout_cond );
    1055                 maybe_accept( node, &WaitUntilStmt::else_stmt );
    1056                 maybe_accept( node, &WaitUntilStmt::else_cond );
    1057         }
    1058 
    1059         VISIT_END( Stmt, node );
    10601100}
    10611101
     
    20032043        if ( __visit_children() ) {
    20042044                maybe_accept( node, &TupleType::types );
     2045                maybe_accept( node, &TupleType::members );
    20052046        }
    20062047
     
    21642205}
    21652206
    2166 #undef __pedantic_pass_assertf
    2167 #undef __pedantic_pass_assert
    21682207#undef VISIT_START
    21692208#undef VISIT_END
  • src/AST/Pass.proto.hpp

    r24d6572 r34b4268  
    1717// IWYU pragma: private, include "Pass.hpp"
    1818
    19 #include "Common/Iterate.hpp"
    2019#include "Common/Stats/Heap.h"
     20
    2121namespace ast {
    22         template<typename core_t> class Pass;
    23         class TranslationUnit;
    24         struct PureVisitor;
    25         template<typename node_t> node_t * deepCopy( const node_t * );
    26 }
    27 
    28 #ifdef PEDANTIC_PASS_ASSERT
    29 #define __pedantic_pass_assert(...) assert(__VA_ARGS__)
    30 #define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
    31 #else
    32 #define __pedantic_pass_assert(...)
    33 #define __pedantic_pass_assertf(...)
    34 #endif
    35 
    36 namespace ast::__pass {
    37 
    38 typedef std::function<void( void * )> cleanup_func_t;
    39 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t;
    40 
    41 // boolean reference that may be null
    42 // either refers to a boolean value or is null and returns true
    43 class bool_ref {
    44 public:
    45         bool_ref() = default;
    46         ~bool_ref() = default;
    47 
    48         operator bool() { return m_ref ? *m_ref : true; }
    49         bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
    50 
    51 private:
    52 
    53         friend class visit_children_guard;
    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;
    62 };
    63 
    64 // Implementation of the guard value
    65 // Created inside the visit scope
    66 class guard_value {
    67 public:
    68         /// Push onto the cleanup
    69         guard_value( at_cleanup_t * at_cleanup ) {
    70                 if( at_cleanup ) {
    71                         *at_cleanup = [this]( cleanup_func_t && func, void* val ) {
    72                                 push( std::move( func ), val );
    73                         };
    74                 }
    75         }
    76 
    77         ~guard_value() {
    78                 while( !cleanups.empty() ) {
    79                         auto& cleanup = cleanups.top();
    80                         cleanup.func( cleanup.val );
    81                         cleanups.pop();
    82                 }
    83         }
    84 
    85         void push( cleanup_func_t && func, void* val ) {
    86                 cleanups.emplace( std::move(func), val );
    87         }
    88 
    89 private:
    90         struct cleanup_t {
    91                 cleanup_func_t func;
    92                 void * val;
    93 
    94                 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
    95         };
    96 
    97         std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
    98 };
    99 
    100 // Guard structure implementation for whether or not children should be visited
    101 class visit_children_guard {
    102 public:
    103 
    104         visit_children_guard( bool_ref * ref )
    105                 : m_val ( true )
    106                 , m_prev( ref ? ref->set( &m_val ) : nullptr )
    107                 , m_ref ( ref )
    108         {}
    109 
    110         ~visit_children_guard() {
    111                 if( m_ref ) {
    112                         m_ref->set( m_prev );
    113                 }
    114         }
    115 
    116         operator bool() { return m_val; }
    117 
    118 private:
    119         bool       m_val;
    120         bool     * m_prev;
    121         bool_ref * m_ref;
    122 };
    123 
    124 /// "Short hand" to check if this is a valid previsit function
    125 /// Mostly used to make the static_assert look (and print) prettier
    126 template<typename core_t, typename node_t>
    127 struct is_valid_previsit {
    128         using ret_t = decltype( std::declval<core_t*>()->previsit( std::declval<const node_t *>() ) );
    129 
    130         static constexpr bool value = std::is_void< ret_t >::value ||
    131                 std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value;
    132 };
    133 
    134 /// The result is a single node.
    135 template< typename node_t >
    136 struct result1 {
    137         bool differs = false;
    138         const node_t * value = nullptr;
    139 
    140         template< typename object_t, typename super_t, typename field_t >
    141         void apply( object_t * object, field_t super_t::* field ) {
    142                 object->*field = value;
    143         }
    144 };
    145 
    146 /// The result is a container of statements.
    147 template< template<class...> class container_t >
    148 struct resultNstmt {
    149         /// The delta/change on a single node.
    150         struct delta {
    151                 ptr<Stmt> new_val;
    152                 ssize_t old_idx;
    153                 bool is_old;
    154 
    155                 delta(const Stmt * s, ssize_t i, bool old) :
    156                         new_val(s), old_idx(i), is_old(old) {}
    157         };
    158 
    159         bool differs = false;
    160         container_t< delta > values;
    161 
    162         template< typename object_t, typename super_t, typename field_t >
    163         void apply( object_t * object, field_t super_t::* field ) {
    164                 field_t & container = object->*field;
    165                 __pedantic_pass_assert( container.size() <= values.size() );
    166 
    167                 auto cit = enumerate(container).begin();
    168 
    169                 container_t<ptr<Stmt>> nvals;
    170                 for ( delta & d : values ) {
    171                         if ( d.is_old ) {
    172                                 __pedantic_pass_assert( cit.idx <= d.old_idx );
    173                                 std::advance( cit, d.old_idx - cit.idx );
    174                                 nvals.push_back( std::move( (*cit).val ) );
    175                         } else {
    176                                 nvals.push_back( std::move( d.new_val ) );
    177                         }
    178                 }
    179 
    180                 container = std::move(nvals);
    181         }
    182 
    183         template< template<class...> class incontainer_t >
    184         void take_all( incontainer_t<ptr<Stmt>> * stmts ) {
    185                 if ( !stmts || stmts->empty() ) return;
    186 
    187                 std::transform( stmts->begin(), stmts->end(), std::back_inserter( values ),
    188                         [](ast::ptr<ast::Stmt>& stmt) -> delta {
    189                                 return delta( stmt.release(), -1, false );
    190                         });
    191                 stmts->clear();
    192                 differs = true;
    193         }
    194 
    195         template< template<class...> class incontainer_t >
    196         void take_all( incontainer_t<ptr<Decl>> * decls ) {
    197                 if ( !decls || decls->empty() ) return;
    198 
    199                 std::transform( decls->begin(), decls->end(), std::back_inserter( values ),
    200                         [](ast::ptr<ast::Decl>& decl) -> delta {
    201                                 ast::Decl const * d = decl.release();
    202                                 return delta( new DeclStmt( d->location, d ), -1, false );
    203                         });
    204                 decls->clear();
    205                 differs = true;
    206         }
    207 };
    208 
    209 /// The result is a container of nodes.
    210 template< template<class...> class container_t, typename node_t >
    211 struct resultN {
    212         bool differs = false;
    213         container_t<ptr<node_t>> values;
    214 
    215         template< typename object_t, typename super_t, typename field_t >
    216         void apply( object_t * object, field_t super_t::* field ) {
    217                 field_t & container = object->*field;
    218                 __pedantic_pass_assert( container.size() == values.size() );
    219 
    220                 for ( size_t i = 0; i < container.size(); ++i ) {
    221                         // Take all the elements that are different in 'values'
    222                         // and swap them into 'container'
    223                         if ( values[i] != nullptr ) swap(container[i], values[i]);
    224                 }
    225                 // Now the original containers should still have the unchanged values
    226                 // but also contain the new values.
    227         }
    228 };
    229 
    230 /// Used by previsit implementation
    231 /// We need to reassign the result to 'node', unless the function
    232 /// returns void, then we just leave 'node' unchanged
    233 template<bool is_void>
    234 struct __assign;
    235 
    236 template<>
    237 struct __assign<true> {
     22template<typename core_t>
     23class Pass;
     24
     25class TranslationUnit;
     26
     27struct PureVisitor;
     28
     29template<typename node_t>
     30node_t * deepCopy( const node_t * localRoot );
     31
     32namespace __pass {
     33        typedef std::function<void( void * )> cleanup_func_t;
     34        typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t;
     35
     36
     37        // boolean reference that may be null
     38        // either refers to a boolean value or is null and returns true
     39        class bool_ref {
     40        public:
     41                bool_ref() = default;
     42                ~bool_ref() = default;
     43
     44                operator bool() { return m_ref ? *m_ref : true; }
     45                bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
     46
     47        private:
     48
     49                friend class visit_children_guard;
     50
     51                bool * set( bool * val ) {
     52                        bool * prev = m_ref;
     53                        m_ref = val;
     54                        return prev;
     55                }
     56
     57                bool * m_ref = nullptr;
     58        };
     59
     60        // Implementation of the guard value
     61        // Created inside the visit scope
     62        class guard_value {
     63        public:
     64                /// Push onto the cleanup
     65                guard_value( at_cleanup_t * at_cleanup ) {
     66                        if( at_cleanup ) {
     67                                *at_cleanup = [this]( cleanup_func_t && func, void* val ) {
     68                                        push( std::move( func ), val );
     69                                };
     70                        }
     71                }
     72
     73                ~guard_value() {
     74                        while( !cleanups.empty() ) {
     75                                auto& cleanup = cleanups.top();
     76                                cleanup.func( cleanup.val );
     77                                cleanups.pop();
     78                        }
     79                }
     80
     81                void push( cleanup_func_t && func, void* val ) {
     82                        cleanups.emplace( std::move(func), val );
     83                }
     84
     85        private:
     86                struct cleanup_t {
     87                        cleanup_func_t func;
     88                        void * val;
     89
     90                        cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
     91                };
     92
     93                std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
     94        };
     95
     96        // Guard structure implementation for whether or not children should be visited
     97        class visit_children_guard {
     98        public:
     99
     100                visit_children_guard( bool_ref * ref )
     101                        : m_val ( true )
     102                        , m_prev( ref ? ref->set( &m_val ) : nullptr )
     103                        , m_ref ( ref )
     104                {}
     105
     106                ~visit_children_guard() {
     107                        if( m_ref ) {
     108                                m_ref->set( m_prev );
     109                        }
     110                }
     111
     112                operator bool() { return m_val; }
     113
     114        private:
     115                bool       m_val;
     116                bool     * m_prev;
     117                bool_ref * m_ref;
     118        };
     119
     120        /// "Short hand" to check if this is a valid previsit function
     121        /// Mostly used to make the static_assert look (and print) prettier
    238122        template<typename core_t, typename node_t>
    239         static inline void result( core_t & core, const node_t * & node ) {
    240                 core.previsit( node );
    241         }
    242 };
    243 
    244 template<>
    245 struct __assign<false> {
     123        struct is_valid_previsit {
     124                using ret_t = decltype( std::declval<core_t*>()->previsit( std::declval<const node_t *>() ) );
     125
     126                static constexpr bool value = std::is_void< ret_t >::value ||
     127                        std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value;
     128        };
     129
     130        /// The result is a single node.
     131        template< typename node_t >
     132        struct result1 {
     133                bool differs = false;
     134                const node_t * value = nullptr;
     135
     136                template< typename object_t, typename super_t, typename field_t >
     137                void apply( object_t *, field_t super_t::* field );
     138        };
     139
     140        /// The result is a container of statements.
     141        template< template<class...> class container_t >
     142        struct resultNstmt {
     143                /// The delta/change on a single node.
     144                struct delta {
     145                        ptr<Stmt> new_val;
     146                        ssize_t old_idx;
     147                        bool is_old;
     148
     149                        delta(const Stmt * s, ssize_t i, bool old) :
     150                                new_val(s), old_idx(i), is_old(old) {}
     151                };
     152
     153                bool differs = false;
     154                container_t< delta > values;
     155
     156                template< typename object_t, typename super_t, typename field_t >
     157                void apply( object_t *, field_t super_t::* field );
     158
     159                template< template<class...> class incontainer_t >
     160                void take_all( incontainer_t<ptr<Stmt>> * stmts );
     161
     162                template< template<class...> class incontainer_t >
     163                void take_all( incontainer_t<ptr<Decl>> * decls );
     164        };
     165
     166        /// The result is a container of nodes.
     167        template< template<class...> class container_t, typename node_t >
     168        struct resultN {
     169                bool differs = false;
     170                container_t<ptr<node_t>> values;
     171
     172                template< typename object_t, typename super_t, typename field_t >
     173                void apply( object_t *, field_t super_t::* field );
     174        };
     175
     176        /// Used by previsit implementation
     177        /// We need to reassign the result to 'node', unless the function
     178        /// returns void, then we just leave 'node' unchanged
     179        template<bool is_void>
     180        struct __assign;
     181
     182        template<>
     183        struct __assign<true> {
     184                template<typename core_t, typename node_t>
     185                static inline void result( core_t & core, const node_t * & node ) {
     186                        core.previsit( node );
     187                }
     188        };
     189
     190        template<>
     191        struct __assign<false> {
     192                template<typename core_t, typename node_t>
     193                static inline void result( core_t & core, const node_t * & node ) {
     194                        node = core.previsit( node );
     195                        assertf(node, "Previsit must not return NULL");
     196                }
     197        };
     198
     199        /// Used by postvisit implementation
     200        /// We need to return the result unless the function
     201        /// returns void, then we just return the original node
     202        template<bool is_void>
     203        struct __return;
     204
     205        template<>
     206        struct __return<true> {
     207                template<typename core_t, typename node_t>
     208                static inline const node_t * result( core_t & core, const node_t * & node ) {
     209                        core.postvisit( node );
     210                        return node;
     211                }
     212        };
     213
     214        template<>
     215        struct __return<false> {
     216                template<typename core_t, typename node_t>
     217                static inline auto result( core_t & core, const node_t * & node ) {
     218                        return core.postvisit( node );
     219                }
     220        };
     221
     222        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     223        // Deep magic (a.k.a template meta programming) to make the templated visitor work
     224        // Basically the goal is to make 2 previsit
     225        // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
     226        //     'pass.previsit( node )' that compiles will be used for that node for that type
     227        //     This requires that this option only compile for passes that actually define an appropriate visit.
     228        //     SFINAE will make sure the compilation errors in this function don't halt the build.
     229        //     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
     230        // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
     231        //     This is needed only to eliminate the need for passes to specify any kind of handlers.
     232        //     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
     233        //     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
     234        //     the first implementation takes priority in regards to overloading.
     235        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     236        // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
    246237        template<typename core_t, typename node_t>
    247         static inline void result( core_t & core, const node_t * & node ) {
    248                 node = core.previsit( node );
    249                 assertf(node, "Previsit must not return NULL");
    250         }
    251 };
    252 
    253 /// Used by postvisit implementation
    254 /// We need to return the result unless the function
    255 /// returns void, then we just return the original node
    256 template<bool is_void>
    257 struct __return;
    258 
    259 template<>
    260 struct __return<true> {
     238        static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) {
     239                static_assert(
     240                        is_valid_previsit<core_t, node_t>::value,
     241                        "Previsit may not change the type of the node. It must return its paremeter or void."
     242                );
     243
     244                __assign<
     245                        std::is_void<
     246                                decltype( core.previsit( node ) )
     247                        >::value
     248                >::result( core, node );
     249        }
     250
    261251        template<typename core_t, typename node_t>
    262         static inline const node_t * result( core_t & core, const node_t * & node ) {
    263                 core.postvisit( node );
    264                 return node;
    265         }
    266 };
    267 
    268 template<>
    269 struct __return<false> {
     252        static inline auto previsit( core_t &, const node_t *, long ) {}
     253
     254        // PostVisit : never mutates the passed pointer but may return a different node
    270255        template<typename core_t, typename node_t>
    271         static inline auto result( core_t & core, const node_t * & node ) {
    272                 return core.postvisit( node );
    273         }
    274 };
    275 
    276 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    277 // Deep magic (a.k.a template meta programming) to make the templated visitor work
    278 // Basically the goal is to make 2 previsit
    279 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
    280 //     'pass.previsit( node )' that compiles will be used for that node for that type
    281 //     This requires that this option only compile for passes that actually define an appropriate visit.
    282 //     SFINAE will make sure the compilation errors in this function don't halt the build.
    283 //     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
    284 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
    285 //     This is needed only to eliminate the need for passes to specify any kind of handlers.
    286 //     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
    287 //     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
    288 //     the first implementation takes priority in regards to overloading.
    289 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    290 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
    291 template<typename core_t, typename node_t>
    292 static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) {
    293         static_assert(
    294                 is_valid_previsit<core_t, node_t>::value,
    295                 "Previsit may not change the type of the node. It must return its paremeter or void."
    296         );
    297 
    298         __assign<
    299                 std::is_void<
    300                         decltype( core.previsit( node ) )
    301                 >::value
    302         >::result( core, node );
    303 }
    304 
    305 template<typename core_t, typename node_t>
    306 static inline auto previsit( core_t &, const node_t *, long ) {}
    307 
    308 // PostVisit : never mutates the passed pointer but may return a different node
    309 template<typename core_t, typename node_t>
    310 static inline auto postvisit( core_t & core, const node_t * node, int ) ->
    311         decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
    312 {
    313         return __return<
    314                 std::is_void<
    315                         decltype( core.postvisit( node ) )
    316                 >::value
    317         >::result( core, node );
    318 }
    319 
    320 template<typename core_t, typename node_t>
    321 static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }
    322 
    323 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    324 // Deep magic (a.k.a template meta programming) continued
    325 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit
    326 // from in order to get extra functionallity for example
    327 // class ErrorChecker : WithShortCircuiting { ... };
    328 // Pass<ErrorChecker> checker;
    329 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting
    330 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched
    331 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    332 // For several accessories, the feature is enabled by detecting that a specific field is present
    333 // Use a macro the encapsulate the logic of detecting a particular field
    334 // The type is not strictly enforced but does match the accessory
    335 #define FIELD_PTR( name, default_type ) \
    336 template< typename core_t > \
    337 static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \
    338 \
    339 template< typename core_t > \
    340 static inline default_type * name( core_t &, long ) { return nullptr; }
    341 
    342 // List of fields and their expected types
    343 FIELD_PTR( typeSubs, const ast::TypeSubstitution * )
    344 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
    345 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
    346 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > )
    347 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > )
    348 FIELD_PTR( visit_children, __pass::bool_ref )
    349 FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
    350 FIELD_PTR( visitor, ast::Pass<core_t> * const )
    351 
    352 // Remove the macro to make sure we don't clash
    353 #undef FIELD_PTR
    354 
    355 template< typename core_t >
    356 static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
    357         // Stats::Heap::stacktrace_push(core_t::traceId);
    358 }
    359 
    360 template< typename core_t >
    361 static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
    362         // Stats::Heap::stacktrace_pop();
    363 }
    364 
    365 template< typename core_t >
    366 static void beginTrace(core_t &, long) {}
    367 
    368 template< typename core_t >
    369 static void endTrace(core_t &, long) {}
    370 
    371 // Allows visitor to handle an error on top-level declarations, and possibly suppress the error.
    372 // If on_error() returns false, the error will be ignored. By default, it returns true.
    373 
    374 template< typename core_t >
    375 static bool on_error (core_t &, ptr<Decl> &, long) { return true; }
    376 
    377 template< typename core_t >
    378 static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) {
    379         return core.on_error(decl);
    380 }
    381 
    382 template< typename core_t, typename node_t >
    383 static auto make_location_guard( core_t & core, node_t * node, int )
    384                 -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) {
    385         ValueGuardPtr<const CodeLocation *> guard( &core.location );
    386         core.location = &node->location;
    387         return guard;
    388 }
    389 
    390 template< typename core_t, typename node_t >
    391 static auto make_location_guard( core_t &, node_t *, long ) -> int {
    392         return 0;
    393 }
    394 
    395 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
    396 // All passes which have such functions are assumed desire this behaviour
    397 // detect it using the same strategy
    398 namespace scope {
     256        static inline auto postvisit( core_t & core, const node_t * node, int ) ->
     257                decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
     258        {
     259                return __return<
     260                        std::is_void<
     261                                decltype( core.postvisit( node ) )
     262                        >::value
     263                >::result( core, node );
     264        }
     265
     266        template<typename core_t, typename node_t>
     267        static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }
     268
     269        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     270        // Deep magic (a.k.a template meta programming) continued
     271        // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit
     272        // from in order to get extra functionallity for example
     273        // class ErrorChecker : WithShortCircuiting { ... };
     274        // Pass<ErrorChecker> checker;
     275        // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting
     276        // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched
     277        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     278        // For several accessories, the feature is enabled by detecting that a specific field is present
     279        // Use a macro the encapsulate the logic of detecting a particular field
     280        // The type is not strictly enforced but does match the accessory
     281        #define FIELD_PTR( name, default_type ) \
     282        template< typename core_t > \
     283        static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \
     284        \
     285        template< typename core_t > \
     286        static inline default_type * name( core_t &, long ) { return nullptr; }
     287
     288        // List of fields and their expected types
     289        FIELD_PTR( typeSubs, const ast::TypeSubstitution * )
     290        FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
     291        FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
     292        FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > )
     293        FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > )
     294        FIELD_PTR( visit_children, __pass::bool_ref )
     295        FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
     296        FIELD_PTR( visitor, ast::Pass<core_t> * const )
     297
     298        // Remove the macro to make sure we don't clash
     299        #undef FIELD_PTR
     300
     301        template< typename core_t >
     302        static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
     303                // Stats::Heap::stacktrace_push(core_t::traceId);
     304        }
     305
     306        template< typename core_t >
     307        static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
     308                // Stats::Heap::stacktrace_pop();
     309        }
     310
     311        template< typename core_t >
     312        static void beginTrace(core_t &, long) {}
     313
     314        template< typename core_t >
     315        static void endTrace(core_t &, long) {}
     316
     317        // Allows visitor to handle an error on top-level declarations, and possibly suppress the error.
     318        // If onError() returns false, the error will be ignored. By default, it returns true.
     319
     320        template< typename core_t >
     321        static bool on_error (core_t &, ptr<Decl> &, long) { return true; }
     322
     323        template< typename core_t >
     324        static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) {
     325                return core.on_error(decl);
     326        }
     327
     328        template< typename core_t, typename node_t >
     329        static auto make_location_guard( core_t & core, node_t * node, int )
     330                        -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) {
     331                ValueGuardPtr<const CodeLocation *> guard( &core.location );
     332                core.location = &node->location;
     333                return guard;
     334        }
     335
     336        template< typename core_t, typename node_t >
     337        static auto make_location_guard( core_t &, node_t *, long ) -> int {
     338                return 0;
     339        }
     340
     341        // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
     342        // All passes which have such functions are assumed desire this behaviour
     343        // detect it using the same strategy
     344        namespace scope {
     345                template<typename core_t>
     346                static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) {
     347                        core.beginScope();
     348                }
     349
     350                template<typename core_t>
     351                static inline void enter( core_t &, long ) {}
     352
     353                template<typename core_t>
     354                static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) {
     355                        core.endScope();
     356                }
     357
     358                template<typename core_t>
     359                static inline void leave( core_t &, long ) {}
     360        } // namespace scope
     361
     362        // Certain passes desire an up to date symbol table automatically
     363        // detect the presence of a member name `symtab` and call all the members appropriately
     364        namespace symtab {
     365                // Some simple scoping rules
     366                template<typename core_t>
     367                static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) {
     368                        core.symtab.enterScope();
     369                }
     370
     371                template<typename core_t>
     372                static inline auto enter( core_t &, long ) {}
     373
     374                template<typename core_t>
     375                static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) {
     376                        core.symtab.leaveScope();
     377                }
     378
     379                template<typename core_t>
     380                static inline auto leave( core_t &, long ) {}
     381
     382                // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
     383                // Create macro to condense these common patterns
     384                #define SYMTAB_FUNC1( func, type ) \
     385                template<typename core_t> \
     386                static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\
     387                        core.symtab.func( arg ); \
     388                } \
     389                \
     390                template<typename core_t> \
     391                static inline void func( core_t &, long, type ) {}
     392
     393                #define SYMTAB_FUNC2( func, type1, type2 ) \
     394                template<typename core_t> \
     395                static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\
     396                        core.symtab.func( arg1, arg2 ); \
     397                } \
     398                        \
     399                template<typename core_t> \
     400                static inline void func( core_t &, long, type1, type2 ) {}
     401
     402                SYMTAB_FUNC1( addId     , const DeclWithType *  );
     403                SYMTAB_FUNC1( addType   , const NamedTypeDecl * );
     404                SYMTAB_FUNC1( addStruct , const StructDecl *    );
     405                SYMTAB_FUNC1( addEnum   , const EnumDecl *      );
     406                SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
     407                SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
     408                SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
     409
     410                // A few extra functions have more complicated behaviour, they are hand written
     411                template<typename core_t>
     412                static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {
     413                        ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
     414                        for ( const auto & param : decl->params ) {
     415                                fwd->params.push_back( deepCopy( param.get() ) );
     416                        }
     417                        core.symtab.addStruct( fwd );
     418                }
     419
     420                template<typename core_t>
     421                static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {}
     422
     423                template<typename core_t>
     424                static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {
     425                        ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name );
     426                        for ( const auto & param : decl->params ) {
     427                                fwd->params.push_back( deepCopy( param.get() ) );
     428                        }
     429                        core.symtab.addUnion( fwd );
     430                }
     431
     432                template<typename core_t>
     433                static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {}
     434
     435                template<typename core_t>
     436                static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {
     437                        if ( ! core.symtab.lookupStruct( str ) ) {
     438                                core.symtab.addStruct( str );
     439                        }
     440                }
     441
     442                template<typename core_t>
     443                static inline void addStruct( core_t &, long, const std::string & ) {}
     444
     445                template<typename core_t>
     446                static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) {
     447                        if ( ! core.symtab.lookupUnion( str ) ) {
     448                                core.symtab.addUnion( str );
     449                        }
     450                }
     451
     452                template<typename core_t>
     453                static inline void addUnion( core_t &, long, const std::string & ) {}
     454
     455                #undef SYMTAB_FUNC1
     456                #undef SYMTAB_FUNC2
     457        } // namespace symtab
     458
     459        // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
     460        // Detect the presence of a member name `subs` and call all members appropriately
     461        namespace forall {
     462                // Some simple scoping rules
     463                template<typename core_t>
     464                static inline auto enter( core_t & core, int, const ast::FunctionType * type )
     465                -> decltype( core.subs, void() ) {
     466                        if ( ! type->forall.empty() ) core.subs.beginScope();
     467                }
     468
     469                template<typename core_t>
     470                static inline auto enter( core_t &, long, const ast::FunctionType * ) {}
     471
     472                template<typename core_t>
     473                static inline auto leave( core_t & core, int, const ast::FunctionType * type )
     474                -> decltype( core.subs, void() ) {
     475                        if ( ! type->forall.empty() ) { core.subs.endScope(); }
     476                }
     477
     478                template<typename core_t>
     479                static inline auto leave( core_t &, long, const ast::FunctionType * ) {}
     480
     481                // Replaces a TypeInstType's base TypeDecl according to the table
     482                template<typename core_t>
     483                static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst )
     484                -> decltype( core.subs, void() ) {
     485                        inst = ast::mutate_field(
     486                                inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) );
     487                }
     488
     489                template<typename core_t>
     490                static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {}
     491
     492        } // namespace forall
     493
     494        // For passes that need access to the global context. Sreaches `translationUnit`
     495        namespace translation_unit {
     496                template<typename core_t>
     497                static inline auto get_cptr( core_t & core, int )
     498                                -> decltype( &core.translationUnit ) {
     499                        return &core.translationUnit;
     500                }
     501
     502                template<typename core_t>
     503                static inline const TranslationUnit ** get_cptr( core_t &, long ) {
     504                        return nullptr;
     505                }
     506        }
     507
    399508        template<typename core_t>
    400         static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) {
    401                 core.beginScope();
     509        static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) {
     510                return core.result();
    402511        }
    403512
    404513        template<typename core_t>
    405         static inline void enter( core_t &, long ) {}
     514        static inline auto get_result( core_t & core, int ) -> decltype( core.result ) {
     515                return core.result;
     516        }
    406517
    407518        template<typename core_t>
    408         static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) {
    409                 core.endScope();
    410         }
    411 
    412         template<typename core_t>
    413         static inline void leave( core_t &, long ) {}
    414 } // namespace scope
    415 
    416 // Certain passes desire an up to date symbol table automatically
    417 // detect the presence of a member name `symtab` and call all the members appropriately
    418 namespace symtab {
    419         // Some simple scoping rules
    420         template<typename core_t>
    421         static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) {
    422                 core.symtab.enterScope();
    423         }
    424 
    425         template<typename core_t>
    426         static inline auto enter( core_t &, long ) {}
    427 
    428         template<typename core_t>
    429         static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) {
    430                 core.symtab.leaveScope();
    431         }
    432 
    433         template<typename core_t>
    434         static inline auto leave( core_t &, long ) {}
    435 
    436         // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
    437         // Create macro to condense these common patterns
    438         #define SYMTAB_FUNC1( func, type ) \
    439         template<typename core_t> \
    440         static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\
    441                 core.symtab.func( arg ); \
    442         } \
    443         \
    444         template<typename core_t> \
    445         static inline void func( core_t &, long, type ) {}
    446 
    447         #define SYMTAB_FUNC2( func, type1, type2 ) \
    448         template<typename core_t> \
    449         static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\
    450                 core.symtab.func( arg1, arg2 ); \
    451         } \
    452         \
    453         template<typename core_t> \
    454         static inline void func( core_t &, long, type1, type2 ) {}
    455 
    456         SYMTAB_FUNC1( addId     , const DeclWithType *  );
    457         SYMTAB_FUNC1( addType   , const NamedTypeDecl * );
    458         SYMTAB_FUNC1( addStruct , const StructDecl *    );
    459         SYMTAB_FUNC1( addEnum   , const EnumDecl *      );
    460         SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
    461         SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
    462         SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
    463 
    464         // A few extra functions have more complicated behaviour, they are hand written
    465         template<typename core_t>
    466         static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {
    467                 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
    468                 for ( const auto & param : decl->params ) {
    469                         fwd->params.push_back( deepCopy( param.get() ) );
    470                 }
    471                 core.symtab.addStruct( fwd );
    472         }
    473 
    474         template<typename core_t>
    475         static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {}
    476 
    477         template<typename core_t>
    478         static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {
    479                 ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name );
    480                 for ( const auto & param : decl->params ) {
    481                         fwd->params.push_back( deepCopy( param.get() ) );
    482                 }
    483                 core.symtab.addUnion( fwd );
    484         }
    485 
    486         template<typename core_t>
    487         static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {}
    488 
    489         template<typename core_t>
    490         static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {
    491                 if ( ! core.symtab.lookupStruct( str ) ) {
    492                         core.symtab.addStruct( str );
    493                 }
    494         }
    495 
    496         template<typename core_t>
    497         static inline void addStruct( core_t &, long, const std::string & ) {}
    498 
    499         template<typename core_t>
    500         static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) {
    501                 if ( ! core.symtab.lookupUnion( str ) ) {
    502                         core.symtab.addUnion( str );
    503                 }
    504         }
    505 
    506         template<typename core_t>
    507         static inline void addUnion( core_t &, long, const std::string & ) {}
    508 
    509         #undef SYMTAB_FUNC1
    510         #undef SYMTAB_FUNC2
    511 } // namespace symtab
    512 
    513 // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
    514 // Detect the presence of a member name `subs` and call all members appropriately
    515 namespace forall {
    516         // Some simple scoping rules
    517         template<typename core_t>
    518         static inline auto enter( core_t & core, int, const ast::FunctionType * type )
    519                         -> decltype( core.subs, void() ) {
    520                 if ( ! type->forall.empty() ) core.subs.beginScope();
    521         }
    522 
    523         template<typename core_t>
    524         static inline auto enter( core_t &, long, const ast::FunctionType * ) {}
    525 
    526         template<typename core_t>
    527         static inline auto leave( core_t & core, int, const ast::FunctionType * type )
    528                         -> decltype( core.subs, void() ) {
    529                 if ( ! type->forall.empty() ) { core.subs.endScope(); }
    530         }
    531 
    532         template<typename core_t>
    533         static inline auto leave( core_t &, long, const ast::FunctionType * ) {}
    534 
    535         // Replaces a TypeInstType's base TypeDecl according to the table
    536         template<typename core_t>
    537         static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst )
    538                         -> decltype( core.subs, void() ) {
    539                 inst = ast::mutate_field(
    540                         inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) );
    541         }
    542 
    543         template<typename core_t>
    544         static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {}
    545 } // namespace forall
    546 
    547 // For passes that need access to the global context. Searches `translationUnit`
    548 namespace translation_unit {
    549         template<typename core_t>
    550         static inline auto get_cptr( core_t & core, int )
    551                         -> decltype( &core.translationUnit ) {
    552                 return &core.translationUnit;
    553         }
    554 
    555         template<typename core_t>
    556         static inline const TranslationUnit ** get_cptr( core_t &, long ) {
    557                 return nullptr;
    558         }
    559 }
    560 
    561 // For passes, usually utility passes, that have a result.
    562 namespace result {
    563         template<typename core_t>
    564         static inline auto get( core_t & core, char ) -> decltype( core.result() ) {
    565                 return core.result();
    566         }
    567 
    568         template<typename core_t>
    569         static inline auto get( core_t & core, int ) -> decltype( core.result ) {
    570                 return core.result;
    571         }
    572 
    573         template<typename core_t>
    574         static inline void get( core_t &, long ) {}
    575 }
    576 
    577 } // namespace ast::__pass
    578 
    579 #undef __pedantic_pass_assertf
    580 #undef __pedantic_pass_assert
     519        static inline void get_result( core_t &, long ) {}
     520} // namespace __pass
     521} // namespace ast
  • src/AST/Print.cpp

    r24d6572 r34b4268  
    1616#include "Print.hpp"
    1717
    18 #include "Attribute.hpp"
    1918#include "Decl.hpp"
    2019#include "Expr.hpp"
    21 #include "Init.hpp"
    2220#include "Stmt.hpp"
    2321#include "Type.hpp"
    2422#include "TypeSubstitution.hpp"
    2523#include "CompilationState.h"
    26 #include "Common/Iterate.hpp"
     24
     25#include "Common/utility.h" // for group_iterate
    2726
    2827using namespace std;
     
    3029namespace ast {
    3130
    32 namespace {
    33 
    34 template<typename C, typename... T>
    35 constexpr array<C, sizeof...(T)> make_array( T&&... values ) {
    36         return array<C, sizeof...(T)>{ std::forward<T>( values )... };
    37 }
    38 
    39 namespace Names {
    40         static constexpr auto FuncSpecifiers = make_array<const char*>(
    41                 "inline", "_Noreturn", "fortran"
    42         );
    43 
    44         static constexpr auto StorageClasses = make_array<const char*>(
    45                 "extern", "static", "auto", "register", "__thread", "_Thread_local"
    46         );
    47 
    48         static constexpr auto Qualifiers = make_array<const char*>(
    49                 "const", "restrict", "volatile", "mutex", "_Atomic"
    50         );
    51 }
    52 
    53 template<typename bits_t, size_t N>
    54 void print( ostream & os, const bits_t & bits,
    55                 const array<const char *, N> & names ) {
    56         if ( !bits.any() ) return;
    57         for ( size_t i = 0 ; i < N ; i += 1 ) {
    58                 if ( bits[i] ) {
    59                         os << names[i] << ' ';
    60                 }
    61         }
     31template <typename C, typename... T>
     32constexpr array<C,sizeof...(T)> make_array(T&&... values)
     33{
     34        return array<C,sizeof...(T)>{
     35                std::forward<T>(values)...
     36        };
    6237}
    6338
     
    10580        static const char* Names[];
    10681
     82        struct Names {
     83                static constexpr auto FuncSpecifiers = make_array<const char*>(
     84                        "inline", "_Noreturn", "fortran"
     85                );
     86
     87                static constexpr auto StorageClasses = make_array<const char*>(
     88                        "extern", "static", "auto", "register", "__thread", "_Thread_local"
     89                );
     90
     91                static constexpr auto Qualifiers = make_array<const char*>(
     92                        "const", "restrict", "volatile", "mutex", "_Atomic"
     93                );
     94        };
     95
     96        template<typename storage_t, size_t N>
     97        void print(const storage_t & storage, const array<const char *, N> & Names ) {
     98                if ( storage.any() ) {
     99                        for ( size_t i = 0; i < Names.size(); i += 1 ) {
     100                                if ( storage[i] ) {
     101                                        os << Names[i] << ' ';
     102                                }
     103                        }
     104                }
     105        }
     106
     107        void print( const ast::Function::Specs & specs ) {
     108                print(specs, Names::FuncSpecifiers);
     109        }
     110
     111        void print( const ast::Storage::Classes & storage ) {
     112                print(storage, Names::StorageClasses);
     113        }
     114
     115        void print( const ast::CV::Qualifiers & qualifiers ) {
     116                print(qualifiers, Names::Qualifiers);
     117        }
     118
    107119        void print( const std::vector<ast::Label> & labels ) {
    108120                if ( labels.empty() ) return;
     
    209221        }
    210222
    211     void print( const ast::WaitStmt * node ) {
    212                 if ( node->timeout_time ) {
    213                         os << indent-1 << "timeout of:" << endl;
    214                         node->timeout_time->accept( *this );
    215 
    216                         if ( node->timeout_stmt ) {
    217                                 os << indent-1 << "... with statment:" << endl;
    218                                 node->timeout_stmt->accept( *this );
    219                         }
    220 
    221                         if ( node->timeout_cond ) {
    222                                 os << indent-1 << "... with condition:" << endl;
    223                                 node->timeout_cond->accept( *this );
    224                         }
    225                 }
    226 
    227                 if ( node->else_stmt ) {
    228                         os << indent-1 << "else:" << endl;
    229                         node->else_stmt->accept( *this );
    230 
    231                         if ( node->else_cond ) {
    232                                 os << indent-1 << "... with condition:" << endl;
    233                                 node->else_cond->accept( *this );
    234                         }
    235                 }
    236         }
    237 
    238223        void preprint( const ast::NamedTypeDecl * node ) {
    239224                if ( ! node->name.empty() ) {
     
    245230                }
    246231
    247                 ast::print( os, node->storage );
     232                print( node->storage );
    248233                os << node->typeString();
    249234
     
    287272
    288273        void preprint( const ast::Type * node ) {
    289                 ast::print( os, node->qualifiers );
     274                print( node->qualifiers );
    290275        }
    291276
     
    293278                print( node->forall );
    294279                print( node->assertions );
    295                 ast::print( os, node->qualifiers );
     280                print( node->qualifiers );
    296281        }
    297282
    298283        void preprint( const ast::BaseInstType * node ) {
    299284                print( node->attributes );
    300                 ast::print( os, node->qualifiers );
     285                print( node->qualifiers );
    301286        }
    302287
     
    309294                }
    310295
    311                 ast::print( os, node->storage );
     296                print( node->storage );
    312297
    313298                if ( node->type ) {
     
    353338                if ( ! short_mode ) printAll( node->attributes );
    354339
    355                 ast::print( os, node->storage );
    356                 ast::print( os, node->funcSpec );
     340                print( node->storage );
     341                print( node->funcSpec );
     342
     343
    357344
    358345                if ( node->type && node->isTypeFixed ) {
     
    397384                                --indent;
    398385                        }
    399                 }
    400 
    401                 if ( ! node->withExprs.empty() ) {
    402                         // Not with a clause, but the 'with clause'.
    403                         ++indent;
    404                         os << " with clause" << endl << indent;
    405                         printAll( node->withExprs );
    406                         --indent;
    407386                }
    408387
     
    767746        virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final {
    768747                os << "Suspend Statement";
    769                 switch (node->kind) {
    770                 case ast::SuspendStmt::None     : os << " with implicit target"; break;
    771                 case ast::SuspendStmt::Generator: os << " for generator"; break;
    772                 case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
     748                switch (node->type) {
     749                        case ast::SuspendStmt::None     : os << " with implicit target"; break;
     750                        case ast::SuspendStmt::Generator: os << " for generator"; break;
     751                        case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
    773752                }
    774753                os << endl;
     
    780759                }
    781760                ++indent;
    782 
    783                 return node;
    784         }
    785 
    786         virtual const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
    787                 os << indent-1 << "target: ";
    788                 safe_print( node->target );
    789 
    790                 if ( node->stmt ) {
    791                         os << indent-1 << "... with statment:" << endl;
    792                         node->stmt->accept( *this );
    793                 }
    794 
    795                 if ( node->when_cond ) {
    796                         os << indent-1 << "... with when condition:" << endl;
    797                         node->when_cond->accept( *this );
    798                 }
    799761
    800762                return node;
     
    838800        virtual const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    839801                os << indent-1 << "target function: ";
    840                 safe_print( node->target );
     802                safe_print( node->target_func );
    841803
    842804                if ( !node->target_args.empty() ) {
     
    852814                }
    853815
    854                 if ( node->when_cond ) {
     816                if ( node->cond ) {
    855817                        os << indent-1 << "... with condition:" << endl;
    856                         node->when_cond->accept( *this );
    857                 }
    858 
    859                 return node;
    860         }
    861 
    862     virtual const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
    863                 os << "Waituntil Statement" << endl;
    864                 indent += 2;
    865                 for( const auto & clause : node->clauses ) {
    866                         clause->accept( *this );
    867                 }
    868         print(node);    // calls print( const ast::WaitStmt * node )
     818                        node->cond->accept( *this );
     819                }
     820
    869821                return node;
    870822        }
     
    16751627};
    16761628
    1677 } // namespace
    1678 
    16791629void print( ostream & os, const ast::Node * node, Indenter indent ) {
    16801630        Printer printer { os, indent, false };
     
    16871637}
    16881638
    1689 void print( ostream & os, Function::Specs specs ) {
    1690         print( os, specs, Names::FuncSpecifiers );
     1639// Annoyingly these needed to be defined out of line to avoid undefined references.
     1640// The size here needs to be explicit but at least the compiler will produce an error
     1641// if the wrong size is specified
     1642constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
     1643constexpr array<const char*, 6> Printer::Names::StorageClasses;
     1644constexpr array<const char*, 5> Printer::Names::Qualifiers;
    16911645}
    1692 
    1693 void print( ostream & os, Storage::Classes storage ) {
    1694         print( os, storage, Names::StorageClasses );
    1695 }
    1696 
    1697 void print( ostream & os, CV::Qualifiers qualifiers ) {
    1698         print( os, qualifiers, Names::Qualifiers );
    1699 }
    1700 
    1701 } // namespace ast
  • src/AST/Print.hpp

    r24d6572 r34b4268  
    1616#pragma once
    1717
    18 #include <iosfwd>
     18#include <iostream>
     19#include <utility>   // for forward
    1920
    20 #include "AST/Fwd.hpp"
     21#include "AST/Node.hpp"
    2122#include "Common/Indenter.h"
    2223
    2324namespace ast {
     25
     26class Decl;
    2427
    2528/// Print a node with the given indenter
     
    4144}
    4245
    43 /// Print each cv-qualifier used in the set, followed by a space.
    44 void print( std::ostream & os, CV::Qualifiers );
    45 /// Print each function specifier used in the set, followed by a space.
    46 void print( std::ostream & os, Function::Specs );
    47 /// Print each storage class used in the set, followed by a space.
    48 void print( std::ostream & os, Storage::Classes );
    49 
    5046}
  • src/AST/Stmt.hpp

    r24d6572 r34b4268  
    1010// Created On       : Wed May  8 13:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Apr  5 10:34:00 2023
    13 // Update Count     : 37
     12// Last Modified On : Wed Apr 20 14:34:00 2022
     13// Update Count     : 36
    1414//
    1515
     
    205205};
    206206
    207 // A while loop or a do-while loop:
    208 enum WhileDoKind { While, DoWhile };
    209 
    210207// While loop: while (...) ... else ... or do ... while (...) else ...;
    211208class WhileDoStmt final : public Stmt {
     
    215212        ptr<Stmt> else_;
    216213        std::vector<ptr<Stmt>> inits;
    217         WhileDoKind isDoWhile;
     214        bool isDoWhile;
    218215
    219216        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
    220                                  const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )
     217                                 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
    221218                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {}
    222219
    223220        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_,
    224                                  const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )
     221                                 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
    225222                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {}
    226223
     
    367364  public:
    368365        ptr<CompoundStmt> then;
    369         enum Kind { None, Coroutine, Generator } kind = None;
    370 
    371         SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Kind kind, const std::vector<Label> && labels = {} )
    372                 : Stmt(loc, std::move(labels)), then(then), kind(kind) {}
     366        enum Type { None, Coroutine, Generator } type = None;
     367
     368        SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )
     369                : Stmt(loc, std::move(labels)), then(then), type(type) {}
    373370
    374371        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     
    378375};
    379376
    380 // Base class of WaitFor/WaitUntil statements
    381 // form: KEYWORD(...) ... timeout(...) ... else ...
    382 class WaitStmt : public Stmt {
    383   public:
    384     ptr<Expr> timeout_time;
     377// Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
     378class WaitForStmt final : public Stmt {
     379  public:
     380        std::vector<ptr<WaitForClause>> clauses;
     381        ptr<Expr> timeout_time;
    385382        ptr<Stmt> timeout_stmt;
    386383        ptr<Expr> timeout_cond;
     
    388385        ptr<Expr> else_cond;
    389386
    390     WaitStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     387        WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    391388                : Stmt(loc, std::move(labels)) {}
    392389
    393   private:
    394     WaitStmt * clone() const override = 0;
    395         MUTATE_FRIEND
    396 };
    397 
    398 // Base class for WaitFor/WaitUntil clauses
    399 // form: when( when_cond ) KEYWORD( target ) stmt
    400 class WhenClause : public StmtClause {
    401   public:
    402         ptr<Expr> target;
     390        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     391  private:
     392        WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
     393        MUTATE_FRIEND
     394};
     395
     396class WaitForClause final : public StmtClause {
     397  public:
     398        ptr<Expr> target_func;
     399        std::vector<ptr<Expr>> target_args;
    403400        ptr<Stmt> stmt;
    404         ptr<Expr> when_cond;
    405 
    406         WhenClause( const CodeLocation & loc )
     401        ptr<Expr> cond;
     402
     403        WaitForClause( const CodeLocation & loc )
    407404                : StmtClause( loc ) {}
    408405
    409         const WhenClause * accept( Visitor & v ) const override { return v.visit( this ); }
    410   private:
    411         WhenClause * clone() const override { return new WhenClause{ *this }; }
    412         MUTATE_FRIEND
    413 };
    414 
    415 // Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
    416 class WaitForStmt final : public WaitStmt {
    417   public:
    418         std::vector<ptr<WaitForClause>> clauses;
    419 
    420         WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    421                 : WaitStmt(loc, std::move(labels)) {}
    422 
    423         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    424   private:
    425         WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
    426         MUTATE_FRIEND
    427 };
    428 
    429 // Clause in a waitfor statement: waitfor (..., ...) ...
    430 class WaitForClause final : public WhenClause {
    431   public:
    432         std::vector<ptr<Expr>> target_args;
    433 
    434         WaitForClause( const CodeLocation & loc )
    435                 : WhenClause( loc ) {}
    436 
    437406        const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); }
    438407  private:
    439408        WaitForClause * clone() const override { return new WaitForClause{ *this }; }
    440         MUTATE_FRIEND
    441 };
    442 
    443 // waituntil statement: when (...) waituntil (...) ... timeout(...) ... else ...
    444 class WaitUntilStmt final : public WaitStmt {
    445   public:
    446     // Non-ast node used during compilation to store data needed to generate predicates
    447     //    and set initial status values for clauses
    448     // Used to create a tree corresponding to the structure of the clauses in a WaitUntil
    449     struct ClauseNode {
    450         enum Op { AND, OR, LEFT_OR, LEAF, ELSE, TIMEOUT } op; // operation/type tag
    451         // LEFT_OR used with TIMEOUT/ELSE to indicate that we ignore right hand side after parsing
    452 
    453         ClauseNode * left;
    454         ClauseNode * right;
    455         WhenClause * leaf;  // only set if this node is a leaf (points into vector of clauses)
    456 
    457         bool ambiguousWhen; // used to paint nodes of predicate tree based on when() clauses
    458         bool whenState;     // used to track if when_cond is toggled on or off for generating init values
    459         bool childOfAnd;      // true on leaf nodes that are children of AND, false otherwise
    460 
    461         ClauseNode( Op op, ClauseNode * left, ClauseNode * right )
    462             : op(op), left(left), right(right), leaf(nullptr),
    463             ambiguousWhen(false), whenState(true), childOfAnd(false) {}
    464         ClauseNode( Op op, WhenClause * leaf )
    465             : op(op), left(nullptr), right(nullptr), leaf(leaf),
    466             ambiguousWhen(false), whenState(true), childOfAnd(false) {}
    467         ClauseNode( WhenClause * leaf ) : ClauseNode(LEAF, leaf) {}
    468        
    469         ~ClauseNode() {
    470             if ( left ) delete left;
    471             if ( right ) delete right;
    472         }
    473     };
    474 
    475         std::vector<ptr<WhenClause>> clauses;
    476     ClauseNode * predicateTree;
    477 
    478         WaitUntilStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    479                 : WaitStmt(loc, std::move(labels)) {}
    480 
    481     ~WaitUntilStmt() { delete predicateTree; }
    482 
    483         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    484   private:
    485         WaitUntilStmt * clone() const override { return new WaitUntilStmt{ *this }; }
    486409        MUTATE_FRIEND
    487410};
     
    531454        MUTATE_FRIEND
    532455};
    533 
    534456} // namespace ast
    535457
  • src/AST/SymbolTable.cpp

    r24d6572 r34b4268  
    1818#include <cassert>
    1919
    20 #include "Copy.hpp"
    21 #include <iostream>
    22 #include <algorithm>
    23 
    2420#include "Decl.hpp"
    2521#include "Expr.hpp"
    2622#include "Inspect.hpp"
    2723#include "Type.hpp"
    28 #include "CodeGen/OperatorTable.h"         // for isCtorDtorAssign
     24#include "CodeGen/OperatorTable.h"  // for isCtorDtorAssign
    2925#include "Common/SemanticError.h"
    3026#include "Common/Stats/Counter.h"
     
    3228#include "InitTweak/InitTweak.h"
    3329#include "ResolvExpr/Cost.h"
    34 #include "ResolvExpr/CandidateFinder.hpp"  // for referenceToRvalueConversion
    35 #include "ResolvExpr/Unify.h"
     30#include "ResolvExpr/typeops.h"
    3631#include "SymTab/Mangler.h"
    3732
     
    7469        if ( baseExpr ) {
    7570                if (baseExpr->env) {
    76                         Expr * base = deepCopy(baseExpr);
     71                        Expr * base = shallowCopy(baseExpr);
    7772                        const TypeSubstitution * subs = baseExpr->env;
    7873                        base->env = nullptr;
     
    198193                        out.push_back(decl.second);
    199194                }
    200 
    201                 // std::cerr << otypeKey << ' ' << out.size() << std::endl;
    202195        }
    203196
     
    266259void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) {
    267260        // default handling of conflicts is to raise an error
    268         addIdCommon( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
     261        addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
    269262}
    270263
    271264void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) {
    272265        // default handling of conflicts is to raise an error
    273         addIdCommon( decl, OnConflict::error(), nullptr, deleter );
     266        addId( decl, OnConflict::error(), nullptr, deleter );
    274267}
    275268
     
    283276                } else {
    284277                        // typedef redeclarations are errors only if types are different
    285                         if ( ! ResolvExpr::typesCompatible( existing->base, added->base ) ) {
     278                        if ( ! ResolvExpr::typesCompatible( existing->base, added->base, SymbolTable{} ) ) {
    286279                                SemanticError( added->location, "redeclaration of " + added->name );
    287280                        }
     
    648641        } else if ( existing.id->linkage.is_mangled
    649642                        || ResolvExpr::typesCompatible(
    650                                 added->get_type(), existing.id->get_type() ) ) {
     643                                added->get_type(), existing.id->get_type(), SymbolTable{} ) ) {
    651644
    652645                // it is a conflict if one declaration is deleted and the other is not
     
    683676}
    684677
    685 void SymbolTable::addIdCommon(
    686                 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts,
    687                 const Expr * baseExpr, const Decl * deleter ) {
     678void SymbolTable::addId(
     679                const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
     680                const Decl * deleter ) {
    688681        SpecialFunctionKind kind = getSpecialFunctionKind(decl->name);
    689682        if (kind == NUMBER_OF_KINDS) { // not a special decl
    690                 addIdToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);
     683                addId(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);
    691684        }
    692685        else {
     
    701694                        assertf(false, "special decl with non-function type");
    702695                }
    703                 addIdToTable(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter);
    704         }
    705 }
    706 
    707 void SymbolTable::addIdToTable(
    708                 const DeclWithType * decl, const std::string & lookupKey,
    709                 IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts,
    710                 const Expr * baseExpr, const Decl * deleter ) {
     696                addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter);
     697        }
     698}
     699
     700void SymbolTable::addId(
     701                const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
     702                const Decl * deleter ) {
    711703        ++*stats().add_calls;
    712704        const std::string &name = decl->name;
     
    785777void SymbolTable::addMembers(
    786778                const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) {
    787         for ( const ptr<Decl> & decl : aggr->members ) {
    788                 auto dwt = decl.as<DeclWithType>();
    789                 if ( nullptr == dwt ) continue;
    790                 addIdCommon( dwt, handleConflicts, expr );
    791                 // Inline through unnamed struct/union members.
    792                 if ( "" != dwt->name ) continue;
    793                 const Type * t = dwt->get_type()->stripReferences();
    794                 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
    795                         if ( ! dynamic_cast<const StructInstType *>(rty)
    796                                 && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
    797                         ResolvExpr::Cost cost = ResolvExpr::Cost::zero;
    798                         ast::ptr<ast::TypeSubstitution> tmp = expr->env;
    799                         expr = mutate_field(expr, &Expr::env, nullptr);
    800                         const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );
    801                         base = mutate_field(base, &Expr::env, tmp);
    802 
    803                         addMembers(
    804                                 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );
     779        for ( const Decl * decl : aggr->members ) {
     780                if ( auto dwt = dynamic_cast< const DeclWithType * >( decl ) ) {
     781                        addId( dwt, handleConflicts, expr );
     782                        if ( dwt->name == "" ) {
     783                                const Type * t = dwt->get_type()->stripReferences();
     784                                if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
     785                                        if ( ! dynamic_cast<const StructInstType *>(rty)
     786                                                && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
     787                                        ResolvExpr::Cost cost = ResolvExpr::Cost::zero;
     788                                        ast::ptr<ast::TypeSubstitution> tmp = expr->env;
     789                                        expr = mutate_field(expr, &Expr::env, nullptr);
     790                                        const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );
     791                                        base = mutate_field(base, &Expr::env, tmp);
     792
     793                                        addMembers(
     794                                                rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );
     795                                }
     796                        }
    805797                }
    806798        }
  • src/AST/SymbolTable.hpp

    r24d6572 r34b4268  
    192192
    193193        /// common code for addId, addDeletedId, etc.
    194         void addIdCommon(
    195                 const DeclWithType * decl, OnConflict handleConflicts,
    196                 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr );
     194        void addId(
     195                const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr,
     196                const Decl * deleter = nullptr );
    197197
    198198        /// common code for addId when special decls are placed into separate tables
    199         void addIdToTable(
    200                 const DeclWithType * decl, const std::string & lookupKey,
    201                 IdTable::Ptr & idTable, OnConflict handleConflicts,
     199        void addId(
     200                const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts,
    202201                const Expr * baseExpr = nullptr, const Decl * deleter = nullptr);
    203 
     202       
    204203        /// adds all of the members of the Aggregate (addWith helper)
    205204        void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts );
  • src/AST/TranslationUnit.hpp

    r24d6572 r34b4268  
    1010// Created On       : Tue Jun 11 15:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Mar  9 16:41:00 2023
    13 // Update Count     : 2
     12// Last Modified On : Tue Mar 11 11:19:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    1717
    1818#include <map>
    19 #include <list>
     19#include <vector>
    2020
    2121#include "Fwd.hpp"
     
    2828
    2929        ptr<Type> sizeType;
    30         const FunctionDecl * dereference = nullptr;
    31         const StructDecl * dtorStruct = nullptr;
    32         const FunctionDecl * dtorDestroy = nullptr;
     30        const FunctionDecl * dereference;
     31        const StructDecl * dtorStruct;
     32        const FunctionDecl * dtorDestroy;
    3333};
    3434
  • src/AST/Type.cpp

    r24d6572 r34b4268  
    1010// Created On       : Mon May 13 15:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Apr  6 15:59:00 2023
    13 // Update Count     : 7
     12// Last Modified On : Thu Nov 24  9:49:00 2022
     13// Update Count     : 6
    1414//
    1515
     
    199199
    200200TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    201 : Type( q ), types( std::move(ts) ) {}
     201: Type( q ), types( std::move(ts) ), members() {
     202        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
     203        // named, but members without initializer nodes end up getting constructors, which breaks
     204        // things. This happens because the object decls have to be visited so that their types are
     205        // kept in sync with the types listed here. Ultimately, the types listed here should perhaps
     206        // be eliminated and replaced with a list-view over members. The temporary solution is to
     207        // make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not
     208        // constructed. Potential better solutions include:
     209        //   a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`,
     210        //      similar to the aggregate types.
     211        //   b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced
     212        //      by `genInit`, rather than the current boolean flag.
     213        members.reserve( types.size() );
     214        for ( const Type * ty : types ) {
     215                members.emplace_back( new ObjectDecl{
     216                        CodeLocation(), "", ty, new ListInit( CodeLocation(), {}, {}, NoConstruct ),
     217                        Storage::Classes{}, Linkage::Cforall } );
     218        }
     219}
    202220
    203221bool isUnboundType(const Type * type) {
  • src/AST/Type.hpp

    r24d6572 r34b4268  
    1010// Created On       : Thu May 9 10:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Apr  6 15:58:00 2023
    13 // Update Count     : 9
     12// Last Modified On : Thu Nov 24  9:47:00 2022
     13// Update Count     : 8
    1414//
    1515
     
    265265};
    266266
     267/// Function variable arguments flag
     268enum ArgumentFlag { FixedArgs, VariableArgs };
     269
    267270/// Type of a function `[R1, R2](*)(P1, P2, P3)`
    268271class FunctionType final : public Type {
     
    459462public:
    460463        std::vector<ptr<Type>> types;
     464        std::vector<ptr<Decl>> members;
    461465
    462466        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
  • src/AST/TypeEnvironment.cpp

    r24d6572 r34b4268  
    178178
    179179bool TypeEnvironment::combine(
    180                 const TypeEnvironment & o, OpenVarSet & open ) {
     180                const TypeEnvironment & o, OpenVarSet & open, const SymbolTable & symtab ) {
    181181        // short-circuit easy cases
    182182        if ( o.empty() ) return true;
     
    201201                        EqvClass & r = *rt;
    202202                        // merge bindings
    203                         if ( ! mergeBound( r, c, open ) ) return false;
     203                        if ( ! mergeBound( r, c, open, symtab ) ) return false;
    204204                        // merge previous unbound variables into this class, checking occurs if needed
    205205                        if ( r.bound ) for ( const auto & u : c.vars ) {
     
    216216                                } else if ( st != rt ) {
    217217                                        // bound, but not to the same class
    218                                         if ( ! mergeClasses( rt, st, open ) ) return false;
     218                                        if ( ! mergeClasses( rt, st, open, symtab ) ) return false;
    219219                                }       // ignore bound into the same class
    220220                        }
     
    280280bool TypeEnvironment::bindVar(
    281281                const TypeInstType * typeInst, const Type * bindTo, const TypeData & data,
    282                 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen
     282                AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen,
     283                const SymbolTable & symtab
    283284) {
    284285        // remove references from bound type, so that type variables can only bind to value types
     
    299300                        if ( unifyInexact(
    300301                                        newType, target, *this, need, have, open,
    301                                         widen & WidenMode{ it->allowWidening, true }, common ) ) {
     302                                        widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) {
    302303                                if ( common ) {
    303304                                        it->bound = std::move(common);
     
    320321                const TypeInstType * var1, const TypeInstType * var2, TypeData && data,
    321322                AssertionSet & need, AssertionSet & have, const OpenVarSet & open,
    322                 WidenMode widen
     323                WidenMode widen, const SymbolTable & symtab
    323324) {
    324325        auto c1 = internal_lookup( *var1 );
     
    357358
    358359                if ( unifyInexact(
    359                                 newType1, newType2, *this, need, have, open, newWidenMode, common ) ) {
     360                                newType1, newType2, *this, need, have, open, newWidenMode, symtab, common ) ) {
    360361                        c1->vars.insert( c2->vars.begin(), c2->vars.end() );
    361362                        c1->allowWidening = widen1 && widen2;
     
    408409
    409410bool TypeEnvironment::mergeBound(
    410                 EqvClass & to, const EqvClass & from, OpenVarSet & open ) {
     411                EqvClass & to, const EqvClass & from, OpenVarSet & open, const SymbolTable & symtab ) {
    411412        if ( from.bound ) {
    412413                if ( to.bound ) {
     
    418419
    419420                        if ( unifyInexact(
    420                                         toType, fromType, *this, need, have, open, widen, common ) ) {
     421                                        toType, fromType, *this, need, have, open, widen, symtab, common ) ) {
    421422                                // unifies, set common type if necessary
    422423                                if ( common ) {
     
    436437
    437438bool TypeEnvironment::mergeClasses(
    438         ClassList::iterator to, ClassList::iterator from, OpenVarSet & open
     439        ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab
    439440) {
    440441        EqvClass & r = *to, & s = *from;
    441442
    442443        // ensure bounds match
    443         if ( ! mergeBound( r, s, open ) ) return false;
     444        if ( ! mergeBound( r, s, open, symtab ) ) return false;
    444445
    445446        // check safely bindable
  • src/AST/TypeEnvironment.hpp

    r24d6572 r34b4268  
    6363
    6464                int cmp = d1->var->name.compare( d2->var->name );
    65                 return cmp > 0 || ( cmp == 0 && d1->result < d2->result );
     65                return cmp < 0 || ( cmp == 0 && d1->result < d2->result );
    6666        }
    6767};
     
    169169        /// Merge environment with this one, checking compatibility.
    170170        /// Returns false if fails, but does NOT roll back partial changes.
    171         bool combine( const TypeEnvironment & o, OpenVarSet & openVars );
     171        bool combine( const TypeEnvironment & o, OpenVarSet & openVars, const SymbolTable & symtab );
    172172
    173173        /// Add all type variables in environment to open var list
     
    183183                const TypeInstType * typeInst, const Type * bindTo, const TypeData & data,
    184184                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    185                 ResolvExpr::WidenMode widen );
     185                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    186186
    187187        /// Binds the type classes represented by `var1` and `var2` together; will add one or both
     
    190190                const TypeInstType * var1, const TypeInstType * var2, TypeData && data,
    191191                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    192                 ResolvExpr::WidenMode widen );
     192                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    193193
    194194        /// Disallows widening for all bindings in the environment
     
    205205        /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails
    206206        bool mergeBound(
    207                 EqvClass & to, const EqvClass & from, OpenVarSet & openVars );
     207                EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab );
    208208
    209209        /// Merges two type classes from local environment, returning false if fails
    210210        bool mergeClasses(
    211                 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars);
     211                ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars,
     212                const SymbolTable & symtab );
    212213
    213214        /// Private lookup API; returns array index of string, or env.size() for not found
  • src/AST/TypeSubstitution.cpp

    r24d6572 r34b4268  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr May 25 11:24:00 2023
    13 // Update Count     : 6
    14 //
    15 
     12// Last Modified On : Mon Jun  3 13:26:00 2017
     13// Update Count     : 5
     14//
     15
     16#include "Type.hpp"   // for TypeInstType, Type, StructInstType, UnionInstType
    1617#include "TypeSubstitution.hpp"
    1718
    18 #include "Type.hpp"   // for TypeInstType, Type, StructInstType, UnionInstType
    19 #include "Pass.hpp"   // for Pass, PureVisitor, WithGuards, WithVisitorRef
    20 
    2119namespace ast {
     20
     21
     22// size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
    2223
    2324TypeSubstitution::TypeSubstitution() {
     
    118119}
    119120
    120 // definitition must happen after PassVisitor is included so that WithGuards can be used
    121 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {
    122         //static size_t traceId;
    123 
    124         Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    125 
    126         const Type * postvisit( const TypeInstType * aggregateUseType );
    127 
    128         /// Records type variable bindings from forall-statements
    129         void previsit( const FunctionType * type );
    130         /// Records type variable bindings from forall-statements and instantiations of generic types
    131         // void handleAggregateType( const BaseInstType * type );
    132 
    133         // void previsit( const StructInstType * aggregateUseType );
    134         // void previsit( const UnionInstType * aggregateUseType );
    135 
    136         const TypeSubstitution & sub;
    137         int subCount = 0;
    138         bool freeOnly;
    139         typedef std::unordered_set< TypeEnvKey > BoundVarsType;
    140         BoundVarsType boundVars;
    141 };
    142 
    143 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
    144 
    145121void TypeSubstitution::normalize() {
    146122        Pass<Substituter> sub( *this, true );
     
    152128                }
    153129        } while ( sub.core.subCount );
    154 }
    155 
    156 TypeSubstitution::ApplyResult<Node> TypeSubstitution::applyBase(
    157                 const Node * input, bool isFree ) const {
    158         assert( input );
    159         Pass<Substituter> sub( *this, isFree );
    160         const Node * output = input->accept( sub );
    161         return { output, sub.core.subCount };
    162130}
    163131
  • src/AST/TypeSubstitution.hpp

    r24d6572 r34b4268  
    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 : Thr May 25 12:31:00 2023
    13 // Update Count     : 10
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Apr 30 22:52:47 2019
     13// Update Count     : 9
    1414//
    1515
     
    4646        TypeSubstitution &operator=( const TypeSubstitution &other );
    4747
    48         template< typename node_t >
     48        template< typename SynTreeClass >
    4949        struct ApplyResult {
    50                 ast::ptr<node_t> node;
     50                ast::ptr<SynTreeClass> node;
    5151                int count;
    5252        };
    5353
    54         template< typename node_t >
    55         ApplyResult<node_t> apply( const node_t * input ) const {
    56                 ApplyResult<Node> ret = applyBase( input, false );
    57                 return { ret.node.strict_as<node_t>(), ret.count };
    58         }
     54        template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const;
     55        template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const;
    5956
    6057        template< typename node_t, enum Node::ref_type ref_t >
    6158        int apply( ptr_base< node_t, ref_t > & input ) const {
    62                 ApplyResult<Node> ret = applyBase( input.get(), false );
    63                 input = ret.node.strict_as<node_t>();
     59                const node_t * p = input.get();
     60                auto ret = apply(p);
     61                input = ret.node;
    6462                return ret.count;
    6563        }
    6664
    67         template< typename node_t >
    68         ApplyResult<node_t> applyFree( const node_t * input ) const {
    69                 ApplyResult<Node> ret = applyBase( input, true );
    70                 return { ret.node.strict_as<node_t>(), ret.count };
    71         }
    72 
    7365        template< typename node_t, enum Node::ref_type ref_t >
    7466        int applyFree( ptr_base< node_t, ref_t > & input ) const {
    75                 ApplyResult<Node> ret = applyBase( input.get(), true );
    76                 input = ret.node.strict_as<node_t>();
     67                const node_t * p = input.get();
     68                auto ret = applyFree(p);
     69                input = ret.node;
    7770                return ret.count;
    7871        }
     
    10497        // Mutator that performs the substitution
    10598        struct Substituter;
    106         ApplyResult<Node> applyBase( const Node * input, bool isFree ) const;
    10799
    108100        // TODO: worry about traversing into a forall-qualified function type or type decl with assertions
     
    166158} // namespace ast
    167159
     160// include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
     161// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
     162#include "Pass.hpp"
     163#include "Copy.hpp"
     164
     165namespace ast {
     166
     167// definitition must happen after PassVisitor is included so that WithGuards can be used
     168struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {
     169                static size_t traceId;
     170
     171                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
     172
     173                const Type * postvisit( const TypeInstType * aggregateUseType );
     174
     175                /// Records type variable bindings from forall-statements
     176                void previsit( const FunctionType * type );
     177                /// Records type variable bindings from forall-statements and instantiations of generic types
     178                // void handleAggregateType( const BaseInstType * type );
     179
     180                // void previsit( const StructInstType * aggregateUseType );
     181                // void previsit( const UnionInstType * aggregateUseType );
     182
     183                const TypeSubstitution & sub;
     184                int subCount = 0;
     185                bool freeOnly;
     186                typedef std::unordered_set< TypeEnvKey > BoundVarsType;
     187                BoundVarsType boundVars;
     188
     189};
     190
     191template< typename SynTreeClass >
     192TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
     193        assert( input );
     194        Pass<Substituter> sub( *this, false );
     195        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
     196        return { input, sub.core.subCount };
     197}
     198
     199template< typename SynTreeClass >
     200TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
     201        assert( input );
     202        Pass<Substituter> sub( *this, true );
     203        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
     204        return { input, sub.core.subCount };
     205}
     206
     207} // namespace ast
     208
    168209// Local Variables: //
    169210// tab-width: 4 //
  • src/AST/Visitor.hpp

    r24d6572 r34b4268  
    5050    virtual const ast::FinallyClause *    visit( const ast::FinallyClause        * ) = 0;
    5151    virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
    52     virtual const ast::WhenClause *       visit( const ast::WhenClause           * ) = 0;
    5352    virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
    5453    virtual const ast::WaitForClause *    visit( const ast::WaitForClause        * ) = 0;
    55     virtual const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) = 0;
    5654    virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
    5755    virtual const ast::NullStmt *         visit( const ast::NullStmt             * ) = 0;
  • src/AST/porting.md

    r24d6572 r34b4268  
    213213* `get_statement()` exclusively used for code location, replaced with `CodeLocation` field
    214214
    215 `CaseStmt` => `CaseClause`
     215`CaseStmt`
    216216* `_isDefault` has been removed
    217217  * `isDefault` calculates value from `cond`
     
    227227* `block` -> `body` and `finallyBlock` -> `finally`
    228228
    229 `ThrowStmt` and `CatchStmt` => `CatchClause`
     229`ThrowStmt` `CatchStmt`
    230230* moved `Kind` enums to shared `ast::ExceptionKind` enum
    231231
    232 `FinallyStmt` => `FinallyClause`
     232`FinallyStmt`
    233233* `block` -> `body`
    234234
     
    280280* Template class, with specializations and using to implement some other types:
    281281  * `StructInstType`, `UnionInstType` & `EnumInstType`
    282   * `baseStruct`, `baseUnion` & `baseEnum` => `base`
    283282
    284283`TypeInstType`
  • src/CodeGen/CodeGenerator.cc

    r24d6572 r34b4268  
    1717#include <cassert>                   // for assert, assertf
    1818#include <list>                      // for _List_iterator, list, list<>::it...
    19 #include <sstream>                   // for stringstream
    2019
    2120#include "AST/Decl.hpp"              // for DeclWithType
    2221#include "Common/UniqueName.h"       // for UniqueName
     22#include "Common/utility.h"          // for CodeLocation, toString
    2323#include "GenType.h"                 // for genType
    2424#include "InitTweak/InitTweak.h"     // for getPointerBase
     
    273273        }
    274274
    275         template<typename pass_type>
    276         inline void genEnumInitializer( PassVisitor<pass_type> * visitor, Type * baseType, std::ostream & output,
    277         Initializer * init, long long * cur_val, Options options) {
    278                 auto baseTypeAsBasic = baseType ? dynamic_cast<BasicType *>( baseType ) : nullptr;
    279                 if ( init ) { // If value has an explicit initiazatior
    280                         output << " = ";
    281                         output << "(" << genType(baseType, "", options) << ")";
    282                         init->accept( *visitor );
    283                         if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // if it is an integral type and initilizer offered,
    284                         // need to update the cur_val
    285                                 Expression* expr = ((SingleInit *)(init))->value;
    286                                 while ( auto temp = dynamic_cast<CastExpr *>(expr) ) { // unwrap introduced cast
    287                                         expr = temp->arg;
    288                                 }
    289                                 *cur_val = ((ConstantExpr *)expr)->constant.get_ival()+1;
    290                         }
    291                 } else if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // integral implicitly init to cur_val + 1
    292                         output << " = " << "(" << genType(baseType, "", options) << ")";
    293                         output << (*cur_val)++;
    294                 }
    295         }
    296 
    297275        void CodeGenerator::postvisit( EnumDecl * enumDecl ) {
    298276                extension( enumDecl );
    299277                std::list< Declaration* > &memb = enumDecl->get_members();
    300278                if (enumDecl->base && ! memb.empty()) {
    301                         long long cur_val = 0;
     279                        unsigned long long last_val = -1; // if the first enum value has no explicit initializer,
     280                        // as other
    302281                        for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
    303282                                ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
    304283                                assert( obj );
    305284                                output << "static ";
    306                                 output << genType(enumDecl->base, mangleName( obj ), options);
    307                                 genEnumInitializer( visitor, enumDecl->base, output, obj->get_init(), &cur_val, options);
     285                                output << genType(enumDecl->base, "", options) << " const ";
     286                                output << mangleName( obj ) << " ";
     287                                output << " = ";
     288                                output << "(" << genType(enumDecl->base, "", options) << ")";
     289                                if ( (BasicType *)(enumDecl->base) && ((BasicType *)(enumDecl->base))->isWholeNumber() ) {
     290                                        if ( obj->get_init() ) {
     291                                                obj->get_init()->accept( *visitor );
     292                                                Expression* expr = ((SingleInit *)(obj->init))->value;
     293                                                while ( auto temp = dynamic_cast<CastExpr *>(expr) ) {
     294                                                        expr = temp->arg;
     295                                                }
     296                                                last_val = ((ConstantExpr *)expr)->constant.get_ival();
     297                                        } else {
     298                                                output << ++last_val;
     299                                        } // if
     300                                } else {
     301                                        if ( obj->get_init() ) {
     302                                                obj->get_init()->accept( *visitor );
     303                                        } else {
     304                                                // Should not reach here!
     305                                        }
     306                                }
    308307                                output << ";" << endl;
    309308                        } // for
  • src/CodeGen/GenType.cc

    r24d6572 r34b4268  
    255255        void GenType::postvisit( EnumInstType * enumInst ) {
    256256                if ( enumInst->baseEnum && enumInst->baseEnum->base ) {
    257                         typeString = genType(enumInst->baseEnum->base, typeString, options);
     257                        typeString = genType(enumInst->baseEnum->base, "", options) + typeString;
    258258                } else {
    259259                        typeString = enumInst->name + " " + typeString;
  • src/Common/CodeLocationTools.cpp

    r24d6572 r34b4268  
    128128    macro(FinallyClause, FinallyClause) \
    129129    macro(SuspendStmt, Stmt) \
    130     macro(WhenClause, WhenClause) \
    131130    macro(WaitForStmt, Stmt) \
    132131    macro(WaitForClause, WaitForClause) \
    133     macro(WaitUntilStmt, Stmt) \
    134132    macro(WithStmt, Decl) \
    135133    macro(NullStmt, NullStmt) \
     
    210208
    211209struct LeafKindVisitor : public ast::Visitor {
    212         LeafKind result;
     210        LeafKind kind;
    213211
    214212#define VISIT(node_type, return_type) \
    215213        const ast::return_type * visit( const ast::node_type * ) final { \
    216                 result = LeafKind::node_type; \
     214                kind = LeafKind::node_type; \
    217215                return nullptr; \
    218216        }
     
    224222
    225223LeafKind get_leaf_kind( ast::Node const * node ) {
    226         return ast::Pass<LeafKindVisitor>::read( node );
     224        LeafKindVisitor visitor;
     225        node->accept( visitor );
     226        return visitor.kind;
    227227}
    228228
  • src/Common/DeclStats.cpp

    r24d6572 r34b4268  
    2323#include <iostream>
    2424#include <map>
    25 #include <sstream>
    2625#include <unordered_map>
    2726#include <unordered_set>
  • src/Common/Eval.cc

    r24d6572 r34b4268  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Eval.cc -- Evaluate parts of the ast at compile time.
     7// utility.h --
    88//
    99// Author           : Richard C. Bilson
     
    1313// Update Count     : 119
    1414//
    15 
    16 #include "Eval.h"
    1715
    1816#include <utility> // for pair
  • src/Common/ResolvProtoDump.cpp

    r24d6572 r34b4268  
    1919#include <iostream>
    2020#include <set>
    21 #include <sstream>
    2221#include <unordered_set>
    2322
     
    2726#include "AST/Type.hpp"
    2827#include "CodeGen/OperatorTable.h"
     28#include "Common/utility.h"
    2929
    3030namespace {
  • src/Common/ScopedMap.h

    r24d6572 r34b4268  
    3737                template<typename N>
    3838                Scope(N && n) : map(), note(std::forward<N>(n)) {}
    39 
     39               
    4040                Scope() = default;
    4141                Scope(const Scope &) = default;
     
    4646        typedef std::vector< Scope > ScopeList;
    4747
    48         /// Scoped list of maps.
    49         ScopeList scopes;
     48        ScopeList scopes; ///< scoped list of maps
    5049public:
    5150        typedef typename MapType::key_type key_type;
     
    5958        typedef typename MapType::const_pointer const_pointer;
    6059
    61         // Both iterator types are complete bidrectional iterators, see below.
    62         class iterator;
    63         class const_iterator;
     60        class iterator : public std::iterator< std::bidirectional_iterator_tag, value_type > {
     61        friend class ScopedMap;
     62        friend class const_iterator;
     63                typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     64                typedef typename ScopedMap::ScopeList scope_list;
     65                typedef typename scope_list::size_type size_type;
     66
     67                /// Checks if this iterator points to a valid item
     68                bool is_valid() const {
     69                        return it != (*scopes)[level].map.end();
     70                }
     71
     72                /// Increments on invalid
     73                iterator & next_valid() {
     74                        if ( ! is_valid() ) { ++(*this); }
     75                        return *this;
     76                }
     77
     78                /// Decrements on invalid
     79                iterator & prev_valid() {
     80                        if ( ! is_valid() ) { --(*this); }
     81                        return *this;
     82                }
     83
     84                iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
     85                        : scopes(&_scopes), it(_it), level(inLevel) {}
     86        public:
     87                iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     88                iterator & operator= (const iterator & that) {
     89                        scopes = that.scopes; level = that.level; it = that.it;
     90                        return *this;
     91                }
     92
     93                reference operator* () { return *it; }
     94                pointer operator-> () const { return it.operator->(); }
     95
     96                iterator & operator++ () {
     97                        if ( it == (*scopes)[level].map.end() ) {
     98                                if ( level == 0 ) return *this;
     99                                --level;
     100                                it = (*scopes)[level].map.begin();
     101                        } else {
     102                                ++it;
     103                        }
     104                        return next_valid();
     105                }
     106                iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     107
     108                iterator & operator-- () {
     109                        // may fail if this is the begin iterator; allowed by STL spec
     110                        if ( it == (*scopes)[level].map.begin() ) {
     111                                ++level;
     112                                it = (*scopes)[level].map.end();
     113                        }
     114                        --it;
     115                        return prev_valid();
     116                }
     117                iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     118
     119                bool operator== (const iterator & that) const {
     120                        return scopes == that.scopes && level == that.level && it == that.it;
     121                }
     122                bool operator!= (const iterator & that) const { return !( *this == that ); }
     123
     124                size_type get_level() const { return level; }
     125
     126                Note & get_note() { return (*scopes)[level].note; }
     127                const Note & get_note() const { return (*scopes)[level].note; }
     128
     129        private:
     130                scope_list *scopes;
     131                wrapped_iterator it;
     132                size_type level;
     133        };
     134
     135        class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
     136                                                     value_type > {
     137        friend class ScopedMap;
     138                typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     139                typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
     140                typedef typename ScopedMap::ScopeList scope_list;
     141                typedef typename scope_list::size_type size_type;
     142
     143                /// Checks if this iterator points to a valid item
     144                bool is_valid() const {
     145                        return it != (*scopes)[level].map.end();
     146                }
     147
     148                /// Increments on invalid
     149                const_iterator & next_valid() {
     150                        if ( ! is_valid() ) { ++(*this); }
     151                        return *this;
     152                }
     153
     154                /// Decrements on invalid
     155                const_iterator & prev_valid() {
     156                        if ( ! is_valid() ) { --(*this); }
     157                        return *this;
     158                }
     159
     160                const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
     161                        : scopes(&_scopes), it(_it), level(inLevel) {}
     162        public:
     163                const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     164                const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     165                const_iterator & operator= (const iterator & that) {
     166                        scopes = that.scopes; level = that.level; it = that.it;
     167                        return *this;
     168                }
     169                const_iterator & operator= (const const_iterator & that) {
     170                        scopes = that.scopes; level = that.level; it = that.it;
     171                        return *this;
     172                }
     173
     174                const_reference operator* () { return *it; }
     175                const_pointer operator-> () { return it.operator->(); }
     176
     177                const_iterator & operator++ () {
     178                        if ( it == (*scopes)[level].map.end() ) {
     179                                if ( level == 0 ) return *this;
     180                                --level;
     181                                it = (*scopes)[level].map.begin();
     182                        } else {
     183                                ++it;
     184                        }
     185                        return next_valid();
     186                }
     187                const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     188
     189                const_iterator & operator-- () {
     190                        // may fail if this is the begin iterator; allowed by STL spec
     191                        if ( it == (*scopes)[level].map.begin() ) {
     192                                ++level;
     193                                it = (*scopes)[level].map.end();
     194                        }
     195                        --it;
     196                        return prev_valid();
     197                }
     198                const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     199
     200                bool operator== (const const_iterator & that) const {
     201                        return scopes == that.scopes && level == that.level && it == that.it;
     202                }
     203                bool operator!= (const const_iterator & that) const { return !( *this == that ); }
     204
     205                size_type get_level() const { return level; }
     206
     207                const Note & get_note() const { return (*scopes)[level].note; }
     208
     209        private:
     210                scope_list const *scopes;
     211                wrapped_const_iterator it;
     212                size_type level;
     213        };
    64214
    65215        /// Starts a new scope
     
    147297        }
    148298
     299        template< typename value_type_t >
     300        std::pair< iterator, bool > insert( iterator at, value_type_t && value ) {
     301                MapType & scope = (*at.scopes)[ at.level ].map;
     302                std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
     303                return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
     304        }
     305
    149306        template< typename value_t >
    150307        std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }
     
    167324        }
    168325
    169         /// Erases element with key in the innermost scope that has it.
    170         size_type erase( const Key & key ) {
    171                 for ( auto it = scopes.rbegin() ; it != scopes.rend() ; ++it ) {
    172                         size_type i = it->map.erase( key );
    173                         if ( 0 != i ) return i;
    174                 }
    175                 return 0;
     326        iterator erase( iterator pos ) {
     327                MapType & scope = (*pos.scopes)[ pos.level ].map;
     328                const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it );
     329                iterator it( *pos.scopes, new_it, pos.level );
     330                return it.next_valid();
    176331        }
    177332
     
    188343                return c;
    189344        }
    190 
    191         bool contains( const Key & key ) const {
    192                 return find( key ) != cend();
    193         }
    194 };
    195 
    196 template<typename Key, typename Value, typename Note>
    197 class ScopedMap<Key, Value, Note>::iterator :
    198                 public std::iterator< std::bidirectional_iterator_tag, value_type > {
    199         friend class ScopedMap;
    200         friend class const_iterator;
    201         typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    202         typedef typename ScopedMap::ScopeList scope_list;
    203         typedef typename scope_list::size_type size_type;
    204 
    205         /// Checks if this iterator points to a valid item
    206         bool is_valid() const {
    207                 return it != (*scopes)[level].map.end();
    208         }
    209 
    210         /// Increments on invalid
    211         iterator & next_valid() {
    212                 if ( ! is_valid() ) { ++(*this); }
    213                 return *this;
    214         }
    215 
    216         /// Decrements on invalid
    217         iterator & prev_valid() {
    218                 if ( ! is_valid() ) { --(*this); }
    219                 return *this;
    220         }
    221 
    222         iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
    223                 : scopes(&_scopes), it(_it), level(inLevel) {}
    224 public:
    225         iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    226         iterator & operator= (const iterator & that) {
    227                 scopes = that.scopes; level = that.level; it = that.it;
    228                 return *this;
    229         }
    230 
    231         reference operator* () { return *it; }
    232         pointer operator-> () const { return it.operator->(); }
    233 
    234         iterator & operator++ () {
    235                 if ( it == (*scopes)[level].map.end() ) {
    236                         if ( level == 0 ) return *this;
    237                         --level;
    238                         it = (*scopes)[level].map.begin();
    239                 } else {
    240                         ++it;
    241                 }
    242                 return next_valid();
    243         }
    244         iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    245 
    246         iterator & operator-- () {
    247                 // may fail if this is the begin iterator; allowed by STL spec
    248                 if ( it == (*scopes)[level].map.begin() ) {
    249                         ++level;
    250                         it = (*scopes)[level].map.end();
    251                 }
    252                 --it;
    253                 return prev_valid();
    254         }
    255         iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    256 
    257         bool operator== (const iterator & that) const {
    258                 return scopes == that.scopes && level == that.level && it == that.it;
    259         }
    260         bool operator!= (const iterator & that) const { return !( *this == that ); }
    261 
    262         size_type get_level() const { return level; }
    263 
    264         Note & get_note() { return (*scopes)[level].note; }
    265         const Note & get_note() const { return (*scopes)[level].note; }
    266 
    267 private:
    268         scope_list *scopes;
    269         wrapped_iterator it;
    270         size_type level;
    271 };
    272 
    273 template<typename Key, typename Value, typename Note>
    274 class ScopedMap<Key, Value, Note>::const_iterator :
    275                 public std::iterator< std::bidirectional_iterator_tag, value_type > {
    276         friend class ScopedMap;
    277         typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    278         typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
    279         typedef typename ScopedMap::ScopeList scope_list;
    280         typedef typename scope_list::size_type size_type;
    281 
    282         /// Checks if this iterator points to a valid item
    283         bool is_valid() const {
    284                 return it != (*scopes)[level].map.end();
    285         }
    286 
    287         /// Increments on invalid
    288         const_iterator & next_valid() {
    289                 if ( ! is_valid() ) { ++(*this); }
    290                 return *this;
    291         }
    292 
    293         /// Decrements on invalid
    294         const_iterator & prev_valid() {
    295                 if ( ! is_valid() ) { --(*this); }
    296                 return *this;
    297         }
    298 
    299         const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
    300                 : scopes(&_scopes), it(_it), level(inLevel) {}
    301 public:
    302         const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    303         const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    304         const_iterator & operator= (const iterator & that) {
    305                 scopes = that.scopes; level = that.level; it = that.it;
    306                 return *this;
    307         }
    308         const_iterator & operator= (const const_iterator & that) {
    309                 scopes = that.scopes; level = that.level; it = that.it;
    310                 return *this;
    311         }
    312 
    313         const_reference operator* () { return *it; }
    314         const_pointer operator-> () { return it.operator->(); }
    315 
    316         const_iterator & operator++ () {
    317                 if ( it == (*scopes)[level].map.end() ) {
    318                         if ( level == 0 ) return *this;
    319                         --level;
    320                         it = (*scopes)[level].map.begin();
    321                 } else {
    322                         ++it;
    323                 }
    324                 return next_valid();
    325         }
    326         const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    327 
    328         const_iterator & operator-- () {
    329                 // may fail if this is the begin iterator; allowed by STL spec
    330                 if ( it == (*scopes)[level].map.begin() ) {
    331                         ++level;
    332                         it = (*scopes)[level].map.end();
    333                 }
    334                 --it;
    335                 return prev_valid();
    336         }
    337         const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    338 
    339         bool operator== (const const_iterator & that) const {
    340                 return scopes == that.scopes && level == that.level && it == that.it;
    341         }
    342         bool operator!= (const const_iterator & that) const { return !( *this == that ); }
    343 
    344         size_type get_level() const { return level; }
    345 
    346         const Note & get_note() const { return (*scopes)[level].note; }
    347 
    348 private:
    349         scope_list const *scopes;
    350         wrapped_const_iterator it;
    351         size_type level;
    352345};
    353346
  • src/Common/SemanticError.h

    r24d6572 r34b4268  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 25 12:01:31 2023
    13 // Update Count     : 37
     12// Last Modified On : Wed May  4 14:08:26 2022
     13// Update Count     : 35
    1414//
    1515
     
    5454
    5555constexpr WarningData WarningFormats[] = {
    56         {"self-assign"              , Severity::Warn    , "self assignment of expression: %s"                          },
    57         {"reference-conversion"     , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
    58         {"qualifiers-zero_t-one_t"  , Severity::Warn    , "questionable use of type qualifier(s) with %s"              },
    59         {"aggregate-forward-decl"   , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
    60         {"superfluous-decl"         , Severity::Warn    , "declaration does not allocate storage: %s"                  },
    61         {"superfluous-else"         , Severity::Warn    , "else clause never executed for empty loop conditional"      },
    62         {"gcc-attributes"           , Severity::Warn    , "invalid attribute: %s"                                      },
    63         {"c++-like-copy"            , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
    64         {"depreciated-trait-syntax" , Severity::Warn    , "trait type-parameters are now specified using the forall clause" },
     56        {"self-assign"            , Severity::Warn    , "self assignment of expression: %s"                          },
     57        {"reference-conversion"   , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
     58        {"qualifiers-zero_t-one_t", Severity::Warn    , "questionable use of type qualifier %s with %s"              },
     59        {"aggregate-forward-decl" , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
     60        {"superfluous-decl"       , Severity::Warn    , "declaration does not allocate storage: %s"                  },
     61        {"superfluous-else"       , Severity::Warn    , "else clause never executed for empty loop conditional"      },
     62        {"gcc-attributes"         , Severity::Warn    , "invalid attribute: %s"                                      },
     63        {"c++-like-copy"          , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
    6564};
    6665
     
    7473        GccAttributes,
    7574        CppCopy,
    76         DeprecTraitSyntax,
    7775        NUMBER_OF_WARNINGS, // This MUST be the last warning
    7876};
  • src/Common/module.mk

    r24d6572 r34b4268  
    2020        Common/CodeLocationTools.hpp \
    2121        Common/CodeLocationTools.cpp \
     22        Common/CompilerError.h \
     23        Common/Debug.h \
    2224        Common/DeclStats.hpp \
    2325        Common/DeclStats.cpp \
    2426        Common/ErrorObjects.h \
    2527        Common/Eval.cc \
    26         Common/Eval.h \
    2728        Common/Examine.cc \
    2829        Common/Examine.h \
     
    3031        Common/Indenter.h \
    3132        Common/Indenter.cc \
    32         Common/Iterate.hpp \
    3333        Common/PassVisitor.cc \
    3434        Common/PassVisitor.h \
     
    5252        Common/Stats/Time.cc \
    5353        Common/Stats/Time.h \
    54         Common/ToString.hpp \
     54        Common/UnimplementedError.h \
    5555        Common/UniqueName.cc \
    5656        Common/UniqueName.h \
  • src/Common/utility.h

    r24d6572 r34b4268  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // utility.h -- General utilities used across the compiler.
     7// utility.h --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Feb 17 15:25:00 2023
    13 // Update Count     : 53
     12// Last Modified On : Mon Apr 25 14:26:00 2022
     13// Update Count     : 51
    1414//
    1515
     
    1919#include <cctype>
    2020#include <algorithm>
     21#include <functional>
    2122#include <iostream>
     23#include <iterator>
    2224#include <list>
    2325#include <memory>
     26#include <sstream>
    2427#include <string>
    2528#include <type_traits>
     29#include <utility>
    2630#include <vector>
    2731#include <cstring>                                                                              // memcmp
     
    4549                return 0;
    4650        } // if
     51}
     52
     53template< typename T, typename U >
     54struct maybeBuild_t {
     55        static T * doit( const U *orig ) {
     56                if ( orig ) {
     57                        return orig->build();
     58                } else {
     59                        return 0;
     60                } // if
     61        }
     62};
     63
     64template< typename T, typename U >
     65static inline T * maybeBuild( const U *orig ) {
     66        return maybeBuild_t<T,U>::doit(orig);
     67}
     68
     69template< typename T, typename U >
     70static inline T * maybeMoveBuild( const U *orig ) {
     71        T* ret = maybeBuild<T>(orig);
     72        delete orig;
     73        return ret;
    4774}
    4875
     
    141168        splice( src, dst );
    142169        dst.swap( src );
     170}
     171
     172template < typename T >
     173void toString_single( std::ostream & os, const T & value ) {
     174        os << value;
     175}
     176
     177template < typename T, typename... Params >
     178void toString_single( std::ostream & os, const T & value, const Params & ... params ) {
     179        os << value;
     180        toString_single( os, params ... );
     181}
     182
     183template < typename ... Params >
     184std::string toString( const Params & ... params ) {
     185        std::ostringstream os;
     186        toString_single( os, params... );
     187        return os.str();
     188}
     189
     190#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
     191
     192// replace element of list with all elements of another list
     193template< typename T >
     194void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) {
     195        typename std::list< T >::iterator next = pos; advance( next, 1 );
     196
     197        //if ( next != org.end() ) {
     198        org.erase( pos );
     199        org.splice( next, with );
     200        //}
     201
     202        return;
     203}
     204
     205// replace range of a list with a single element
     206template< typename T >
     207void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) {
     208        org.insert( begin, with );
     209        org.erase( begin, end );
    143210}
    144211
     
    169236}
    170237
     238template< typename... Args >
     239auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {
     240  return zipWith(std::forward<Args>(args)..., std::make_pair);
     241}
     242
     243template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction >
     244void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) {
     245        while ( b1 != e1 && b2 != e2 )
     246                *out++ = func(*b1++, *b2++);
     247}
     248
     249// it's nice to actually be able to increment iterators by an arbitrary amount
     250template< class InputIt, class Distance >
     251InputIt operator+( InputIt it, Distance n ) {
     252        advance(it, n);
     253        return it;
     254}
     255
     256template< typename T >
     257void warn_single( const T & arg ) {
     258        std::cerr << arg << std::endl;
     259}
     260
     261template< typename T, typename... Params >
     262void warn_single(const T & arg, const Params & ... params ) {
     263        std::cerr << arg;
     264        warn_single( params... );
     265}
     266
     267template< typename... Params >
     268void warn( const Params & ... params ) {
     269        std::cerr << "Warning: ";
     270        warn_single( params... );
     271}
     272
    171273// determines if pref is a prefix of str
    172274static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) {
    173275        if ( pref.size() > str.size() ) return false;
    174         return pref == str.substr(start, pref.size());
    175 }
     276    return 0 == memcmp( str.c_str() + start, pref.c_str(), pref.size() );
     277        // return prefix == full.substr(0, prefix.size()); // for future, requires c++17
     278}
     279
     280// -----------------------------------------------------------------------------
     281// Ref Counted Singleton class
     282// Objects that inherit from this class will have at most one reference to it
     283// but if all references die, the object will be deleted.
     284
     285template< typename ThisType >
     286class RefCountSingleton {
     287  public:
     288        static std::shared_ptr<ThisType> get() {
     289                if( global_instance.expired() ) {
     290                        std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>();
     291                        global_instance = new_instance;
     292                        return std::move(new_instance);
     293                }
     294                return global_instance.lock();
     295        }
     296  private:
     297        static std::weak_ptr<ThisType> global_instance;
     298};
     299
     300template< typename ThisType >
     301std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance;
    176302
    177303// -----------------------------------------------------------------------------
     
    230356        ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } }
    231357};
     358
     359// -----------------------------------------------------------------------------
     360// Helper struct and function to support
     361// for ( val : reverseIterate( container ) ) {}
     362// syntax to have a for each that iterates backwards
     363
     364template< typename T >
     365struct reverse_iterate_t {
     366        T& ref;
     367
     368        reverse_iterate_t( T & ref ) : ref(ref) {}
     369
     370        // this does NOT work on const T!!!
     371        // typedef typename T::reverse_iterator iterator;
     372        auto begin() { return ref.rbegin(); }
     373        auto end() { return ref.rend(); }
     374};
     375
     376template< typename T >
     377reverse_iterate_t< T > reverseIterate( T & ref ) {
     378        return reverse_iterate_t< T >( ref );
     379}
     380
     381template< typename T >
     382struct enumerate_t {
     383        template<typename val_t>
     384        struct value_t {
     385                val_t & val;
     386                size_t idx;
     387        };
     388
     389        template< typename iter_t, typename val_t >
     390        struct iterator_t {
     391                iter_t it;
     392                size_t idx;
     393
     394                iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {}
     395
     396                value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; }
     397
     398                bool operator==(const iterator_t & o) const { return o.it == it; }
     399                bool operator!=(const iterator_t & o) const { return o.it != it; }
     400
     401                iterator_t & operator++() {
     402                        it++;
     403                        idx++;
     404                        return *this;
     405                }
     406
     407                using difference_type   = typename std::iterator_traits< iter_t >::difference_type;
     408                using value_type        = value_t<val_t>;
     409                using pointer           = value_t<val_t> *;
     410                using reference         = value_t<val_t> &;
     411                using iterator_category = std::forward_iterator_tag;
     412        };
     413
     414        T & ref;
     415
     416        using iterator = iterator_t< typename T::iterator, typename T::value_type >;
     417        using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >;
     418
     419        iterator begin() { return iterator( ref.begin(), 0 ); }
     420        iterator end()   { return iterator( ref.end(), ref.size() ); }
     421
     422        const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); }
     423        const_iterator end()   const { return const_iterator( ref.cend(), ref.size() ); }
     424
     425        const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); }
     426        const_iterator cend()   const { return const_iterator( ref.cend(), ref.size() ); }
     427};
     428
     429template< typename T >
     430enumerate_t<T> enumerate( T & ref ) {
     431        return enumerate_t< T >{ ref };
     432}
     433
     434template< typename T >
     435const enumerate_t< const T > enumerate( const T & ref ) {
     436        return enumerate_t< const T >{ ref };
     437}
     438
     439template< typename OutType, typename Range, typename Functor >
     440OutType map_range( const Range& range, Functor&& functor ) {
     441        OutType out;
     442
     443        std::transform(
     444                begin( range ),
     445                end( range ),
     446                std::back_inserter( out ),
     447                std::forward< Functor >( functor )
     448        );
     449
     450        return out;
     451}
     452
     453// -----------------------------------------------------------------------------
     454// Helper struct and function to support:
     455// for ( auto val : group_iterate( container1, container2, ... ) ) { ... }
     456// This iteraters through multiple containers of the same size.
     457
     458template<typename... Args>
     459class group_iterate_t {
     460        using Iterables = std::tuple<Args...>;
     461        Iterables iterables;
     462
     463        // Getting the iterator and value types this way preserves const.
     464        template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());
     465        template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());
     466        template<typename> struct base_iterator;
     467
     468        // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1`
     469        // into a pack. These are the indexes into the tuples, so unpacking can
     470        // go over each element of the tuple.
     471        // The std::integer_sequence is just used to build that sequence.
     472        // A library reference will probably explain it better than I can.
     473        template<std::size_t... Indices>
     474        struct base_iterator<std::integer_sequence<std::size_t, Indices...>> {
     475                using value_type = std::tuple< Data<Indices>... >;
     476                std::tuple<Iter<Indices>...> iterators;
     477
     478                base_iterator( Iter<Indices>... is ) : iterators( is... ) {}
     479                base_iterator operator++() {
     480                        return base_iterator( ++std::get<Indices>( iterators )... );
     481                }
     482                bool operator!=( const base_iterator& other ) const {
     483                        return iterators != other.iterators;
     484                }
     485                value_type operator*() const {
     486                        return std::tie( *std::get<Indices>( iterators )... );
     487                }
     488
     489                static base_iterator make_begin( Iterables & data ) {
     490                        return base_iterator( std::get<Indices>( data ).begin()... );
     491                }
     492                static base_iterator make_end( Iterables & data ) {
     493                        return base_iterator( std::get<Indices>( data ).end()... );
     494                }
     495        };
     496
     497public:
     498        group_iterate_t( const Args &... args ) : iterables( args... ) {}
     499
     500        using iterator = base_iterator<decltype(
     501                std::make_integer_sequence<std::size_t, sizeof...(Args)>())>;
     502
     503        iterator begin() { return iterator::make_begin( iterables ); }
     504        iterator end() { return iterator::make_end( iterables ); }
     505};
     506
     507// Helpers for the bounds checks (the non-varatic part of group_iterate):
     508static inline void runGroupBoundsCheck(size_t size0, size_t size1) {
     509        assertf( size0 == size1,
     510                "group iteration requires containers of the same size: <%zd, %zd>.",
     511                size0, size1 );
     512}
     513
     514static inline void runGroupBoundsCheck(size_t size0, size_t size1, size_t size2) {
     515        assertf( size0 == size1 && size1 == size2,
     516                "group iteration requires containers of the same size: <%zd, %zd, %zd>.",
     517                size0, size1, size2 );
     518}
     519
     520/// Performs bounds check to ensure that all arguments are of the same length.
     521template< typename... Args >
     522group_iterate_t<Args...> group_iterate( Args &&... args ) {
     523        runGroupBoundsCheck( args.size()... );
     524        return group_iterate_t<Args...>( std::forward<Args>( args )... );
     525}
     526
     527/// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
     528template< typename... Args >
     529group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
     530        return group_iterate_t<Args...>( std::forward<Args>( args )... );
     531}
     532
     533// -----------------------------------------------------------------------------
     534// Helper struct and function to support
     535// for ( val : lazy_map( container1, f ) ) {}
     536// syntax to have a for each that iterates a container, mapping each element by applying f
     537template< typename T, typename Func >
     538struct lambda_iterate_t {
     539        const T & ref;
     540        std::function<Func> f;
     541
     542        struct iterator {
     543                typedef decltype(begin(ref)) Iter;
     544                Iter it;
     545                std::function<Func> f;
     546                iterator( Iter it, std::function<Func> f ) : it(it), f(f) {}
     547                iterator & operator++() {
     548                        ++it; return *this;
     549                }
     550                bool operator!=( const iterator &other ) const { return it != other.it; }
     551                auto operator*() const -> decltype(f(*it)) { return f(*it); }
     552        };
     553
     554        lambda_iterate_t( const T & ref, std::function<Func> f ) : ref(ref), f(f) {}
     555
     556        auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); }
     557        auto end() const   -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); }
     558};
     559
     560template< typename... Args >
     561lambda_iterate_t<Args...> lazy_map( const Args &... args ) {
     562        return lambda_iterate_t<Args...>( args...);
     563}
    232564
    233565// -----------------------------------------------------------------------------
     
    251583} // ilog2
    252584
     585// -----------------------------------------------------------------------------
     586/// evaluates expr as a long long int. If second is false, expr could not be evaluated
     587std::pair<long long int, bool> eval(const Expression * expr);
     588
     589namespace ast {
     590        class Expr;
     591}
     592
     593std::pair<long long int, bool> eval(const ast::Expr * expr);
     594
     595// -----------------------------------------------------------------------------
     596/// Reorders the input range in-place so that the minimal-value elements according to the
     597/// comparator are in front;
     598/// returns the iterator after the last minimal-value element.
     599template<typename Iter, typename Compare>
     600Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
     601        if ( begin == end ) return end;
     602
     603        Iter min_pos = begin;
     604        for ( Iter i = begin + 1; i != end; ++i ) {
     605                if ( lt( *i, *min_pos ) ) {
     606                        // new minimum cost; swap into first position
     607                        min_pos = begin;
     608                        std::iter_swap( min_pos, i );
     609                } else if ( ! lt( *min_pos, *i ) ) {
     610                        // duplicate minimum cost; swap into next minimum position
     611                        ++min_pos;
     612                        std::iter_swap( min_pos, i );
     613                }
     614        }
     615        return ++min_pos;
     616}
     617
     618template<typename Iter, typename Compare>
     619inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {
     620        return sort_mins( begin, end, lt );
     621}
     622
     623/// sort_mins defaulted to use std::less
     624template<typename Iter>
     625inline Iter sort_mins( Iter begin, Iter end ) {
     626        return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
     627}
     628
    253629// Local Variables: //
    254630// tab-width: 4 //
  • src/CompilationState.cc

    r24d6572 r34b4268  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon Ju1 30 10:47:01 2018
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 10 19:12:50 2023
    13 // Update Count     : 6
     11// Last Modified By : Henry Xue
     12// Last Modified On : Tue Jul 20 04:27:35 2021
     13// Update Count     : 5
    1414//
    1515
     
    2727        expraltp = false,
    2828        genericsp = false,
    29         invariant = false,
    3029        libcfap = false,
    3130        nopreludep = false,
     
    3433        useNewAST = true,
    3534        nomainp = false,
     35        parsep = false,
    3636        resolvep = false,
    3737        resolvprotop = false,
  • src/CompilationState.h

    r24d6572 r34b4268  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon Ju1 30 10:47:01 2018
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 10 19:12:53 2023
    13 // Update Count     : 6
     11// Last Modified By : Henry Xue
     12// Last Modified On : Tue Jul 20 04:27:35 2021
     13// Update Count     : 5
    1414//
    1515
     
    2626        expraltp,
    2727        genericsp,
    28         invariant,
    2928        libcfap,
    3029        nopreludep,
     
    3332        useNewAST,
    3433        nomainp,
     34        parsep,
    3535        resolvep,
    3636        resolvprotop,
  • src/Concurrency/KeywordsNew.cpp

    r24d6572 r34b4268  
    779779
    780780const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) {
    781         switch ( stmt->kind ) {
     781        switch ( stmt->type ) {
    782782        case ast::SuspendStmt::None:
    783783                // Use the context to determain the implicit target.
  • src/Concurrency/WaitforNew.cpp

    r24d6572 r34b4268  
    305305
    306306        const ast::VariableExpr * variableExpr =
    307                 clause->target.as<ast::VariableExpr>();
     307                clause->target_func.as<ast::VariableExpr>();
    308308        ast::Expr * castExpr = new ast::CastExpr(
    309309                location,
    310310                new ast::CastExpr(
    311311                        location,
    312                         clause->target,
     312                        clause->target_func,
    313313                        ast::deepCopy( variableExpr->result.get() ),
    314314                        ast::GeneratedCast ),
     
    325325
    326326        ResolveContext context{ symtab, transUnit().global };
    327         out->push_back( maybeCond( location, clause->when_cond.get(), {
     327        out->push_back( maybeCond( location, clause->cond.get(), {
    328328                makeAccStmt( location, acceptables, index, "is_dtor",
    329                         detectIsDtor( location, clause->target ), context ),
     329                        detectIsDtor( location, clause->target_func ), context ),
    330330                makeAccStmt( location, acceptables, index, "func",
    331331                        funcExpr, context ),
  • src/Concurrency/module.mk

    r24d6572 r34b4268  
    1616
    1717SRC += \
    18         Concurrency/Actors.cpp \
    19         Concurrency/Actors.hpp \
    2018        Concurrency/KeywordsNew.cpp \
    2119        Concurrency/Keywords.cc \
     
    2321        Concurrency/WaitforNew.cpp \
    2422        Concurrency/Waitfor.cc \
    25         Concurrency/Waitfor.h \
    26         Concurrency/Waituntil.cpp \
    27         Concurrency/Waituntil.hpp
     23        Concurrency/Waitfor.h
  • src/ControlStruct/ExceptDeclNew.cpp

    r24d6572 r34b4268  
    1616#include "ExceptDecl.h"
    1717
    18 #include <sstream>
    19 
    20 #include "AST/Copy.hpp"
    2118#include "AST/Decl.hpp"
    2219#include "AST/Pass.hpp"
  • src/ControlStruct/ExceptTranslateNew.cpp

    r24d6572 r34b4268  
    314314                nullptr,
    315315                ast::Storage::Classes{},
    316                 ast::Linkage::Cforall,
    317                 {},
    318                 { ast::Function::Inline }
     316                ast::Linkage::Cforall
    319317        );
    320318}
  • src/ControlStruct/MLEMutator.cc

    r24d6572 r34b4268  
    2525#include <memory>                          // for allocator_traits<>::value_...
    2626
    27 #include "Common/ToString.hpp"             // for toString
     27#include "Common/utility.h"                // for toString, operator+
    2828#include "ControlStruct/LabelGenerator.h"  // for LabelGenerator
    2929#include "MLEMutator.h"
  • src/GenPoly/Box.cc

    r24d6572 r34b4268  
    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 : Mon Dec 19 16:36:00 2022
    13 // Update Count     : 348
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Dec 13 23:40:34 2019
     13// Update Count     : 347
    1414//
    15 
    16 #include "Box.h"
    1715
    1816#include <algorithm>                     // for mismatch
     
    2624#include <utility>                       // for pair
    2725
     26#include "Box.h"
     27
    2828#include "CodeGen/OperatorTable.h"
    2929#include "Common/PassVisitor.h"          // for PassVisitor
     
    3131#include "Common/SemanticError.h"        // for SemanticError
    3232#include "Common/UniqueName.h"           // for UniqueName
    33 #include "Common/ToString.hpp"           // for toCString
     33#include "Common/utility.h"              // for toString
    3434#include "FindFunction.h"                // for findFunction, findAndReplace...
    3535#include "GenPoly/ErasableScopedMap.h"   // for ErasableScopedMap<>::const_i...
     
    3737#include "InitTweak/InitTweak.h"         // for getFunctionName, isAssignment
    3838#include "Lvalue.h"                      // for generalizedLvalue
    39 #include "ResolvExpr/Unify.h"            // for typesCompatible
     39#include "ResolvExpr/typeops.h"          // for typesCompatible
    4040#include "ScopedSet.h"                   // for ScopedSet, ScopedSet<>::iter...
    4141#include "ScrubTyVars.h"                 // for ScrubTyVars
     
    7272                };
    7373
    74                 /// Updates the call sites of polymorphic functions.
    7574                /// Replaces polymorphic return types with out-parameters,
    7675                /// replaces calls to polymorphic functions with adapter calls,
    7776                /// and adds appropriate type variables to the function call.
    78                 class CallAdapter final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<CallAdapter>, public WithShortCircuiting {
     77                class Pass1 final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
    7978                  public:
    80                         CallAdapter();
    81 
    82                         void premutate( Declaration * declaration );
     79                        Pass1();
     80
    8381                        void premutate( FunctionDecl * functionDecl );
    8482                        void premutate( TypeDecl * typeDecl );
     
    140138                };
    141139
    142                 /// Updates declarations (and types) that require adapters.
    143140                /// * Moves polymorphic returns in function types to pointer-type parameters
    144141                /// * adds type size and assertion parameters to parameter lists
    145                 struct DeclAdapter final : public BoxPass, public WithGuards {
     142                struct Pass2 final : public BoxPass, public WithGuards {
    146143                        void handleAggDecl();
    147144
     
    213210                };
    214211
    215                 /// Erases unneeded/unwanted polymorphic information.
    216212                /// Replaces initialization of polymorphic values with alloca,
    217213                /// declaration of dtype/ftype with appropriate void expression,
    218214                /// sizeof expressions of polymorphic types with the proper variable,
    219215                /// and strips fields from generic struct declarations.
    220                 struct Eraser final {
     216                struct Pass3 final : public BoxPass, public WithGuards {
     217                        template< typename DeclClass >
     218                        void handleDecl( DeclClass * decl, Type * type );
     219
    221220                        void premutate( ObjectDecl * objectDecl );
    222221                        void premutate( FunctionDecl * functionDecl );
     
    224223                        void premutate( StructDecl * structDecl );
    225224                        void premutate( UnionDecl * unionDecl );
     225                        void premutate( TypeDecl * typeDecl );
     226                        void premutate( PointerType * pointerType );
     227                        void premutate( FunctionType * funcType );
    226228                };
    227229        } // anonymous namespace
     
    229231        void box( std::list< Declaration *>& translationUnit ) {
    230232                PassVisitor<LayoutFunctionBuilder> layoutBuilder;
    231                 PassVisitor<CallAdapter> callAdapter;
    232                 PassVisitor<DeclAdapter> declAdapter;
     233                PassVisitor<Pass1> pass1;
     234                PassVisitor<Pass2> pass2;
    233235                PassVisitor<PolyGenericCalculator> polyCalculator;
    234                 PassVisitor<Eraser> eraser;
     236                PassVisitor<Pass3> pass3;
    235237
    236238                acceptAll( translationUnit, layoutBuilder );
    237                 mutateAll( translationUnit, callAdapter );
    238                 mutateAll( translationUnit, declAdapter );
     239                mutateAll( translationUnit, pass1 );
     240                mutateAll( translationUnit, pass2 );
    239241                mutateAll( translationUnit, polyCalculator );
    240                 mutateAll( translationUnit, eraser );
     242                mutateAll( translationUnit, pass3 );
    241243        }
    242244
    243 ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////
     245        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
    244246
    245247        /// Get a list of type declarations that will affect a layout function
     
    421423        }
    422424
    423 ////////////////////////////////////////////// CallAdapter //////////////////////////////////////
     425        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
    424426
    425427        namespace {
    426428                std::string makePolyMonoSuffix( FunctionType const * function, const TyVarMap &tyVars ) {
     429                        std::stringstream name;
     430
    427431                        // NOTE: this function previously used isPolyObj, which failed to produce
    428432                        // the correct thing in some situations. It's not clear to me why this wasn't working.
     
    431435                        // to take those polymorphic types as pointers. Therefore, there can be two different functions
    432436                        // with the same mangled name, so we need to further mangle the names.
    433                         std::stringstream name;
    434437                        for ( DeclarationWithType const * const ret : function->returnVals ) {
    435                                 name << ( isPolyType( ret->get_type(), tyVars ) ? 'P' : 'M' );
    436                         }
    437                         name << '_';
     438                                if ( isPolyType( ret->get_type(), tyVars ) ) {
     439                                        name << "P";
     440                                } else {
     441                                        name << "M";
     442                                }
     443                        }
     444                        name << "_";
    438445                        for ( DeclarationWithType const * const arg : function->parameters ) {
    439                                 name << ( isPolyType( arg->get_type(), tyVars ) ? 'P' : 'M' );
    440                         }
     446                                if ( isPolyType( arg->get_type(), tyVars ) ) {
     447                                        name << "P";
     448                                } else {
     449                                        name << "M";
     450                                }
     451                        } // for
    441452                        return name.str();
    442453                }
     
    454465                Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone = true );
    455466
    456                 CallAdapter::CallAdapter() : tempNamer( "_temp" ) {}
    457 
    458                 void CallAdapter::premutate( Declaration * ) {
    459                         // Prevent type declaration information from leaking out.
    460                         GuardScope( scopeTyVars );
    461                 }
    462 
    463                 void CallAdapter::premutate( FunctionDecl *functionDecl ) {
     467                Pass1::Pass1() : tempNamer( "_temp" ) {}
     468
     469                void Pass1::premutate( FunctionDecl *functionDecl ) {
    464470                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    465471                                // std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
     
    494500                                for ( FunctionType const * const funType : functions ) {
    495501                                        std::string mangleName = mangleAdapterName( funType, scopeTyVars );
    496                                         if ( !adapters.contains( mangleName ) ) {
     502                                        if ( adapters.find( mangleName ) == adapters.end() ) {
    497503                                                std::string adapterName = makeAdapterName( mangleName );
    498504                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) );
     
    503509                }
    504510
    505                 void CallAdapter::premutate( TypeDecl *typeDecl ) {
     511                void Pass1::premutate( TypeDecl *typeDecl ) {
    506512                        addToTyVarMap( typeDecl, scopeTyVars );
    507513                }
    508514
    509                 void CallAdapter::premutate( CommaExpr *commaExpr ) {
     515                void Pass1::premutate( CommaExpr *commaExpr ) {
    510516                        // Attempting to find application expressions that were mutated by the copy constructor passes
    511517                        // to use an explicit return variable, so that the variable can be reused as a parameter to the
     
    525531                }
    526532
    527                 std::list< Expression *>::iterator CallAdapter::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
     533                std::list< Expression *>::iterator Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
    528534                        Type *polyType = isPolyType( parmType, exprTyVars );
    529535                        if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     
    552558                }
    553559
    554                 std::list< Expression *>::iterator CallAdapter::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
     560                std::list< Expression *>::iterator Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
    555561                        assert( env );
    556562                        std::list< Expression *>::iterator arg = appExpr->args.begin();
     
    562568                        // even when converted to strings, sort in the original order.
    563569                        // (At least, that is the best explination I have.)
    564                         for ( std::pair<const std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
     570                        for ( std::pair<std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
    565571                                if ( !tyParam.second.isComplete ) continue;
    566572                                Type *concrete = env->lookup( tyParam.first );
     
    605611                }
    606612
    607                 ObjectDecl *CallAdapter::makeTemporary( Type *type ) {
     613                ObjectDecl *Pass1::makeTemporary( Type *type ) {
    608614                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
    609615                        stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
     
    611617                }
    612618
    613                 Expression *CallAdapter::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
     619                Expression *Pass1::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
    614620                        // Create temporary to hold return value of polymorphic function and produce that temporary as a result
    615621                        // using a comma expression.
     
    674680                }
    675681
    676                 Expression *CallAdapter::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
     682                Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
    677683                        Type *concrete = replaceWithConcrete( dynType, env );
    678684                        // add out-parameter for return value
     
    680686                }
    681687
    682                 Expression *CallAdapter::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
     688                Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
    683689                        Expression *ret = appExpr;
    684690                        if ( isDynRet( function, scopeTyVars ) ) {
     
    729735                }
    730736
    731                 void CallAdapter::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
     737                void Pass1::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
    732738                        assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
    733739                        addCast( arg, param, exprTyVars );
     
    764770                }
    765771
    766                 void CallAdapter::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
     772                void Pass1::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
    767773                        for ( DeclarationWithType * param : function->parameters ) {
    768774                                assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
     
    772778                }
    773779
    774                 void CallAdapter::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
     780                void Pass1::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
    775781                        for ( TypeDecl * const tyVar : functionType->forall ) {
    776782                                for ( DeclarationWithType * const assert : tyVar->assertions ) {
     
    840846                }
    841847
    842                 FunctionDecl *CallAdapter::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
     848                FunctionDecl *Pass1::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
    843849                        FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
    844850                        adapterType = ScrubTyVars::scrub( adapterType, tyVars );
     
    900906                }
    901907
    902                 void CallAdapter::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
     908                void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
    903909                        // collect a list of function types passed as parameters or implicit parameters (assertions)
    904910                        std::list<FunctionType const *> functions;
     
    917923
    918924                        for ( FunctionType const * const funType : functions ) {
    919                                 std::string mangleName = SymTab::Mangler::mangle( funType );
     925                                FunctionType *originalFunction = funType->clone();
     926                                FunctionType *realFunction = funType->clone();
     927                                std::string mangleName = SymTab::Mangler::mangle( realFunction );
    920928
    921929                                // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
    922930                                // pre-substitution parameter function type.
    923931                                // The second part of the insert result is "is the value new".
    924                                 if ( !adaptersDone.insert( mangleName ).second ) continue;
    925 
    926                                 // Apply substitution to type variables to figure out what the adapter's type should look like.
    927                                 assert( env );
    928                                 FunctionType *realType = funType->clone();
    929                                 env->apply( realType );
    930                                 mangleName = SymTab::Mangler::mangle( realType );
    931                                 mangleName += makePolyMonoSuffix( funType, exprTyVars );
    932 
    933                                 typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
    934                                 AdapterIter adapter = adapters.find( mangleName );
    935                                 if ( adapter == adapters.end() ) {
    936                                         // Adapter has not been created yet in the current scope, so define it.
    937                                         FunctionDecl *newAdapter = makeAdapter( funType, realType, mangleName, exprTyVars );
    938                                         std::pair< AdapterIter, bool > answer = adapters.insert( mangleName, newAdapter );
    939                                         adapter = answer.first;
    940                                         stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
     932                                if ( adaptersDone.insert( mangleName ).second ) {
     933
     934                                        // apply substitution to type variables to figure out what the adapter's type should look like
     935                                        assert( env );
     936                                        env->apply( realFunction );
     937                                        mangleName = SymTab::Mangler::mangle( realFunction );
     938                                        mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
     939
     940                                        typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
     941                                        AdapterIter adapter = adapters.find( mangleName );
     942                                        if ( adapter == adapters.end() ) {
     943                                                // adapter has not been created yet in the current scope, so define it
     944                                                FunctionDecl *newAdapter = makeAdapter( funType, realFunction, mangleName, exprTyVars );
     945                                                std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
     946                                                adapter = answer.first;
     947                                                stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
     948                                        } // if
     949                                        assert( adapter != adapters.end() );
     950
     951                                        // add the appropriate adapter as a parameter
     952                                        appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
    941953                                } // if
    942                                 assert( adapter != adapters.end() );
    943 
    944                                 // Add the appropriate adapter as a parameter.
    945                                 appExpr->args.push_front( new VariableExpr( adapter->second ) );
    946954                        } // for
    947955                } // passAdapters
     
    966974                }
    967975
    968                 Expression *CallAdapter::handleIntrinsics( ApplicationExpr *appExpr ) {
     976                Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
    969977                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->function ) ) {
    970978                                if ( varExpr->var->linkage == LinkageSpec::Intrinsic ) {
     
    10891097                }
    10901098
    1091                 Expression *CallAdapter::postmutate( ApplicationExpr *appExpr ) {
     1099                Expression *Pass1::postmutate( ApplicationExpr *appExpr ) {
    10921100                        // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
    10931101                        // for ( auto tyVar : scopeTyVars ) {
     
    11611169                }
    11621170
    1163                 Expression * CallAdapter::postmutate( UntypedExpr *expr ) {
     1171                Expression * Pass1::postmutate( UntypedExpr *expr ) {
    11641172                        if ( isPolyDeref( expr, scopeTyVars, env ) ) {
    11651173                                Expression *ret = expr->args.front();
     
    11711179                }
    11721180
    1173                 void CallAdapter::premutate( AddressExpr * ) { visit_children = false; }
    1174 
    1175                 Expression * CallAdapter::postmutate( AddressExpr * addrExpr ) {
     1181                void Pass1::premutate( AddressExpr * ) { visit_children = false; }
     1182
     1183                Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
    11761184                        assert( addrExpr->arg->result && ! addrExpr->arg->result->isVoid() );
    11771185
     
    12041212                }
    12051213
    1206                 void CallAdapter::premutate( ReturnStmt *returnStmt ) {
     1214                void Pass1::premutate( ReturnStmt *returnStmt ) {
    12071215                        if ( retval && returnStmt->expr ) {
    12081216                                assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() );
     
    12121220                }
    12131221
    1214                 void CallAdapter::premutate( PointerType *pointerType ) {
     1222                void Pass1::premutate( PointerType *pointerType ) {
    12151223                        GuardScope( scopeTyVars );
    12161224                        makeTyVarMap( pointerType, scopeTyVars );
    12171225                }
    12181226
    1219                 void CallAdapter::premutate( FunctionType *functionType ) {
     1227                void Pass1::premutate( FunctionType *functionType ) {
    12201228                        GuardScope( scopeTyVars );
    12211229                        makeTyVarMap( functionType, scopeTyVars );
    12221230                }
    12231231
    1224                 void CallAdapter::beginScope() {
     1232                void Pass1::beginScope() {
    12251233                        adapters.beginScope();
    12261234                }
    12271235
    1228                 void CallAdapter::endScope() {
     1236                void Pass1::endScope() {
    12291237                        adapters.endScope();
    12301238                }
    12311239
    1232 ////////////////////////////////////////// DeclAdapter //////////////////////////////////////////
    1233 
    1234                 void DeclAdapter::addAdapters( FunctionType *functionType ) {
     1240////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
     1241
     1242                void Pass2::addAdapters( FunctionType *functionType ) {
    12351243                        std::list< FunctionType const *> functions;
    12361244                        for ( DeclarationWithType * const arg : functionType->parameters ) {
     
    12521260                }
    12531261
    1254                 DeclarationWithType * DeclAdapter::postmutate( FunctionDecl *functionDecl ) {
     1262                DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {
    12551263                        FunctionType * ftype = functionDecl->type;
    12561264                        if ( ! ftype->returnVals.empty() && functionDecl->statements ) {
     
    12771285                }
    12781286
    1279                 void DeclAdapter::premutate( StructDecl * ) {
     1287                void Pass2::premutate( StructDecl * ) {
    12801288                        // prevent tyVars from leaking into containing scope
    12811289                        GuardScope( scopeTyVars );
    12821290                }
    12831291
    1284                 void DeclAdapter::premutate( UnionDecl * ) {
     1292                void Pass2::premutate( UnionDecl * ) {
    12851293                        // prevent tyVars from leaking into containing scope
    12861294                        GuardScope( scopeTyVars );
    12871295                }
    12881296
    1289                 void DeclAdapter::premutate( TraitDecl * ) {
     1297                void Pass2::premutate( TraitDecl * ) {
    12901298                        // prevent tyVars from leaking into containing scope
    12911299                        GuardScope( scopeTyVars );
    12921300                }
    12931301
    1294                 void DeclAdapter::premutate( TypeDecl *typeDecl ) {
     1302                void Pass2::premutate( TypeDecl *typeDecl ) {
    12951303                        addToTyVarMap( typeDecl, scopeTyVars );
    12961304                }
    12971305
    1298                 void DeclAdapter::premutate( PointerType *pointerType ) {
     1306                void Pass2::premutate( PointerType *pointerType ) {
    12991307                        GuardScope( scopeTyVars );
    13001308                        makeTyVarMap( pointerType, scopeTyVars );
    13011309                }
    13021310
    1303                 void DeclAdapter::premutate( FunctionType *funcType ) {
     1311                void Pass2::premutate( FunctionType *funcType ) {
    13041312                        GuardScope( scopeTyVars );
    13051313                        makeTyVarMap( funcType, scopeTyVars );
     
    13851393                }
    13861394
    1387 ////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////
     1395////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
    13881396
    13891397                PolyGenericCalculator::PolyGenericCalculator()
     
    14661474                        // make sure that any type information passed into the function is accounted for
    14671475                        for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
    1468                                 // condition here duplicates that in DeclAdapter::mutate( FunctionType* )
     1476                                // condition here duplicates that in Pass2::mutate( FunctionType* )
    14691477                                Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
    14701478                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     
    14931501                                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
    14941502                                                // do not try to monomorphize generic parameters
    1495                                                 if ( scopeTyVars.contains( typeInst->get_name() ) && ! genericParams.count( typeInst->name ) ) {
     1503                                                if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {
    14961504                                                        // polymorphic aggregate members should be converted into monomorphic members.
    14971505                                                        // Using char[size_T] here respects the expected sizing rules of an aggregate type.
     
    17021710
    17031711                        if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) {
    1704                                 if ( scopeTyVars.contains( typeInst->get_name() ) ) {
     1712                                if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
    17051713                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
    17061714                                        return true;
     
    17101718                                // check if this type already has a layout generated for it
    17111719                                std::string typeName = mangleType( ty );
    1712                                 if ( knownLayouts.contains( typeName ) ) return true;
     1720                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
    17131721
    17141722                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    17471755                                // check if this type already has a layout generated for it
    17481756                                std::string typeName = mangleType( ty );
    1749                                 if ( knownLayouts.contains( typeName ) ) return true;
     1757                                if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
    17501758
    17511759                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    18381846                        } else {
    18391847                                std::string offsetName = offsetofName( mangleType( ty ) );
    1840                                 if ( knownOffsets.contains( offsetName ) ) {
     1848                                if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
    18411849                                        // use the already-generated offsets for this type
    18421850                                        ret = new NameExpr( offsetName );
     
    18761884                }
    18771885
    1878 ////////////////////////////////////////// Eraser ///////////////////////////////////////////////
    1879 
    1880                 void Eraser::premutate( ObjectDecl * objectDecl ) {
    1881                         ScrubTyVars::scrubAll( objectDecl );
    1882                 }
    1883 
    1884                 void Eraser::premutate( FunctionDecl * functionDecl ) {
    1885                         ScrubTyVars::scrubAll( functionDecl );
    1886                 }
    1887 
    1888                 void Eraser::premutate( TypedefDecl * typedefDecl ) {
    1889                         ScrubTyVars::scrubAll( typedefDecl );
     1886////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
     1887
     1888                template< typename DeclClass >
     1889                void Pass3::handleDecl( DeclClass * decl, Type * type ) {
     1890                        GuardScope( scopeTyVars );
     1891                        makeTyVarMap( type, scopeTyVars );
     1892                        ScrubTyVars::scrubAll( decl );
     1893                }
     1894
     1895                void Pass3::premutate( ObjectDecl * objectDecl ) {
     1896                        handleDecl( objectDecl, objectDecl->type );
     1897                }
     1898
     1899                void Pass3::premutate( FunctionDecl * functionDecl ) {
     1900                        handleDecl( functionDecl, functionDecl->type );
     1901                }
     1902
     1903                void Pass3::premutate( TypedefDecl * typedefDecl ) {
     1904                        handleDecl( typedefDecl, typedefDecl->base );
    18901905                }
    18911906
    18921907                /// Strips the members from a generic aggregate
    1893                 static void stripGenericMembers( AggregateDecl * decl ) {
     1908                void stripGenericMembers(AggregateDecl * decl) {
    18941909                        if ( ! decl->parameters.empty() ) decl->members.clear();
    18951910                }
    18961911
    1897                 void Eraser::premutate( StructDecl * structDecl ) {
     1912                void Pass3::premutate( StructDecl * structDecl ) {
    18981913                        stripGenericMembers( structDecl );
    18991914                }
    19001915
    1901                 void Eraser::premutate( UnionDecl * unionDecl ) {
     1916                void Pass3::premutate( UnionDecl * unionDecl ) {
    19021917                        stripGenericMembers( unionDecl );
     1918                }
     1919
     1920                void Pass3::premutate( TypeDecl * typeDecl ) {
     1921                        addToTyVarMap( typeDecl, scopeTyVars );
     1922                }
     1923
     1924                void Pass3::premutate( PointerType * pointerType ) {
     1925                        GuardScope( scopeTyVars );
     1926                        makeTyVarMap( pointerType, scopeTyVars );
     1927                }
     1928
     1929                void Pass3::premutate( FunctionType * functionType ) {
     1930                        GuardScope( scopeTyVars );
     1931                        makeTyVarMap( functionType, scopeTyVars );
    19031932                }
    19041933        } // anonymous namespace
     
    19101939// compile-command: "make install" //
    19111940// End: //
     1941
  • src/GenPoly/ErasableScopedMap.h

    r24d6572 r34b4268  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ErasableScopedMap.h --
     7// ScopedMap.h --
    88//
    99// Author           : Aaron B. Moss
     
    5151        typedef typename Scope::const_pointer const_pointer;
    5252
    53         // Both iterator types are complete bidirectional iterators, see below.
     53        // Both iterator types are complete bidirection iterators, defined below.
    5454        class iterator;
    5555        class const_iterator;
     
    118118        std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
    119119
    120         Value& operator[] ( const Key &key ) {
    121                 iterator slot = find( key );
    122                 if ( slot != end() ) return slot->second;
    123                 return insert( key, Value() ).first->second;
    124         }
    125 
    126120        /// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise
    127121        size_type erase( const Key &key ) {
     
    136130        }
    137131
    138         bool contains( const Key & key ) const {
    139                 return find( key ) != cend();
     132        Value& operator[] ( const Key &key ) {
     133                iterator slot = find( key );
     134                if ( slot != end() ) return slot->second;
     135                return insert( key, Value() ).first->second;
    140136        }
    141137};
  • src/GenPoly/FindFunction.cc

    r24d6572 r34b4268  
    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 : Fri Oct  7 17:05:20 2022
    13 // Update Count     : 7
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Fri Feb 05 12:22:20 2016
     13// Update Count     : 6
    1414//
    1515
     
    1818#include <utility>                      // for pair
    1919
    20 #include "AST/Pass.hpp"                 // for Pass
    21 #include "AST/Type.hpp"
    2220#include "Common/PassVisitor.h"         // for PassVisitor
    2321#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
     
    9189                handleForall( pointerType->get_forall() );
    9290        }
    93 
    94 namespace {
    95 
    96 struct FindFunctionCore :
    97                 public ast::WithGuards,
    98                 public ast::WithShortCircuiting,
    99                 public ast::WithVisitorRef<FindFunctionCore> {
    100         FindFunctionCore(
    101                 std::vector<ast::ptr<ast::FunctionType>> & functions,
    102                 const TypeVarMap & typeVars, FindFunctionPred predicate,
    103                 bool replaceMode );
    104 
    105         void previsit( ast::FunctionType const * type );
    106         ast::Type const * postvisit( ast::FunctionType const * type );
    107         void previsit( ast::PointerType const * type );
    108 private:
    109         void handleForall( const ast::FunctionType::ForallList & forall );
    110 
    111         std::vector<ast::ptr<ast::FunctionType>> &functions;
    112         TypeVarMap typeVars;
    113         FindFunctionPred predicate;
    114         bool replaceMode;
    115 };
    116 
    117 FindFunctionCore::FindFunctionCore(
    118                 std::vector<ast::ptr<ast::FunctionType>> & functions,
    119                 const TypeVarMap &typeVars, FindFunctionPred predicate,
    120                 bool replaceMode ) :
    121         functions( functions ), typeVars( typeVars ),
    122         predicate( predicate ), replaceMode( replaceMode ) {}
    123 
    124 void FindFunctionCore::handleForall( const ast::FunctionType::ForallList & forall ) {
    125         for ( const ast::ptr<ast::TypeInstType> & td : forall ) {
    126                 TypeVarMap::iterator var = typeVars.find( *td );
    127                 if ( var != typeVars.end() ) {
    128                         typeVars.erase( var->first );
    129                 } // if
    130         } // for
    131 }
    132 
    133 void FindFunctionCore::previsit( ast::FunctionType const * type ) {
    134         visit_children = false;
    135         GuardScope( typeVars );
    136         handleForall( type->forall );
    137         //ast::accept_all( type->returns, *visitor );
    138         // This might have to become ast::mutate_each with return.
    139         ast::accept_each( type->returns, *visitor );
    140 }
    141 
    142 ast::Type const * FindFunctionCore::postvisit( ast::FunctionType const * type ) {
    143         ast::Type const * ret = type;
    144         if ( predicate( type, typeVars ) ) {
    145                 functions.push_back( type );
    146                 if ( replaceMode ) {
    147                         // replace type parameters in function type with void*
    148                         ret = scrubTypeVars( ast::deepCopy( type ), typeVars );
    149                 } // if
    150         } // if
    151         return ret;
    152 }
    153 
    154 void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) {
    155         GuardScope( typeVars );
    156         //handleForall( type->forall );
    157 }
    158 
    159 } // namespace
    160 
    161 void findFunction( const ast::Type * type,
    162                 std::vector<ast::ptr<ast::FunctionType>> & functions,
    163                 const TypeVarMap & typeVars, FindFunctionPred predicate ) {
    164         ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false );
    165         type->accept( pass );
    166         //(void)type;
    167         //(void)functions;
    168         //(void)typeVars;
    169         //(void)predicate;
    170 }
    171 
    172 const ast::Type * findAndReplaceFunction( const ast::Type * type,
    173                 std::vector<ast::ptr<ast::FunctionType>> & functions,
    174                 const TypeVarMap & typeVars, FindFunctionPred predicate ) {
    175         ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true );
    176         return type->accept( pass );
    177         //(void)functions;
    178         //(void)typeVars;
    179         //(void)predicate;
    180         //return type;
    181 }
    182 
    18391} // namespace GenPoly
    18492
  • src/GenPoly/FindFunction.h

    r24d6572 r34b4268  
    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 : Fri Oct  7 10:30:00 2022
    13 // Update Count     : 3
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:23:36 2017
     13// Update Count     : 2
    1414//
    1515
     
    3030        /// like `findFunction`, but also replaces the function type with void ()(void)
    3131        void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
    32 
    33 typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & );
    34 
    35 /// Recursively walks `type`, placing all functions that match `predicate`
    36 /// under `typeVars` into `functions`.
    37 void findFunction( const ast::Type * type,
    38                 std::vector<ast::ptr<ast::FunctionType>> & functions,
    39                 const TypeVarMap & typeVars, FindFunctionPred predicate );
    40 /// Like findFunction, but also replaces the function type with `void ()(void)`.
    41 const ast::Type * findAndReplaceFunction( const ast::Type * type,
    42                 std::vector<ast::ptr<ast::FunctionType>> & functions,
    43                 const TypeVarMap & typeVars, FindFunctionPred predicate );
    44 
    4532} // namespace GenPoly
    4633
  • src/GenPoly/GenPoly.cc

    r24d6572 r34b4268  
    2424#include <vector>                       // for vector
    2525
    26 #include "AST/Expr.hpp"
    2726#include "AST/Type.hpp"
    28 #include "AST/TypeSubstitution.hpp"
    2927#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    3028#include "ResolvExpr/typeops.h"         // for flatten
     
    172170
    173171                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    174                         if ( tyVars.contains( typeInst->get_name() ) ) {
     172                        if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
    175173                                return type;
    176174                        }
     
    189187
    190188                if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    191                         if ( tyVars.contains( typeInst->typeString() ) ) return type;
     189                        return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;
    192190                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    193191                        return isPolyType( arrayType->base, env );
     
    205203
    206204        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    207                 if ( typeVars.contains( *inst ) ) return type;
     205                if ( typeVars.find( *inst ) != typeVars.end() ) return type;
    208206        } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
    209207                return isPolyType( array->base, subst );
     
    274272                return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
    275273        }
    276 
    277 const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) {
    278         if ( func->returns.empty() ) return nullptr;
    279 
    280         TypeVarMap forallTypes = { ast::TypeData() };
    281         makeTypeVarMap( func, forallTypes );
    282         return isDynType( func->returns.front(), forallTypes );
    283 }
    284274
    285275        bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
     
    327317                return 0;
    328318        }
    329 
    330 const ast::Type * isPolyPtr(
    331                 const ast::Type * type, const TypeVarMap & typeVars,
    332                 const ast::TypeSubstitution * typeSubs ) {
    333         type = replaceTypeInst( type, typeSubs );
    334 
    335         if ( auto * ptr = dynamic_cast<ast::PointerType const *>( type ) ) {
    336                 return isPolyType( ptr->base, typeVars, typeSubs );
    337         }
    338         return nullptr;
    339 }
    340319
    341320        Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
     
    412391
    413392                if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
    414                         if ( tyVars.contains( typeInstType->get_name() ) ) {
     393                        if ( tyVars.find( typeInstType->get_name() ) != tyVars.end() ) {
    415394                                return true;
    416395                        }
     
    511490                }
    512491
    513                 /// Flattens a list of types.
    514                 // There is another flattenList in Unify.
    515492                void flattenList( vector<ast::ptr<ast::Type>> const & src,
    516493                                vector<ast::ptr<ast::Type>> & out ) {
     
    815792        }
    816793
    817 void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {
    818         typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );
    819 }
    820 
    821794void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
    822         typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );
     795        typeVars.insert( *type, ast::TypeData( type->base ) );
    823796}
    824797
     
    845818}
    846819
    847 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) {
    848         for ( auto & typeDecl : decl->type_params ) {
    849                 addToTypeVarMap( typeDecl, typeVars );
    850         }
    851 }
    852 
    853820        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
    854821                for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
  • src/GenPoly/GenPoly.h

    r24d6572 r34b4268  
    111111        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
    112112        void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars );
    113         void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars );
    114113
    115114        /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
    116115        void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
    117116        void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars );
    118         void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars );
    119117
    120118        /// Prints type variable map
  • src/GenPoly/InstantiateGeneric.cc

    r24d6572 r34b4268  
    2828#include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
    2929#include "InitTweak/InitTweak.h"
    30 #include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
    31 #include "ResolvExpr/Unify.h"          // for typesCompatible
     30#include "ResolvExpr/typeops.h"
    3231#include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
    3332#include "ScrubTyVars.h"               // for ScrubTyVars
  • src/GenPoly/InstantiateGenericNew.cpp

    r24d6572 r34b4268  
    3232#include "GenPoly/GenPoly.h"           // for isPolyType, typesPolyCompatible
    3333#include "GenPoly/ScrubTyVars.h"       // for scrubAll
    34 #include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
    35 #include "ResolvExpr/Unify.h"          // for typesCompatible
     34#include "ResolvExpr/typeops.h"        // for typesCompatible
    3635
    3736namespace GenPoly {
     
    362361                        ResolvExpr::typesCompatible(
    363362                                memberExpr->result,
    364                                 memberExpr->member->get_type() ) ) {
     363                                memberExpr->member->get_type(), ast::SymbolTable() ) ) {
    365364                return memberExpr;
    366365        }
  • src/GenPoly/Lvalue.cc

    r24d6572 r34b4268  
    1717#include <string>                        // for string
    1818
    19 #include "Common/ToString.hpp"           // for toCString
    2019#include "Common/UniqueName.h"
    2120#include "Common/PassVisitor.h"
  • src/GenPoly/LvalueNew.cpp

    r24d6572 r34b4268  
    2525#include "AST/Pass.hpp"
    2626#include "Common/SemanticError.h"      // for SemanticWarning
    27 #include "Common/ToString.hpp"         // for toCString
    2827#include "Common/UniqueName.h"         // for UniqueName
    2928#include "GenPoly/GenPoly.h"           // for genFunctionType
     
    359358                                !ResolvExpr::typesCompatible(
    360359                                        srcType,
    361                                         strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base ) ) {
     360                                        strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base,
     361                                        ast::SymbolTable() ) ) {
    362362                        // Must keep cast if cast-to type is different from the actual type.
    363363                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
     
    376376                if ( !ResolvExpr::typesCompatibleIgnoreQualifiers(
    377377                                dstType->stripReferences(),
    378                                 srcType->stripReferences() ) ) {
     378                                srcType->stripReferences(),
     379                                ast::SymbolTable() ) ) {
    379380                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
    380381                }
     
    391392                                ResolvExpr::typesCompatible(
    392393                                        expr->result,
    393                                         expr->arg->result ) ) {
     394                                        expr->arg->result, ast::SymbolTable() ) ) {
    394395                        PRINT(
    395396                                std::cerr << "types are compatible, removing cast: " << expr << '\n';
     
    588589                ast::OpenVarSet openVars;
    589590                ResolvExpr::unify( ret->arg2->result, ret->arg3->result, newEnv,
    590                         needAssertions, haveAssertions, openVars, common );
     591                        needAssertions, haveAssertions, openVars,
     592                        ast::SymbolTable(), common );
    591593                ret->result = common ? common : ast::deepCopy( ret->arg2->result );
    592594                return ret;
  • src/GenPoly/ScopedSet.h

    r24d6572 r34b4268  
    2121
    2222namespace GenPoly {
    23 
    24 /// A set where the items are placed into nested scopes;
    25 /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
    26 template<typename Value>
    27 class ScopedSet {
    28         typedef std::set< Value > Scope;
    29         typedef std::vector< Scope > ScopeList;
    30 
    31         /// Scoped list of sets.
    32         ScopeList scopes;
    33 public:
    34         typedef typename Scope::key_type key_type;
    35         typedef typename Scope::value_type value_type;
    36         typedef typename ScopeList::size_type size_type;
    37         typedef typename ScopeList::difference_type difference_type;
    38         typedef typename Scope::reference reference;
    39         typedef typename Scope::const_reference const_reference;
    40         typedef typename Scope::pointer pointer;
    41         typedef typename Scope::const_pointer const_pointer;
    42 
    43         // Both iterator types are complete bidirectional iterators, see below.
    44         class iterator;
    45         class const_iterator;
    46 
    47         /// Starts a new scope
    48         void beginScope() {
    49                 Scope scope;
    50                 scopes.push_back(scope);
    51         }
    52 
    53         /// Ends a scope; invalidates any iterators pointing to elements of that scope
    54         void endScope() {
    55                 scopes.pop_back();
    56         }
    57 
    58         /// Default constructor initializes with one scope
    59         ScopedSet() { beginScope(); }
    60 
    61         iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    62         const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    63         const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    64         iterator end() { return iterator(scopes, scopes[0].end(), 0); }
    65         const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
    66         const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
    67 
    68         /// Gets the index of the current scope (counted from 1)
    69         size_type currentScope() const { return scopes.size(); }
    70 
    71         /// Finds the given key in the outermost scope it occurs; returns end() for none such
    72         iterator find( const Value &key ) {
    73                 for ( size_type i = scopes.size() - 1; ; --i ) {
    74                         typename Scope::iterator val = scopes[i].find( key );
    75                         if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    76                         if ( i == 0 ) break;
    77                 }
    78                 return end();
    79         }
    80         const_iterator find( const Value &key ) const {
    81                 return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
    82         }
    83 
    84         /// Finds the given key in the outermost scope inside the given scope where it occurs
    85         iterator findNext( const_iterator &it, const Value &key ) {
    86                 if ( it.i == 0 ) return end();
     23        /// A set where the items are placed into nested scopes;
     24        /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
     25        template<typename Value>
     26        class ScopedSet {
     27                typedef std::set< Value > Scope;
     28                typedef std::vector< Scope > ScopeList;
     29
     30                ScopeList scopes; ///< scoped list of sets
     31        public:
     32                typedef typename Scope::key_type key_type;
     33                typedef typename Scope::value_type value_type;
     34                typedef typename ScopeList::size_type size_type;
     35                typedef typename ScopeList::difference_type difference_type;
     36                typedef typename Scope::reference reference;
     37                typedef typename Scope::const_reference const_reference;
     38                typedef typename Scope::pointer pointer;
     39                typedef typename Scope::const_pointer const_pointer;
     40
     41                class iterator : public std::iterator< std::bidirectional_iterator_tag,
     42                                                       value_type > {
     43                friend class ScopedSet;
     44                friend class const_iterator;
     45                        typedef typename std::set< Value >::iterator wrapped_iterator;
     46                        typedef typename std::vector< std::set< Value > > scope_list;
     47                        typedef typename scope_list::size_type size_type;
     48
     49                        /// Checks if this iterator points to a valid item
     50                        bool is_valid() const {
     51                                return it != (*scopes)[i].end();
     52                        }
     53
     54                        /// Increments on invalid
     55                        iterator& next_valid() {
     56                                if ( ! is_valid() ) { ++(*this); }
     57                                return *this;
     58                        }
     59
     60                        /// Decrements on invalid
     61                        iterator& prev_valid() {
     62                                if ( ! is_valid() ) { --(*this); }
     63                                return *this;
     64                        }
     65
     66                        iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
     67                                : scopes(&_scopes), it(_it), i(_i) {}
     68                public:
     69                        iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     70                        iterator& operator= (const iterator &that) {
     71                                scopes = that.scopes; i = that.i; it = that.it;
     72                                return *this;
     73                        }
     74
     75                        reference operator* () { return *it; }
     76                        pointer operator-> () { return it.operator->(); }
     77
     78                        iterator& operator++ () {
     79                                if ( it == (*scopes)[i].end() ) {
     80                                        if ( i == 0 ) return *this;
     81                                        --i;
     82                                        it = (*scopes)[i].begin();
     83                                } else {
     84                                        ++it;
     85                                }
     86                                return next_valid();
     87                        }
     88                        iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     89
     90                        iterator& operator-- () {
     91                                // may fail if this is the begin iterator; allowed by STL spec
     92                                if ( it == (*scopes)[i].begin() ) {
     93                                        ++i;
     94                                        it = (*scopes)[i].end();
     95                                }
     96                                --it;
     97                                return prev_valid();
     98                        }
     99                        iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     100
     101                        bool operator== (const iterator &that) {
     102                                return scopes == that.scopes && i == that.i && it == that.it;
     103                        }
     104                        bool operator!= (const iterator &that) { return !( *this == that ); }
     105
     106                        size_type get_level() const { return i; }
     107
     108                private:
     109                        scope_list const *scopes;
     110                        wrapped_iterator it;
     111                        size_type i;
     112                };
     113
     114                class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
     115                                                             value_type > {
     116                friend class ScopedSet;
     117                        typedef typename std::set< Value >::iterator wrapped_iterator;
     118                        typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
     119                        typedef typename std::vector< std::set< Value > > scope_list;
     120                        typedef typename scope_list::size_type size_type;
     121
     122                        /// Checks if this iterator points to a valid item
     123                        bool is_valid() const {
     124                                return it != (*scopes)[i].end();
     125                        }
     126
     127                        /// Increments on invalid
     128                        const_iterator& next_valid() {
     129                                if ( ! is_valid() ) { ++(*this); }
     130                                return *this;
     131                        }
     132
     133                        /// Decrements on invalid
     134                        const_iterator& prev_valid() {
     135                                if ( ! is_valid() ) { --(*this); }
     136                                return *this;
     137                        }
     138
     139                        const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
     140                                : scopes(&_scopes), it(_it), i(_i) {}
     141                public:
     142                        const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     143                        const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     144                        const_iterator& operator= (const iterator &that) {
     145                                scopes = that.scopes; i = that.i; it = that.it;
     146                                return *this;
     147                        }
     148                        const_iterator& operator= (const const_iterator &that) {
     149                                scopes = that.scopes; i = that.i; it = that.it;
     150                                return *this;
     151                        }
     152
     153                        const_reference operator* () { return *it; }
     154                        const_pointer operator-> () { return it.operator->(); }
     155
     156                        const_iterator& operator++ () {
     157                                if ( it == (*scopes)[i].end() ) {
     158                                        if ( i == 0 ) return *this;
     159                                        --i;
     160                                        it = (*scopes)[i].begin();
     161                                } else {
     162                                        ++it;
     163                                }
     164                                return next_valid();
     165                        }
     166                        const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     167
     168                        const_iterator& operator-- () {
     169                                // may fail if this is the begin iterator; allowed by STL spec
     170                                if ( it == (*scopes)[i].begin() ) {
     171                                        ++i;
     172                                        it = (*scopes)[i].end();
     173                                }
     174                                --it;
     175                                return prev_valid();
     176                        }
     177                        const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     178
     179                        bool operator== (const const_iterator &that) {
     180                                return scopes == that.scopes && i == that.i && it == that.it;
     181                        }
     182                        bool operator!= (const const_iterator &that) { return !( *this == that ); }
     183
     184                        size_type get_level() const { return i; }
     185
     186                private:
     187                        scope_list const *scopes;
     188                        wrapped_const_iterator it;
     189                        size_type i;
     190                };
     191
     192                /// Starts a new scope
     193                void beginScope() {
     194                        Scope scope;
     195                        scopes.push_back(scope);
     196                }
     197
     198                /// Ends a scope; invalidates any iterators pointing to elements of that scope
     199                void endScope() {
     200                        scopes.pop_back();
     201                }
     202
     203                /// Default constructor initializes with one scope
     204                ScopedSet() { beginScope(); }
     205
     206                iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     207                const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     208                const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     209                iterator end() { return iterator(scopes, scopes[0].end(), 0); }
     210                const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
     211                const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
     212
     213                /// Gets the index of the current scope (counted from 1)
     214                size_type currentScope() const { return scopes.size(); }
     215
     216                /// Finds the given key in the outermost scope it occurs; returns end() for none such
     217                iterator find( const Value &key ) {
     218                        for ( size_type i = scopes.size() - 1; ; --i ) {
     219                                typename Scope::iterator val = scopes[i].find( key );
     220                                if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     221                                if ( i == 0 ) break;
     222                        }
     223                        return end();
     224                }
     225                const_iterator find( const Value &key ) const {
     226                        return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
     227                }
     228
     229                /// Finds the given key in the outermost scope inside the given scope where it occurs
     230                iterator findNext( const_iterator &it, const Value &key ) {
     231                        if ( it.i == 0 ) return end();
    87232                        for ( size_type i = it.i - 1; ; --i ) {
    88                         typename Scope::iterator val = scopes[i].find( key );
    89                         if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    90                         if ( i == 0 ) break;
    91                 }
    92                 return end();
    93         }
    94         const_iterator findNext( const_iterator &it, const Value &key ) const {
    95                 return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
    96         }
    97 
    98         /// Inserts the given value into the outermost scope
    99         std::pair< iterator, bool > insert( const value_type &value ) {
    100                 std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
    101                 return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
    102         }
    103 
    104         bool contains( const Value & key ) const {
    105                 return find( key ) != cend();
    106         }
    107 };
    108 
    109 template<typename Value>
    110 class ScopedSet<Value>::iterator :
    111                 public std::iterator< std::bidirectional_iterator_tag, value_type > {
    112         friend class ScopedSet;
    113         friend class const_iterator;
    114         typedef typename std::set< Value >::iterator wrapped_iterator;
    115         typedef typename std::vector< std::set< Value > > scope_list;
    116         typedef typename scope_list::size_type size_type;
    117 
    118         /// Checks if this iterator points to a valid item
    119         bool is_valid() const {
    120                 return it != (*scopes)[i].end();
    121         }
    122 
    123         /// Increments on invalid
    124         iterator& next_valid() {
    125                 if ( ! is_valid() ) { ++(*this); }
    126                 return *this;
    127         }
    128 
    129         /// Decrements on invalid
    130         iterator& prev_valid() {
    131                 if ( ! is_valid() ) { --(*this); }
    132                 return *this;
    133         }
    134 
    135         iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
    136                 : scopes(&_scopes), it(_it), i(_i) {}
    137 public:
    138         iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    139         iterator& operator= (const iterator &that) {
    140                 scopes = that.scopes; i = that.i; it = that.it;
    141                 return *this;
    142         }
    143 
    144         reference operator* () { return *it; }
    145         pointer operator-> () { return it.operator->(); }
    146 
    147         iterator& operator++ () {
    148                 if ( it == (*scopes)[i].end() ) {
    149                         if ( i == 0 ) return *this;
    150                         --i;
    151                         it = (*scopes)[i].begin();
    152                 } else {
    153                         ++it;
    154                 }
    155                 return next_valid();
    156         }
    157         iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    158 
    159         iterator& operator-- () {
    160                 // may fail if this is the begin iterator; allowed by STL spec
    161                 if ( it == (*scopes)[i].begin() ) {
    162                         ++i;
    163                         it = (*scopes)[i].end();
    164                 }
    165                 --it;
    166                 return prev_valid();
    167         }
    168         iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    169 
    170         bool operator== (const iterator &that) {
    171                 return scopes == that.scopes && i == that.i && it == that.it;
    172         }
    173         bool operator!= (const iterator &that) { return !( *this == that ); }
    174 
    175         size_type get_level() const { return i; }
    176 
    177 private:
    178         scope_list const *scopes;
    179         wrapped_iterator it;
    180         size_type i;
    181 };
    182 
    183 template<typename Value>
    184 class ScopedSet<Value>::const_iterator :
    185                 public std::iterator< std::bidirectional_iterator_tag, value_type > {
    186         friend class ScopedSet;
    187         typedef typename std::set< Value >::iterator wrapped_iterator;
    188         typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
    189         typedef typename std::vector< std::set< Value > > scope_list;
    190         typedef typename scope_list::size_type size_type;
    191 
    192         /// Checks if this iterator points to a valid item
    193         bool is_valid() const {
    194                 return it != (*scopes)[i].end();
    195         }
    196 
    197         /// Increments on invalid
    198         const_iterator& next_valid() {
    199                 if ( ! is_valid() ) { ++(*this); }
    200                 return *this;
    201         }
    202 
    203         /// Decrements on invalid
    204         const_iterator& prev_valid() {
    205                 if ( ! is_valid() ) { --(*this); }
    206                 return *this;
    207         }
    208 
    209         const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
    210                 : scopes(&_scopes), it(_it), i(_i) {}
    211 public:
    212         const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    213         const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    214         const_iterator& operator= (const iterator &that) {
    215                 scopes = that.scopes; i = that.i; it = that.it;
    216                 return *this;
    217         }
    218         const_iterator& operator= (const const_iterator &that) {
    219                 scopes = that.scopes; i = that.i; it = that.it;
    220                 return *this;
    221         }
    222 
    223         const_reference operator* () { return *it; }
    224         const_pointer operator-> () { return it.operator->(); }
    225 
    226         const_iterator& operator++ () {
    227                 if ( it == (*scopes)[i].end() ) {
    228                         if ( i == 0 ) return *this;
    229                         --i;
    230                         it = (*scopes)[i].begin();
    231                 } else {
    232                         ++it;
    233                 }
    234                 return next_valid();
    235         }
    236         const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    237 
    238         const_iterator& operator-- () {
    239                 // may fail if this is the begin iterator; allowed by STL spec
    240                 if ( it == (*scopes)[i].begin() ) {
    241                         ++i;
    242                         it = (*scopes)[i].end();
    243                 }
    244                 --it;
    245                 return prev_valid();
    246         }
    247         const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    248 
    249         bool operator== (const const_iterator &that) {
    250                 return scopes == that.scopes && i == that.i && it == that.it;
    251         }
    252         bool operator!= (const const_iterator &that) { return !( *this == that ); }
    253 
    254         size_type get_level() const { return i; }
    255 
    256 private:
    257         scope_list const *scopes;
    258         wrapped_const_iterator it;
    259         size_type i;
    260 };
    261 
     233                                typename Scope::iterator val = scopes[i].find( key );
     234                                if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     235                                if ( i == 0 ) break;
     236                        }
     237                        return end();
     238                }
     239                const_iterator findNext( const_iterator &it, const Value &key ) const {
     240                        return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
     241                }
     242
     243                /// Inserts the given value into the outermost scope
     244                std::pair< iterator, bool > insert( const value_type &value ) {
     245                        std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
     246                        return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
     247                }
     248
     249        };
    262250} // namespace GenPoly
    263251
  • src/GenPoly/ScrubTyVars.cc

    r24d6572 r34b4268  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Dec  7 17:01:00 2022
    13 // Update Count     : 6
     12// Last Modified On : Fri Oct  7 15:42:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    117117namespace {
    118118
     119enum class ScrubMode {
     120        FromMap,
     121        DynamicFromMap,
     122        All,
     123};
     124
    119125struct ScrubTypeVars :
    120126        public ast::WithGuards,
     
    178184
    179185ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
    180         ast::TypeDecl::Kind kind;
    181186        // This implies that mode == ScrubMode::All.
    182187        if ( !typeVars ) {
    183                 kind = type->kind;
    184         } else {
    185                 // Otherwise, only scrub the type var if it is in map.
    186                 auto typeVar = typeVars->find( *type );
    187                 if ( typeVar == typeVars->end() ) {
    188                         return type;
    189                 }
    190                 kind = typeVar->second.kind;
    191         }
    192 
    193         switch ( kind ) {
    194         case ast::TypeDecl::Dtype:
    195         case ast::TypeDecl::Ttype:
     188                if ( ast::TypeDecl::Ftype == type->kind ) {
     189                        return new ast::PointerType(
     190                                new ast::FunctionType( ast::FixedArgs ) );
     191                } else {
     192                        return new ast::PointerType(
     193                                new ast::VoidType( type->qualifiers ) );
     194                }
     195        }
     196
     197        auto typeVar = typeVars->find( *type );
     198        if ( typeVar == typeVars->end() ) {
     199                return type;
     200        }
     201
     202        switch ( typeVar->second.kind ) {
     203        case ::TypeDecl::Dtype:
     204        case ::TypeDecl::Ttype:
    196205                return new ast::PointerType(
    197206                        new ast::VoidType( type->qualifiers ) );
    198         case ast::TypeDecl::Ftype:
     207        case ::TypeDecl::Ftype:
    199208                return new ast::PointerType(
    200209                        new ast::FunctionType( ast::VariableArgs ) );
    201210        default:
    202                 assertf( false, "Unhandled type variable kind: %d", kind );
     211                assertf( false,
     212                        "Unhandled type variable kind: %d", typeVar->second.kind );
    203213                throw; // Just in case the assert is removed, stop here.
    204214        }
     
    243253}
    244254
    245 } // namespace
    246 
    247255const ast::Node * scrubTypeVarsBase(
    248                 const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) {
     256                const ast::Node * target,
     257                ScrubMode mode, const TypeVarMap * typeVars ) {
    249258        if ( ScrubMode::All == mode ) {
    250259                assert( nullptr == typeVars );
     
    253262        }
    254263        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
    255         return node->accept( visitor );
     264        return target->accept( visitor );
     265}
     266
     267} // namespace
     268
     269template<>
     270ast::Node const * scrubTypeVars<ast::Node>(
     271        const ast::Node * target, const TypeVarMap & typeVars ) {
     272        return scrubTypeVarsBase( target, ScrubMode::FromMap, &typeVars );
     273}
     274
     275template<>
     276ast::Node const * scrubTypeVarsDynamic<ast::Node>(
     277        ast::Node const * target, const TypeVarMap & typeVars ) {
     278        return scrubTypeVarsBase( target, ScrubMode::DynamicFromMap, &typeVars );
     279}
     280
     281template<>
     282ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
     283        return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
    256284}
    257285
  • src/GenPoly/ScrubTyVars.h

    r24d6572 r34b4268  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Dec  7 16:57:00 2022
    13 // Update Count     : 5
     12// Last Modified On : Fri Oct  7 15:51:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    109109        }
    110110
    111 // ScrubMode and scrubTypeVarsBase are internal.
    112 enum class ScrubMode { FromMap, DynamicFromMap, All };
    113 
    114 const ast::Node * scrubTypeVarsBase(
    115         const ast::Node * target, const TypeVarMap * typeVars, ScrubMode mode );
    116 
    117 
    118111/// For all polymorphic types with type variables in `typeVars`,
    119112/// replaces generic types, dtypes, and ftypes with the appropriate void type,
     
    123116                node_t const * target, const TypeVarMap & typeVars ) {
    124117        return strict_dynamic_cast<node_t const *>(
    125                         scrubTypeVarsBase( target, &typeVars, ScrubMode::FromMap ) );
     118                        scrubTypeVars<ast::Node>( target, typeVars ) );
    126119}
    127120
     
    130123/// and sizeof/alignof expressions with the proper variable.
    131124template<typename node_t>
    132 node_t const * scrubTypeVarsDynamic(
     125ast::Node const * scrubTypeVarsDynamic(
    133126                node_t const * target, const TypeVarMap & typeVars ) {
    134127        return strict_dynamic_cast<node_t const *>(
    135                         scrubTypeVarsBase( target, &typeVars, ScrubMode::DynamicFromMap ) );
     128                        scrubTypeVarsDynamic<ast::Node>( target, typeVars ) );
    136129}
    137130
     
    141134node_t const * scrubAllTypeVars( node_t const * target ) {
    142135        return strict_dynamic_cast<node_t const *>(
    143                         scrubTypeVarsBase( target, nullptr, ScrubMode::All ) );
     136                        scrubAllTypeVars<ast::Node>( target ) );
    144137}
     138
     139// We specialize for Node as a base case.
     140template<>
     141ast::Node const * scrubTypeVars<ast::Node>(
     142                const ast::Node * target, const TypeVarMap & typeVars );
     143
     144template<>
     145ast::Node const * scrubTypeVarsDynamic<ast::Node>(
     146                ast::Node const * target, const TypeVarMap & typeVars );
     147
     148template<>
     149ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target );
    145150
    146151} // namespace GenPoly
  • src/GenPoly/SpecializeNew.cpp

    r24d6572 r34b4268  
    1616#include "Specialize.h"
    1717
    18 #include "AST/Copy.hpp"                  // for deepCopy
    1918#include "AST/Inspect.hpp"               // for isIntrinsicCallExpr
    2019#include "AST/Pass.hpp"                  // for Pass
  • src/InitTweak/FixInit.cc

    r24d6572 r34b4268  
    3232#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    3333#include "Common/SemanticError.h"      // for SemanticError
    34 #include "Common/ToString.hpp"         // for toCString
    3534#include "Common/UniqueName.h"         // for UniqueName
     35#include "Common/utility.h"            // for CodeLocation, ValueGuard, toSt...
    3636#include "FixGlobalInit.h"             // for fixGlobalInit
    3737#include "GenInit.h"                   // for genCtorDtor
     
    3939#include "InitTweak.h"                 // for getFunctionName, getCallArg
    4040#include "ResolvExpr/Resolver.h"       // for findVoidExpression
    41 #include "ResolvExpr/Unify.h"          // for typesCompatible
     41#include "ResolvExpr/typeops.h"        // for typesCompatible
    4242#include "SymTab/Autogen.h"            // for genImplicitCall
    4343#include "SymTab/Indexer.h"            // for Indexer
     
    12331233                }
    12341234
     1235                template< typename Visitor, typename... Params >
     1236                void error( Visitor & v, CodeLocation loc, const Params &... params ) {
     1237                        SemanticErrorException err( loc, toString( params... ) );
     1238                        v.errors.append( err );
     1239                }
     1240
    12351241                template< typename... Params >
    12361242                void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) {
    1237                         SemanticErrorException err( loc, toString( params... ) );
    1238                         errors.append( err );
     1243                        // toggle warnings vs. errors here.
     1244                        // warn( params... );
     1245                        error( *this, loc, params... );
    12391246                }
    12401247
  • src/InitTweak/FixInitNew.cpp

    r24d6572 r34b4268  
    1414#include <utility>                     // for pair
    1515
    16 #include "AST/DeclReplacer.hpp"
    17 #include "AST/Expr.hpp"
    1816#include "AST/Inspect.hpp"             // for getFunction, getPointerBase, g...
    19 #include "AST/Node.hpp"
    20 #include "AST/Pass.hpp"
    21 #include "AST/Print.hpp"
    22 #include "AST/SymbolTable.hpp"
    23 #include "AST/Type.hpp"
    2417#include "CodeGen/GenType.h"           // for genPrettyType
    2518#include "CodeGen/OperatorTable.h"
     19#include "Common/CodeLocationTools.hpp"
    2620#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    2721#include "Common/SemanticError.h"      // for SemanticError
    28 #include "Common/ToString.hpp"         // for toCString
    2922#include "Common/UniqueName.h"         // for UniqueName
     23#include "Common/utility.h"            // for CodeLocation, ValueGuard, toSt...
    3024#include "FixGlobalInit.h"             // for fixGlobalInit
    3125#include "GenInit.h"                   // for genCtorDtor
    3226#include "GenPoly/GenPoly.h"           // for getFunctionType
    3327#include "ResolvExpr/Resolver.h"       // for findVoidExpression
    34 #include "ResolvExpr/Unify.h"          // for typesCompatible
     28#include "ResolvExpr/typeops.h"        // for typesCompatible
    3529#include "SymTab/Autogen.h"            // for genImplicitCall
    36 #include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    3730#include "SymTab/Indexer.h"            // for Indexer
    3831#include "SymTab/Mangler.h"            // for Mangler
     
    5245#include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy
    5346
     47#include "AST/Expr.hpp"
     48#include "AST/Node.hpp"
     49#include "AST/Pass.hpp"
     50#include "AST/Print.hpp"
     51#include "AST/SymbolTable.hpp"
     52#include "AST/Type.hpp"
     53#include "AST/DeclReplacer.hpp"
     54
    5455extern bool ctordtorp; // print all debug
    5556extern bool ctorp; // print ctor debug
     
    6263namespace InitTweak {
    6364namespace {
    64 
    65         // Shallow copy the pointer list for return.
    66         std::vector<ast::ptr<ast::TypeDecl>> getGenericParams( const ast::Type * t ) {
    67                 if ( auto inst = dynamic_cast<const ast::StructInstType *>( t ) ) {
    68                         return inst->base->params;
    69                 }
    70                 if ( auto inst = dynamic_cast<const ast::UnionInstType *>( t ) ) {
    71                         return inst->base->params;
    72                 }
    73                 return {};
    74         }
    75 
    76         /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).
    77         ast::FunctionDecl * genDefaultFunc(
    78                         const CodeLocation loc,
    79                         const std::string fname,
    80                         const ast::Type * paramType,
    81                         bool maybePolymorphic = true) {
    82                 std::vector<ast::ptr<ast::TypeDecl>> typeParams;
    83                 if ( maybePolymorphic ) typeParams = getGenericParams( paramType );
    84                 auto dstParam = new ast::ObjectDecl( loc,
    85                         "_dst",
    86                         new ast::ReferenceType( paramType ),
    87                         nullptr,
    88                         {},
    89                         ast::Linkage::Cforall
    90                 );
    91                 return new ast::FunctionDecl( loc,
    92                         fname,
    93                         std::move(typeParams),
    94                         {dstParam},
    95                         {},
    96                         new ast::CompoundStmt(loc),
    97                         {},
    98                         ast::Linkage::Cforall
    99                 );
    100         }
    101 
    10265        struct SelfAssignChecker {
    10366                void previsit( const ast::ApplicationExpr * appExpr );
     
    144107        private:
    145108                /// hack to implement WithTypeSubstitution while conforming to mutation safety.
    146                 ast::TypeSubstitution * env         = nullptr;
    147                 bool                    envModified = false;
     109                ast::TypeSubstitution * env;
     110                bool                    envModified;
    148111        };
    149112
     
    158121                void previsit( const ast::FunctionDecl * ) { visit_children = false; }
    159122
    160         protected:
     123          protected:
    161124                ObjectSet curVars;
    162125        };
     
    239202
    240203                SemanticErrorException errors;
    241         private:
     204          private:
    242205                template< typename... Params >
    243206                void emit( CodeLocation, const Params &... params );
     
    325288                static UniqueName dtorNamer( "__cleanup_dtor" );
    326289                std::string name = dtorNamer.newName();
    327                 ast::FunctionDecl * dtorFunc = genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );
     290                ast::FunctionDecl * dtorFunc = SymTab::genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );
    328291                stmtsToAdd.push_back( new ast::DeclStmt(loc, dtorFunc ) );
    329292
     
    559522        {
    560523                static UniqueName tempNamer("_tmp_cp");
     524                assert( env );
    561525                const CodeLocation loc = impCpCtorExpr->location;
    562526                // CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
     
    570534
    571535                // xxx - this originally mutates arg->result in place. is it correct?
    572                 assert( env );
    573536                result = env->applyFree( result.get() ).node;
    574537                auto mutResult = result.get_and_mutate();
     
    11171080        void InsertDtors::previsit( const ast::BranchStmt * stmt ) {
    11181081                switch( stmt->kind ) {
    1119                 case ast::BranchStmt::Continue:
    1120                 case ast::BranchStmt::Break:
     1082                  case ast::BranchStmt::Continue:
     1083                  case ast::BranchStmt::Break:
    11211084                        // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should
    11221085                        // always be empty), but it serves as a small sanity check.
    1123                 case ast::BranchStmt::Goto:
     1086                  case ast::BranchStmt::Goto:
    11241087                        handleGoto( stmt );
    11251088                        break;
    1126                 default:
     1089                  default:
    11271090                        assert( false );
    11281091                } // switch
     
    13401303        }
    13411304
     1305        template< typename Visitor, typename... Params >
     1306        void error( Visitor & v, CodeLocation loc, const Params &... params ) {
     1307                SemanticErrorException err( loc, toString( params... ) );
     1308                v.errors.append( err );
     1309        }
     1310
    13421311        template< typename... Params >
    13431312        void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) {
    1344                 SemanticErrorException err( loc, toString( params... ) );
    1345                 errors.append( err );
     1313                // toggle warnings vs. errors here.
     1314                // warn( params... );
     1315                error( *this, loc, params... );
    13461316        }
    13471317
     
    13491319                // xxx - functions returning ast::ptr seems wrong...
    13501320                auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } );
    1351                 return res.release();
     1321                // Fix CodeLocation (at least until resolver is fixed).
     1322                auto fix = localFillCodeLocations( untypedExpr->location, res.release() );
     1323                return strict_dynamic_cast<const ast::Expr *>( fix );
    13521324        }
    13531325
  • src/InitTweak/GenInit.cc

    r24d6572 r34b4268  
    3131#include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
    3232#include "Common/SemanticError.h"      // for SemanticError
    33 #include "Common/ToString.hpp"         // for toCString
    3433#include "Common/UniqueName.h"         // for UniqueName
    3534#include "Common/utility.h"            // for ValueGuard, maybeClone
     
    3938#include "ResolvExpr/Resolver.h"
    4039#include "SymTab/Autogen.h"            // for genImplicitCall
    41 #include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    4240#include "SymTab/Mangler.h"            // for Mangler
    4341#include "SynTree/LinkageSpec.h"       // for isOverridable, C
  • src/InitTweak/InitTweak.cc

    r24d6572 r34b4268  
    3535#include "GenPoly/GenPoly.h"       // for getFunctionType
    3636#include "InitTweak.h"
    37 #include "ResolvExpr/Unify.h"      // for typesCompatibleIgnoreQualifiers
     37#include "ResolvExpr/typeops.h"    // for typesCompatibleIgnoreQualifiers
    3838#include "SymTab/Autogen.h"
    3939#include "SymTab/Indexer.h"        // for Indexer
     
    10661066        const ast::Type * t2 = ftype->params.back();
    10671067
    1068         return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 );
     1068        return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable() );
    10691069}
    10701070
  • src/MakeLibCfaNew.cpp

    r24d6572 r34b4268  
    1616#include "MakeLibCfa.h"
    1717
    18 #include "AST/Copy.hpp"
    1918#include "AST/Fwd.hpp"
    2019#include "AST/Pass.hpp"
  • src/Parser/DeclarationNode.cc

    r24d6572 r34b4268  
    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 Apr 20 11:46:00 2023
    13 // Update Count     : 1393
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Aug  8 17:07:00 2022
     13// Update Count     : 1185
    1414//
    15 
    16 #include "DeclarationNode.h"
    1715
    1816#include <cassert>                 // for assert, assertf, strict_dynamic_cast
     
    2321#include <string>                  // for string, operator+, allocator, char...
    2422
    25 #include "AST/Attribute.hpp"       // for Attribute
    26 #include "AST/Copy.hpp"            // for shallowCopy
    27 #include "AST/Decl.hpp"            // for Decl
    28 #include "AST/Expr.hpp"            // for Expr
    29 #include "AST/Print.hpp"           // for print
    30 #include "AST/Stmt.hpp"            // for AsmStmt, DirectiveStmt
    31 #include "AST/StorageClasses.hpp"  // for Storage::Class
    32 #include "AST/Type.hpp"            // for Type
    33 #include "Common/CodeLocation.h"   // for CodeLocation
    34 #include "Common/Iterate.hpp"      // for reverseIterate
    3523#include "Common/SemanticError.h"  // for SemanticError
    3624#include "Common/UniqueName.h"     // for UniqueName
    37 #include "Common/utility.h"        // for maybeClone
    38 #include "Parser/ExpressionNode.h" // for ExpressionNode
    39 #include "Parser/InitializerNode.h"// for InitializerNode
    40 #include "Parser/StatementNode.h"  // for StatementNode
     25#include "Common/utility.h"        // for maybeClone, maybeBuild, CodeLocation
     26#include "Parser/ParseNode.h"      // for DeclarationNode, ExpressionNode
     27#include "SynTree/LinkageSpec.h"   // for Spec, linkageName, Cforall
     28#include "SynTree/Attribute.h"     // for Attribute
     29#include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, InlineMemberDecl, Declaration
     30#include "SynTree/Expression.h"    // for Expression, ConstantExpr
     31#include "SynTree/Statement.h"     // for AsmStmt
     32#include "SynTree/Type.h"          // for Type, Type::StorageClasses, Type::...
    4133#include "TypeData.h"              // for TypeData, TypeData::Aggregate_t
    4234#include "TypedefTable.h"          // for TypedefTable
     
    4941
    5042// These must harmonize with the corresponding DeclarationNode enumerations.
    51 const char * DeclarationNode::basicTypeNames[] = {
    52         "void", "_Bool", "char", "int", "int128",
    53         "float", "double", "long double", "float80", "float128",
    54         "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames"
    55 };
    56 const char * DeclarationNode::complexTypeNames[] = {
    57         "_Complex", "NoComplexTypeNames", "_Imaginary"
    58 }; // Imaginary unsupported => parse, but make invisible and print error message
    59 const char * DeclarationNode::signednessNames[] = {
    60         "signed", "unsigned", "NoSignednessNames"
    61 };
    62 const char * DeclarationNode::lengthNames[] = {
    63         "short", "long", "long long", "NoLengthNames"
    64 };
    65 const char * DeclarationNode::builtinTypeNames[] = {
    66         "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames"
    67 };
     43const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "int128",
     44                                                                                                   "float", "double", "long double", "float80", "float128",
     45                                                                                                   "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" };
     46const char * DeclarationNode::complexTypeNames[] = { "_Complex", "NoComplexTypeNames", "_Imaginary" }; // Imaginary unsupported => parse, but make invisible and print error message
     47const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" };
     48const char * DeclarationNode::lengthNames[] = { "short", "long", "long long", "NoLengthNames" };
     49const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" };
    6850
    6951UniqueName DeclarationNode::anonymous( "__anonymous" );
    7052
    71 extern ast::Linkage::Spec linkage;                                              // defined in parser.yy
     53extern LinkageSpec::Spec linkage;                                               // defined in parser.yy
    7254
    7355DeclarationNode::DeclarationNode() :
     
    7557
    7658//      variable.name = nullptr;
    77         variable.tyClass = ast::TypeDecl::NUMBER_OF_KINDS;
     59        variable.tyClass = TypeDecl::NUMBER_OF_KINDS;
    7860        variable.assertions = nullptr;
    7961        variable.initializer = nullptr;
    8062
     63//      attr.name = nullptr;
     64        attr.expr = nullptr;
     65        attr.type = nullptr;
     66
    8167        assert.condition = nullptr;
    8268        assert.message = nullptr;
     
    8470
    8571DeclarationNode::~DeclarationNode() {
     72//      delete attr.name;
     73        delete attr.expr;
     74        delete attr.type;
     75
    8676//      delete variable.name;
    8777        delete variable.assertions;
    8878        delete variable.initializer;
    8979
    90 //      delete type;
     80//      delete type;
    9181        delete bitfieldWidth;
    9282
     
    113103        newnode->hasEllipsis = hasEllipsis;
    114104        newnode->linkage = linkage;
    115         newnode->asmName = maybeCopy( asmName );
    116         newnode->attributes = attributes;
     105        newnode->asmName = maybeClone( asmName );
     106        cloneAll( attributes, newnode->attributes );
    117107        newnode->initializer = maybeClone( initializer );
    118108        newnode->extension = extension;
     
    125115        newnode->variable.initializer = maybeClone( variable.initializer );
    126116
     117//      newnode->attr.name = attr.name ? new string( *attr.name ) : nullptr;
     118        newnode->attr.expr = maybeClone( attr.expr );
     119        newnode->attr.type = maybeClone( attr.type );
     120
    127121        newnode->assert.condition = maybeClone( assert.condition );
    128         newnode->assert.message = maybeCopy( assert.message );
     122        newnode->assert.message = maybeClone( assert.message );
    129123        return newnode;
    130124} // DeclarationNode::clone
     
    136130        } // if
    137131
    138         if ( linkage != ast::Linkage::Cforall ) {
    139                 os << ast::Linkage::name( linkage ) << " ";
    140         } // if
    141 
    142         ast::print( os, storageClasses );
    143         ast::print( os, funcSpecs );
     132        if ( linkage != LinkageSpec::Cforall ) {
     133                os << LinkageSpec::name( linkage ) << " ";
     134        } // if
     135
     136        storageClasses.print( os );
     137        funcSpecs.print( os );
    144138
    145139        if ( type ) {
     
    160154        } // if
    161155
    162         if ( ! attributes.empty() ) {
    163                 os << string( indent + 2, ' ' ) << "with attributes " << endl;
    164                 for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( attributes ) ) {
    165                         os << string( indent + 4, ' ' ) << attr->name.c_str() << endl;
    166                 } // for
    167         } // if
     156        for ( Attribute * attr: reverseIterate( attributes ) ) {
     157                os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str();
     158        } // for
    168159
    169160        os << endl;
     
    177168}
    178169
    179 DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) {
     170DeclarationNode * DeclarationNode::newStorageClass( Type::StorageClasses sc ) {
    180171        DeclarationNode * newnode = new DeclarationNode;
    181172        newnode->storageClasses = sc;
     
    183174} // DeclarationNode::newStorageClass
    184175
    185 DeclarationNode * DeclarationNode::newFuncSpecifier( ast::Function::Specs fs ) {
     176DeclarationNode * DeclarationNode::newFuncSpecifier( Type::FuncSpecifiers fs ) {
    186177        DeclarationNode * newnode = new DeclarationNode;
    187178        newnode->funcSpecs = fs;
     
    189180} // DeclarationNode::newFuncSpecifier
    190181
    191 DeclarationNode * DeclarationNode::newTypeQualifier( ast::CV::Qualifiers tq ) {
     182DeclarationNode * DeclarationNode::newTypeQualifier( Type::Qualifiers tq ) {
    192183        DeclarationNode * newnode = new DeclarationNode;
    193184        newnode->type = new TypeData();
     
    249240}
    250241
    251 DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
     242DeclarationNode * DeclarationNode::newAggregate( AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
    252243        DeclarationNode * newnode = new DeclarationNode;
    253244        newnode->type = new TypeData( TypeData::Aggregate );
    254245        newnode->type->aggregate.kind = kind;
    255         newnode->type->aggregate.anon = name == nullptr;
    256         newnode->type->aggregate.name = newnode->type->aggregate.anon ? new string( DeclarationNode::anonymous.newName() ) : name;
     246        newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
    257247        newnode->type->aggregate.actuals = actuals;
    258248        newnode->type->aggregate.fields = fields;
     
    260250        newnode->type->aggregate.tagged = false;
    261251        newnode->type->aggregate.parent = nullptr;
     252        newnode->type->aggregate.anon = name == nullptr;
    262253        return newnode;
    263254} // DeclarationNode::newAggregate
     
    266257        DeclarationNode * newnode = new DeclarationNode;
    267258        newnode->type = new TypeData( TypeData::Enum );
    268         newnode->type->enumeration.anon = name == nullptr;
    269         newnode->type->enumeration.name = newnode->type->enumeration.anon ? new string( DeclarationNode::anonymous.newName() ) : name;
     259        newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
    270260        newnode->type->enumeration.constants = constants;
    271261        newnode->type->enumeration.body = body;
     262        newnode->type->enumeration.anon = name == nullptr;
    272263        newnode->type->enumeration.typed = typed;
    273264        newnode->type->enumeration.hiding = hiding;
    274         if ( base && base->type )  {
     265        if ( base && base->type)  {
    275266                newnode->type->base = base->type;
    276267        } // if
     
    278269        return newnode;
    279270} // DeclarationNode::newEnum
     271
     272
    280273
    281274DeclarationNode * DeclarationNode::newName( const string * name ) {
     
    330323} // DeclarationNode::newFromTypeGen
    331324
    332 DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) {
     325DeclarationNode * DeclarationNode::newTypeParam( TypeDecl::Kind tc, const string * name ) {
    333326        DeclarationNode * newnode = newName( name );
    334327        newnode->type = nullptr;
     
    342335        newnode->type = new TypeData( TypeData::Aggregate );
    343336        newnode->type->aggregate.name = name;
    344         newnode->type->aggregate.kind = ast::AggregateDecl::Trait;
     337        newnode->type->aggregate.kind = AggregateDecl::Trait;
    345338        newnode->type->aggregate.params = params;
    346339        newnode->type->aggregate.fields = asserts;
     
    352345        newnode->type = new TypeData( TypeData::AggregateInst );
    353346        newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate );
    354         newnode->type->aggInst.aggregate->aggregate.kind = ast::AggregateDecl::Trait;
     347        newnode->type->aggInst.aggregate->aggregate.kind = AggregateDecl::Trait;
    355348        newnode->type->aggInst.aggregate->aggregate.name = name;
    356349        newnode->type->aggInst.params = params;
     
    387380        newnode->type->array.dimension = size;
    388381        newnode->type->array.isStatic = isStatic;
    389         if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ast::ConstantExpr *>() ) {
     382        if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ConstantExpr * >() ) {
    390383                newnode->type->array.isVarLen = false;
    391384        } else {
     
    457450        DeclarationNode * newnode = new DeclarationNode;
    458451        newnode->type = nullptr;
    459         std::vector<ast::ptr<ast::Expr>> exprs;
     452        std::list< Expression * > exprs;
    460453        buildList( expr, exprs );
    461         newnode->attributes.push_back(
    462                 new ast::Attribute( *name, std::move( exprs ) ) );
     454        newnode->attributes.push_back( new Attribute( *name, exprs ) );
    463455        delete name;
    464456        return newnode;
     
    477469}
    478470
    479 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, ast::Expr * message ) {
     471DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, Expression * message ) {
    480472        DeclarationNode * newnode = new DeclarationNode;
    481473        newnode->assert.condition = condition;
     
    484476}
    485477
    486 static void appendError( string & dst, const string & src ) {
     478
     479void appendError( string & dst, const string & src ) {
    487480        if ( src.empty() ) return;
    488481        if ( dst.empty() ) { dst = src; return; }
     
    491484
    492485void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) {
    493         const ast::CV::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
    494         const ast::CV::Qualifiers duplicates = qsrc & qdst;
    495 
    496         if ( duplicates.any() ) {
    497                 std::stringstream str;
    498                 str << "duplicate ";
    499                 ast::print( str, duplicates );
    500                 str << "qualifier(s)";
    501                 appendError( error, str.str() );
     486        const Type::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
     487
     488        if ( (qsrc & qdst).any() ) {                                            // duplicates ?
     489                for ( unsigned int i = 0; i < Type::NumTypeQualifier; i += 1 ) { // find duplicates
     490                        if ( qsrc[i] && qdst[i] ) {
     491                                appendError( error, string( "duplicate " ) + Type::QualifiersNames[i] );
     492                        } // if
     493                } // for
    502494        } // for
    503495} // DeclarationNode::checkQualifiers
    504496
    505497void DeclarationNode::checkSpecifiers( DeclarationNode * src ) {
    506         ast::Function::Specs fsDups = funcSpecs & src->funcSpecs;
    507         if ( fsDups.any() ) {
    508                 std::stringstream str;
    509                 str << "duplicate ";
    510                 ast::print( str, fsDups );
    511                 str << "function specifier(s)";
    512                 appendError( error, str.str() );
    513         } // if
    514 
    515         // Skip if everything is unset.
    516         if ( storageClasses.any() && src->storageClasses.any() ) {
    517                 ast::Storage::Classes dups = storageClasses & src->storageClasses;
    518                 // Check for duplicates.
    519                 if ( dups.any() ) {
    520                         std::stringstream str;
    521                         str << "duplicate ";
    522                         ast::print( str, dups );
    523                         str << "storage class(es)";
    524                         appendError( error, str.str() );
    525                 // Check for conflicts.
    526                 } else if ( !src->storageClasses.is_threadlocal_any() ) {
    527                         std::stringstream str;
    528                         str << "conflicting ";
    529                         ast::print( str, ast::Storage::Classes( 1 << storageClasses.ffs() ) );
    530                         str << "& ";
    531                         ast::print( str, ast::Storage::Classes( 1 << src->storageClasses.ffs() ) );
    532                         str << "storage classes";
    533                         appendError( error, str.str() );
    534                         // FIX to preserve invariant of one basic storage specifier
    535                         src->storageClasses.reset();
    536                 }
     498        if ( (funcSpecs & src->funcSpecs).any() ) {                     // duplicates ?
     499                for ( unsigned int i = 0; i < Type::NumFuncSpecifier; i += 1 ) { // find duplicates
     500                        if ( funcSpecs[i] && src->funcSpecs[i] ) {
     501                                appendError( error, string( "duplicate " ) + Type::FuncSpecifiersNames[i] );
     502                        } // if
     503                } // for
     504        } // if
     505
     506        if ( storageClasses.any() && src->storageClasses.any() ) { // any reason to check ?
     507                if ( (storageClasses & src->storageClasses ).any() ) { // duplicates ?
     508                        for ( unsigned int i = 0; i < Type::NumStorageClass; i += 1 ) { // find duplicates
     509                                if ( storageClasses[i] && src->storageClasses[i] ) {
     510                                        appendError( error, string( "duplicate " ) + Type::StorageClassesNames[i] );
     511                                } // if
     512                        } // for
     513                        // src is the new item being added and has a single bit
     514                } else if ( ! src->storageClasses.is_threadlocal_any() ) { // conflict ?
     515                        appendError( error, string( "conflicting " ) + Type::StorageClassesNames[storageClasses.ffs()] +
     516                                                 " & " + Type::StorageClassesNames[src->storageClasses.ffs()] );
     517                        src->storageClasses.reset();                            // FIX to preserve invariant of one basic storage specifier
     518                } // if
    537519        } // if
    538520
     
    544526        storageClasses |= q->storageClasses;
    545527
    546         std::vector<ast::ptr<ast::Attribute>> tmp;
    547         tmp.reserve( q->attributes.size() );
    548         for ( auto const & attr : q->attributes ) {
    549                 tmp.emplace_back( ast::shallowCopy( attr.get() ) );
    550         }
    551         spliceBegin( attributes, tmp );
    552 
     528        for ( Attribute * attr: reverseIterate( q->attributes ) ) {
     529                attributes.push_front( attr->clone() );
     530        } // for
    553531        return this;
    554532} // DeclarationNode::copySpecifiers
     
    598576
    599577        checkQualifiers( type, q->type );
    600         if ( (builtin == Zero || builtin == One) && q->type->qualifiers.any() && error.length() == 0 ) {
    601                 SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, builtinTypeNames[builtin] );
     578        if ( (builtin == Zero || builtin == One) && q->type->qualifiers.val != 0 && error.length() == 0 ) {
     579                SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, Type::QualifiersNames[ilog2( q->type->qualifiers.val )], builtinTypeNames[builtin] );
    602580        } // if
    603581        addQualifiersToType( q->type, type );
     
    620598        } else {
    621599                switch ( dst->kind ) {
    622                 case TypeData::Unknown:
     600                  case TypeData::Unknown:
    623601                        src->qualifiers |= dst->qualifiers;
    624602                        dst = src;
    625603                        src = nullptr;
    626604                        break;
    627                 case TypeData::Basic:
     605                  case TypeData::Basic:
    628606                        dst->qualifiers |= src->qualifiers;
    629607                        if ( src->kind != TypeData::Unknown ) {
     
    653631                        } // if
    654632                        break;
    655                 default:
     633                  default:
    656634                        switch ( src->kind ) {
    657                         case TypeData::Aggregate:
    658                         case TypeData::Enum:
     635                          case TypeData::Aggregate:
     636                          case TypeData::Enum:
    659637                                dst->base = new TypeData( TypeData::AggregateInst );
    660638                                dst->base->aggInst.aggregate = src;
     
    665643                                src = nullptr;
    666644                                break;
    667                         default:
     645                          default:
    668646                                if ( dst->forall ) {
    669647                                        dst->forall->appendList( src->forall );
     
    736714
    737715DeclarationNode * DeclarationNode::addAssertions( DeclarationNode * assertions ) {
    738         if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
    739                 if ( variable.assertions ) {
    740                         variable.assertions->appendList( assertions );
    741                 } else {
    742                         variable.assertions = assertions;
    743                 } // if
    744                 return this;
     716        if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {
     717                if ( variable.assertions ) {
     718                        variable.assertions->appendList( assertions );
     719                } else {
     720                        variable.assertions = assertions;
     721                } // if
     722                return this;
    745723        } // if
    746724
    747725        assert( type );
    748726        switch ( type->kind ) {
    749         case TypeData::Symbolic:
     727          case TypeData::Symbolic:
    750728                if ( type->symbolic.assertions ) {
    751729                        type->symbolic.assertions->appendList( assertions );
     
    754732                } // if
    755733                break;
    756         default:
     734          default:
    757735                assert( false );
    758736        } // switch
     
    818796DeclarationNode * DeclarationNode::copyAttribute( DeclarationNode * a ) {
    819797        if ( a ) {
    820                 spliceBegin( attributes, a->attributes );
     798                for ( Attribute *attr: reverseIterate( a->attributes ) ) {
     799                        attributes.push_front( attr );
     800                } // for
    821801                a->attributes.clear();
    822802        } // if
     
    851831                if ( type ) {
    852832                        switch ( type->kind ) {
    853                         case TypeData::Aggregate:
    854                         case TypeData::Enum:
     833                          case TypeData::Aggregate:
     834                          case TypeData::Enum:
    855835                                p->type->base = new TypeData( TypeData::AggregateInst );
    856836                                p->type->base->aggInst.aggregate = type;
     
    861841                                break;
    862842
    863                         default:
     843                          default:
    864844                                p->type->base = type;
    865845                        } // switch
     
    883863
    884864DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) {
    885         if ( ! a ) return this;
     865  if ( ! a ) return this;
    886866        assert( a->type->kind == TypeData::Array );
    887867        TypeData * lastArray = findLast( a->type );
    888868        if ( type ) {
    889869                switch ( type->kind ) {
    890                 case TypeData::Aggregate:
    891                 case TypeData::Enum:
     870                  case TypeData::Aggregate:
     871                  case TypeData::Enum:
    892872                        lastArray->base = new TypeData( TypeData::AggregateInst );
    893873                        lastArray->base->aggInst.aggregate = type;
     
    897877                        lastArray->base->qualifiers |= type->qualifiers;
    898878                        break;
    899                 default:
     879                  default:
    900880                        lastArray->base = type;
    901881                } // switch
     
    939919
    940920DeclarationNode * DeclarationNode::addTypeInitializer( DeclarationNode * init ) {
    941         assertf( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );
     921        assertf( variable.tyClass != TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );
    942922        variable.initializer = init;
    943923        return this;
     
    1003983}
    1004984
    1005 // If a typedef wraps an anonymous declaration, name the inner declaration
    1006 // so it has a consistent name across translation units.
    1007 static void nameTypedefedDecl(
    1008                 DeclarationNode * innerDecl,
    1009                 const DeclarationNode * outerDecl ) {
    1010         TypeData * outer = outerDecl->type;
    1011         assert( outer );
    1012         // First make sure this is a typedef:
    1013         if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) {
    1014                 return;
    1015         }
    1016         TypeData * inner = innerDecl->type;
    1017         assert( inner );
    1018         // Always clear any CVs associated with the aggregate:
    1019         inner->qualifiers.reset();
    1020         // Handle anonymous aggregates: typedef struct { int i; } foo
    1021         if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) {
    1022                 delete inner->aggregate.name;
    1023                 inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
    1024                 inner->aggregate.anon = false;
    1025                 assert( outer->base );
    1026                 delete outer->base->aggInst.aggregate->aggregate.name;
    1027                 outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
    1028                 outer->base->aggInst.aggregate->aggregate.anon = false;
    1029                 outer->base->aggInst.aggregate->qualifiers.reset();
    1030         // Handle anonymous enumeration: typedef enum { A, B, C } foo
    1031         } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) {
    1032                 delete inner->enumeration.name;
    1033                 inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
    1034                 inner->enumeration.anon = false;
    1035                 assert( outer->base );
    1036                 delete outer->base->aggInst.aggregate->enumeration.name;
    1037                 outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
    1038                 outer->base->aggInst.aggregate->enumeration.anon = false;
    1039                 // No qualifiers.reset() here.
    1040         }
    1041 }
    1042 
    1043 // This code handles a special issue with the attribute transparent_union.
    1044 //
    1045 //    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
    1046 //
    1047 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are
    1048 // aligned.  However, the attribute transparent_union must be moved from the typedef_name to
    1049 // alias union U.  Currently, this is the only know attribute that must be moved from typedef to
    1050 // alias.
    1051 static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) {
    1052         if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) {
    1053                 // Is the typedef alias a union aggregate?
    1054                 if ( nullptr == unionDecl ) return;
    1055 
    1056                 // If typedef is an alias for a union, then its alias type was hoisted above and remembered.
    1057                 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) {
    1058                         auto instType = ast::mutate( unionInstType );
    1059                         // Remove all transparent_union attributes from typedef and move to alias union.
    1060                         for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) {
    1061                                 assert( *attr );
    1062                                 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
    1063                                         unionDecl->attributes.emplace_back( attr->release() );
    1064                                         attr = instType->attributes.erase( attr );
    1065                                 } else {
    1066                                         attr++;
    1067                                 }
    1068                         }
    1069                         typedefDecl->base = instType;
    1070                 }
    1071         }
    1072 }
    1073 
    1074 // Get the non-anonymous name of the instance type of the declaration,
    1075 // if one exists.
    1076 static const std::string * getInstTypeOfName( ast::Decl * decl ) {
    1077         if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
    1078                 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) {
    1079                         if ( aggr->name.find("anonymous") == std::string::npos ) {
    1080                                 return &aggr->name;
    1081                         }
    1082                 }
    1083         }
    1084         return nullptr;
    1085 }
    1086 
    1087 void buildList( DeclarationNode * firstNode,
    1088                 std::vector<ast::ptr<ast::Decl>> & outputList ) {
     985void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) {
    1089986        SemanticErrorException errors;
    1090         std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
    1091 
    1092         for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
     987        std::back_insert_iterator< std::list< Declaration * > > out( outputList );
     988
     989        for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
    1093990                try {
    1094                         bool extracted_named = false;
    1095                         ast::UnionDecl * unionDecl = nullptr;
    1096 
     991                        bool extracted = false;
     992                        bool anon = false;
    1097993                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    1098                                 assert( cur->type );
    1099                                 nameTypedefedDecl( extr, cur );
    1100 
    1101                                 if ( ast::Decl * decl = extr->build() ) {
    1102                                         // Remember the declaration if it is a union aggregate ?
    1103                                         unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
    1104 
    1105                                         *out++ = decl;
     994                                // handle the case where a structure declaration is contained within an object or type declaration
     995                                Declaration * decl = extr->build();
     996                                if ( decl ) {
     997                                        // hoist the structure declaration
     998                                        decl->location = cur->location;
     999                                        * out++ = decl;
    11061000
    11071001                                        // need to remember the cases where a declaration contains an anonymous aggregate definition
     1002                                        extracted = true;
    11081003                                        assert( extr->type );
    11091004                                        if ( extr->type->kind == TypeData::Aggregate ) {
    1110                                                 // typedef struct { int A } B is the only case?
    1111                                                 extracted_named = !extr->type->aggregate.anon;
     1005                                                anon = extr->type->aggregate.anon;
    11121006                                        } else if ( extr->type->kind == TypeData::Enum ) {
    1113                                                 // typedef enum { A } B is the only case?
    1114                                                 extracted_named = !extr->type->enumeration.anon;
    1115                                         } else {
    1116                                                 extracted_named = true;
     1007                                                // xxx - is it useful to have an implicit anonymous enum member?
     1008                                                anon = extr->type->enumeration.anon;
    11171009                                        }
    11181010                                } // if
     
    11201012                        } // if
    11211013
    1122                         if ( ast::Decl * decl = cur->build() ) {
    1123                                 moveUnionAttribute( decl, unionDecl );
    1124 
    1125                                 if ( "" == decl->name && !cur->get_inLine() ) {
    1126                                         // Don't include anonymous declaration for named aggregates,
    1127                                         // but do include them for anonymous aggregates, e.g.:
    1128                                         // struct S {
    1129                                         //   struct T { int x; }; // no anonymous member
    1130                                         //   struct { int y; };   // anonymous member
    1131                                         //   struct T;            // anonymous member
    1132                                         // };
    1133                                         if ( extracted_named ) {
    1134                                                 continue;
    1135                                         }
    1136 
    1137                                         if ( auto name = getInstTypeOfName( decl ) ) {
    1138                                                 // Temporary: warn about anonymous member declarations of named types, since
    1139                                                 // this conflicts with the syntax for the forward declaration of an anonymous type.
    1140                                                 SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() );
    1141                                         }
     1014                        Declaration * decl = cur->build();
     1015                        if ( decl ) {
     1016                                // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.:
     1017                                // struct S {
     1018                                //   struct T { int x; }; // no anonymous member
     1019                                //   struct { int y; };   // anonymous member
     1020                                //   struct T;            // anonymous member
     1021                                // };
     1022                                if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) {
     1023                                        if ( decl->name == "" ) {
     1024                                                if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>( decl ) ) {
     1025                                                        if ( ReferenceToType * aggr = dynamic_cast<ReferenceToType *>( dwt->get_type() ) ) {
     1026                                                                if ( aggr->name.find("anonymous") == std::string::npos ) {
     1027                                                                        if ( ! cur->get_inLine() ) {
     1028                                                                                // temporary: warn about anonymous member declarations of named types, since
     1029                                                                                // this conflicts with the syntax for the forward declaration of an anonymous type
     1030                                                                                SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() );
     1031                                                                        } // if
     1032                                                                } // if
     1033                                                        } // if
     1034                                                } // if
     1035                                        } // if
     1036                                        decl->location = cur->location;
     1037                                        *out++ = decl;
    11421038                                } // if
    1143                                 *out++ = decl;
    11441039                        } // if
    1145                 } catch ( SemanticErrorException & e ) {
     1040                } catch( SemanticErrorException & e ) {
    11461041                        errors.append( e );
    11471042                } // try
     
    11541049
    11551050// currently only builds assertions, function parameters, and return values
    1156 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {
     1051void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList ) {
    11571052        SemanticErrorException errors;
    1158         std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList );
    1159 
    1160         for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) {
     1053        std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );
     1054
     1055        for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
    11611056                try {
    1162                         ast::Decl * decl = cur->build();
    1163                         assertf( decl, "buildList: build for ast::DeclWithType." );
    1164                         if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
     1057                        Declaration * decl = cur->build();
     1058                        assert( decl );
     1059                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    11651060                                dwt->location = cur->location;
    11661061                                *out++ = dwt;
    1167                         } else if ( ast::StructDecl * agg = dynamic_cast<ast::StructDecl *>( decl ) ) {
     1062                        } else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
    11681063                                // e.g., int foo(struct S) {}
    1169                                 auto inst = new ast::StructInstType( agg->name );
    1170                                 auto obj = new ast::ObjectDecl( cur->location, "", inst );
    1171                                 obj->linkage = linkage;
     1064                                StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->name );
     1065                                auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
     1066                                obj->location = cur->location;
    11721067                                *out++ = obj;
    11731068                                delete agg;
    1174                         } else if ( ast::UnionDecl * agg = dynamic_cast<ast::UnionDecl *>( decl ) ) {
     1069                        } else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
    11751070                                // e.g., int foo(union U) {}
    1176                                 auto inst = new ast::UnionInstType( agg->name );
    1177                                 auto obj = new ast::ObjectDecl( cur->location,
    1178                                         "", inst, nullptr, ast::Storage::Classes(),
    1179                                         linkage );
     1071                                UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->name );
     1072                                auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
     1073                                obj->location = cur->location;
    11801074                                *out++ = obj;
    1181                         } else if ( ast::EnumDecl * agg = dynamic_cast<ast::EnumDecl *>( decl ) ) {
     1075                        } else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) {
    11821076                                // e.g., int foo(enum E) {}
    1183                                 auto inst = new ast::EnumInstType( agg->name );
    1184                                 auto obj = new ast::ObjectDecl( cur->location,
    1185                                         "",
    1186                                         inst,
    1187                                         nullptr,
    1188                                         ast::Storage::Classes(),
    1189                                         linkage
    1190                                 );
     1077                                EnumInstType * inst = new EnumInstType( Type::Qualifiers(), agg->name );
     1078                                auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
     1079                                obj->location = cur->location;
    11911080                                *out++ = obj;
    1192                         } else {
    1193                                 assertf( false, "buildList: Could not convert to ast::DeclWithType." );
    11941081                        } // if
    1195                 } catch ( SemanticErrorException & e ) {
     1082                } catch( SemanticErrorException & e ) {
    11961083                        errors.append( e );
    11971084                } // try
     
    12031090} // buildList
    12041091
    1205 void buildTypeList( const DeclarationNode * firstNode,
    1206                 std::vector<ast::ptr<ast::Type>> & outputList ) {
     1092void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) {
    12071093        SemanticErrorException errors;
    1208         std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList );
    1209 
    1210         for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
     1094        std::back_insert_iterator< std::list< Type * > > out( outputList );
     1095        const DeclarationNode * cur = firstNode;
     1096
     1097        while ( cur ) {
    12111098                try {
    12121099                        * out++ = cur->buildType();
    1213                 } catch ( SemanticErrorException & e ) {
     1100                } catch( SemanticErrorException & e ) {
    12141101                        errors.append( e );
    12151102                } // try
    1216         } // for
     1103                cur = dynamic_cast< DeclarationNode * >( cur->get_next() );
     1104        } // while
    12171105
    12181106        if ( ! errors.isEmpty() ) {
     
    12211109} // buildTypeList
    12221110
    1223 ast::Decl * DeclarationNode::build() const {
     1111Declaration * DeclarationNode::build() const {
    12241112        if ( ! error.empty() ) SemanticError( this, error + " in declaration of " );
    12251113
    12261114        if ( asmStmt ) {
    1227                 auto stmt = strict_dynamic_cast<ast::AsmStmt *>( asmStmt->build() );
    1228                 return new ast::AsmDecl( stmt->location, stmt );
     1115                return new AsmDecl( strict_dynamic_cast<AsmStmt *>( asmStmt->build() ) );
    12291116        } // if
    12301117        if ( directiveStmt ) {
    1231                 auto stmt = strict_dynamic_cast<ast::DirectiveStmt *>( directiveStmt->build() );
    1232                 return new ast::DirectiveDecl( stmt->location, stmt );
    1233         } // if
    1234 
    1235         if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
     1118                return new DirectiveDecl( strict_dynamic_cast<DirectiveStmt *>( directiveStmt->build() ) );
     1119        } // if
     1120
     1121        if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {
    12361122                // otype is internally converted to dtype + otype parameters
    1237                 static const ast::TypeDecl::Kind kindMap[] = { ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Ftype, ast::TypeDecl::Ttype, ast::TypeDecl::Dimension };
    1238                 static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == ast::TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );
     1123                static const TypeDecl::Kind kindMap[] = { TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Ftype, TypeDecl::Ttype, TypeDecl::Dimension };
     1124                static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );
    12391125                assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." );
    1240                 ast::TypeDecl * ret = new ast::TypeDecl( location,
    1241                         *name,
    1242                         ast::Storage::Classes(),
    1243                         (ast::Type *)nullptr,
    1244                         kindMap[ variable.tyClass ],
    1245                         variable.tyClass == ast::TypeDecl::Otype || variable.tyClass == ast::TypeDecl::DStype,
    1246                         variable.initializer ? variable.initializer->buildType() : nullptr
    1247                 );
    1248                 buildList( variable.assertions, ret->assertions );
     1126                TypeDecl * ret = new TypeDecl( *name, Type::StorageClasses(), nullptr, kindMap[ variable.tyClass ], variable.tyClass == TypeDecl::Otype || variable.tyClass == TypeDecl::DStype, variable.initializer ? variable.initializer->buildType() : nullptr );
     1127                buildList( variable.assertions, ret->get_assertions() );
    12491128                return ret;
    12501129        } // if
     
    12681147                } // if
    12691148                bool isDelete = initializer && initializer->get_isDelete();
    1270                 ast::Decl * decl = buildDecl(
    1271                         type,
    1272                         name ? *name : string( "" ),
    1273                         storageClasses,
    1274                         maybeBuild( bitfieldWidth ),
    1275                         funcSpecs,
    1276                         linkage,
    1277                         asmName,
    1278                         isDelete ? nullptr : maybeBuild( initializer ),
    1279                         copy( attributes )
    1280                 )->set_extension( extension );
     1149                Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
    12811150                if ( isDelete ) {
    1282                         auto dwt = strict_dynamic_cast<ast::DeclWithType *>( decl );
     1151                        DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl );
    12831152                        dwt->isDeleted = true;
    12841153                }
     
    12871156
    12881157        if ( assert.condition ) {
    1289                 auto cond = maybeBuild( assert.condition );
    1290                 auto msg = strict_dynamic_cast<ast::ConstantExpr *>( maybeCopy( assert.message ) );
    1291                 return new ast::StaticAssertDecl( location, cond, msg );
     1158                return new StaticAssertDecl( maybeBuild< Expression >( assert.condition ), strict_dynamic_cast< ConstantExpr * >( maybeClone( assert.message ) ) );
    12921159        }
    12931160
     
    13001167        } // if
    13011168        if ( enumInLine ) {
    1302                 return new ast::InlineMemberDecl( location,
    1303                         *name, (ast::Type*)nullptr, storageClasses, linkage );
     1169                return new InlineMemberDecl( *name, storageClasses, linkage, nullptr );
    13041170        } // if
    13051171        assertf( name, "ObjectDecl must a have name\n" );
    1306         auto ret = new ast::ObjectDecl( location,
    1307                 *name,
    1308                 (ast::Type*)nullptr,
    1309                 maybeBuild( initializer ),
    1310                 storageClasses,
    1311                 linkage,
    1312                 maybeBuild( bitfieldWidth )
    1313         );
    1314         ret->asmName = asmName;
    1315         ret->extension = extension;
    1316         return ret;
    1317 }
    1318 
    1319 ast::Type * DeclarationNode::buildType() const {
     1172        return (new ObjectDecl( *name, storageClasses, linkage, maybeBuild< Expression >( bitfieldWidth ), nullptr, maybeBuild< Initializer >( initializer ) ))->set_asmName( asmName )->set_extension( extension );
     1173}
     1174
     1175Type * DeclarationNode::buildType() const {
    13201176        assert( type );
    13211177
     1178        if ( attr.expr ) {
     1179                return new AttrType( buildQualifiers( type ), *name, attr.expr->build(), attributes );
     1180        } else if ( attr.type ) {
     1181                return new AttrType( buildQualifiers( type ), *name, attr.type->buildType(), attributes );
     1182        } // if
     1183
    13221184        switch ( type->kind ) {
    1323         case TypeData::Enum:
    1324         case TypeData::Aggregate: {
    1325                 ast::BaseInstType * ret =
    1326                         buildComAggInst( type, copy( attributes ), linkage );
    1327                 buildList( type->aggregate.actuals, ret->params );
    1328                 return ret;
    1329         }
    1330         case TypeData::Symbolic: {
    1331                 ast::TypeInstType * ret = new ast::TypeInstType(
    1332                         *type->symbolic.name,
    1333                         // This is just a default, the true value is not known yet.
    1334                         ast::TypeDecl::Dtype,
    1335                         buildQualifiers( type ),
    1336                         copy( attributes ) );
    1337                 buildList( type->symbolic.actuals, ret->params );
    1338                 return ret;
    1339         }
    1340         default:
    1341                 ast::Type * simpletypes = typebuild( type );
    1342                 // copy because member is const
    1343                 simpletypes->attributes = attributes;
     1185          case TypeData::Enum:
     1186          case TypeData::Aggregate: {
     1187                  ReferenceToType * ret = buildComAggInst( type, attributes, linkage );
     1188                  buildList( type->aggregate.actuals, ret->get_parameters() );
     1189                  return ret;
     1190          }
     1191          case TypeData::Symbolic: {
     1192                  TypeInstType * ret = new TypeInstType( buildQualifiers( type ), *type->symbolic.name, false, attributes );
     1193                  buildList( type->symbolic.actuals, ret->get_parameters() );
     1194                  return ret;
     1195          }
     1196          default:
     1197                Type * simpletypes = typebuild( type );
     1198                simpletypes->get_attributes() = attributes;             // copy because member is const
    13441199                return simpletypes;
    13451200        } // switch
  • src/Parser/ExpressionNode.cc

    r24d6572 r34b4268  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat May 16 13:17:07 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr  4 11:07:00 2023
    13 // Update Count     : 1083
    14 //
    15 
    16 #include "ExpressionNode.h"
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Aug  7 09:18:56 2021
     13// Update Count     : 1077
     14//
    1715
    1816#include <cassert>                 // for assert
     
    2321#include <string>                  // for string, operator+, operator==
    2422
    25 #include "AST/Expr.hpp"            // for NameExpr
    26 #include "AST/Type.hpp"            // for BaseType, SueInstType
    2723#include "Common/SemanticError.h"  // for SemanticError
    2824#include "Common/utility.h"        // for maybeMoveBuild, maybeBuild, CodeLo...
    29 #include "DeclarationNode.h"       // for DeclarationNode
    30 #include "InitializerNode.h"       // for InitializerNode
     25#include "ParseNode.h"             // for ExpressionNode, maybeMoveBuildType
     26#include "SynTree/Constant.h"      // for Constant
     27#include "SynTree/Declaration.h"   // for EnumDecl, StructDecl, UnionDecl
     28#include "SynTree/Expression.h"    // for Expression, ConstantExpr, NameExpr
     29#include "SynTree/Statement.h"     // for CompoundStmt, Statement
     30#include "SynTree/Type.h"          // for BasicType, Type, Type::Qualifiers
    3131#include "parserutility.h"         // for notZeroExpr
     32
     33class Initializer;
    3234
    3335using namespace std;
     
    4648// because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their
    4749// type.
     50
     51extern const Type::Qualifiers noQualifiers;                             // no qualifiers on constants
    4852
    4953// static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
     
    6771        size_t end = str.length() - 1;
    6872        if ( posn == end ) { type = 3; return; }                        // no length after 'l' => long
    69 
     73       
    7074        string::size_type next = posn + 1;                                      // advance to length
    7175        if ( str[next] == '3' ) {                                                       // 32
     
    118122                if ( str[i] == '1' ) v |= 1;
    119123                i += 1;
    120                 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
     124          if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
    121125                v <<= 1;
    122126        } // for
    123127} // scanbin
    124128
    125 ast::Expr * build_constantInteger(
    126                 const CodeLocation & location, string & str ) {
    127         static const ast::BasicType::Kind kind[2][6] = {
     129Expression * build_constantInteger( string & str ) {
     130        static const BasicType::Kind kind[2][6] = {
    128131                // short (h) must be before char (hh) because shorter type has the longer suffix
    129                 { ast::BasicType::ShortSignedInt, ast::BasicType::SignedChar, ast::BasicType::SignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ ast::BasicType::LongLongSignedInt, },
    130                 { ast::BasicType::ShortUnsignedInt, ast::BasicType::UnsignedChar, ast::BasicType::UnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ ast::BasicType::LongLongUnsignedInt, },
     132                { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ BasicType::LongLongSignedInt, },
     133                { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ BasicType::LongLongUnsignedInt, },
    131134        };
    132135
     
    138141        string str2( "0x0" );
    139142        unsigned long long int v, v2 = 0;                                       // converted integral value
    140         ast::Expr * ret, * ret2;
     143        Expression * ret, * ret2;
    141144
    142145        int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     
    146149        // special constants
    147150        if ( str == "0" ) {
    148                 ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0 );
     151                ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ) );
    149152                goto CLEANUP;
    150153        } // if
    151154        if ( str == "1" ) {
    152                 ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1 );
     155                ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ) );
    153156                goto CLEANUP;
    154157        } // if
     158
     159        string::size_type posn;
    155160
    156161        // 'u' can appear before or after length suffix
     
    161166        } else {
    162167                // At least one digit in integer constant, so safe to backup while looking for suffix.
    163                 // This declaration and the comma expressions in the conditions mimic
    164                 // the declare and check pattern allowed in later compiler versions.
    165                 // (Only some early compilers/C++ standards do not support it.)
    166                 string::size_type posn;
    167                 // pointer value
    168                 if ( posn = str.find_last_of( "pP" ), posn != string::npos ) {
    169                         ltype = 5; str.erase( posn, 1 );
    170                 // size_t
    171                 } else if ( posn = str.find_last_of( "zZ" ), posn != string::npos ) {
    172                         Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 );
    173                 // signed char
    174                 } else if ( posn = str.rfind( "hh" ), posn != string::npos ) {
    175                         type = 1; str.erase( posn, 2 );
    176                 // signed char
    177                 } else if ( posn = str.rfind( "HH" ), posn != string::npos ) {
    178                         type = 1; str.erase( posn, 2 );
    179                 // short
    180                 } else if ( posn = str.find_last_of( "hH" ), posn != string::npos ) {
    181                         type = 0; str.erase( posn, 1 );
    182                 // int (natural number)
    183                 } else if ( posn = str.find_last_of( "nN" ), posn != string::npos ) {
    184                         type = 2; str.erase( posn, 1 );
    185                 } else if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) {
    186                         type = 4;
    187                 } else {
    188                         lnthSuffix( str, type, ltype );
    189                 } // if
     168
     169                posn = str.find_last_of( "pP" );                                // pointer value
     170                if ( posn != string::npos ) { ltype = 5; str.erase( posn, 1 ); goto FINI; }
     171
     172                posn = str.find_last_of( "zZ" );                                // size_t
     173                if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
     174
     175                posn = str.rfind( "hh" );                                               // char
     176                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
     177
     178                posn = str.rfind( "HH" );                                               // char
     179                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
     180
     181                posn = str.find_last_of( "hH" );                                // short
     182                if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; }
     183
     184                posn = str.find_last_of( "nN" );                                // int (natural number)
     185                if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
     186
     187                if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
     188
     189                lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
     190          FINI: ;
    190191        } // if
    191192
     
    195196        if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str );
    196197#endif // ! __SIZEOF_INT128__
    197 
     198       
    198199        if ( str[0] == '0' ) {                                                          // radix character ?
    199200                dec = false;
     
    205206                                unsigned int len = str.length();
    206207                                if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str );
    207                                 // hex digits < 2^64
    208                                 if ( len > (2 + 16) ) {
    209                                         str2 = "0x" + str.substr( len - 16 );
    210                                         sscanf( (char *)str2.c_str(), "%llx", &v2 );
    211                                         str = str.substr( 0, len - 16 );
    212                                 } // if
     208                          if ( len <= (2 + 16) ) goto FHEX1;            // hex digits < 2^64
     209                                str2 = "0x" + str.substr( len - 16 );
     210                                sscanf( (char *)str2.c_str(), "%llx", &v2 );
     211                                str = str.substr( 0, len - 16 );
     212                          FHEX1: ;
    213213                                sscanf( (char *)str.c_str(), "%llx", &v );
    214214#endif // __SIZEOF_INT128__
     
    301301
    302302        // Constant type is correct for overload resolving.
    303         ret = new ast::ConstantExpr( location,
    304                 new ast::BasicType( kind[Unsigned][type] ), str, v );
     303        ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][type] ), str, v ) );
    305304        if ( Unsigned && type < 2 ) {                                           // hh or h, less than int ?
    306305                // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
    307                 ret = new ast::CastExpr( location,
    308                         ret,
    309                         new ast::BasicType( kind[Unsigned][type] ),
    310                         ast::ExplicitCast );
     306                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
    311307        } else if ( ltype != -1 ) {                                                     // explicit length ?
    312308                if ( ltype == 6 ) {                                                             // int128, (int128)constant
    313                         ret2 = new ast::ConstantExpr( location,
    314                                 new ast::BasicType( ast::BasicType::LongLongSignedInt ),
    315                                 str2,
    316                                 v2 );
    317                         ret = build_compoundLiteral( location,
    318                                 DeclarationNode::newBasicType(
    319                                         DeclarationNode::Int128
    320                                 )->addType(
    321                                         DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
    322                                 new InitializerNode(
    323                                         (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true )
    324                         );
     309//                      ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
     310                        ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) );
     311                        ret = build_compoundLiteral( DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
     312                                                                                 new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) );
    325313                } else {                                                                                // explicit length, (length_type)constant
    326                         ret = new ast::CastExpr( location,
    327                                 ret,
    328                                 new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ),
    329                                 ast::ExplicitCast );
     314                        ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
    330315                        if ( ltype == 5 ) {                                                     // pointer, intptr( (uintptr_t)constant )
    331                                 ret = build_func( location,
    332                                         new ExpressionNode(
    333                                                 build_varref( location, new string( "intptr" ) ) ),
    334                                         new ExpressionNode( ret ) );
     316                                ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) );
    335317                        } // if
    336318                } // if
     
    376358
    377359
    378 ast::Expr * build_constantFloat(
    379                 const CodeLocation & location, string & str ) {
    380         static const ast::BasicType::Kind kind[2][12] = {
    381                 { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x },
    382                 { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex },
     360Expression * build_constantFloat( string & str ) {
     361        static const BasicType::Kind kind[2][12] = {
     362                { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x },
     363                { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex },
    383364        };
    384365
     
    417398
    418399        assert( 0 <= type && type < 12 );
    419         ast::Expr * ret = new ast::ConstantExpr( location,
    420                 new ast::BasicType( kind[complx][type] ),
    421                 str,
    422                 v );
    423         // explicit length ?
    424         if ( explnth ) {
    425                 ret = new ast::CastExpr( location,
    426                         ret,
    427                         new ast::BasicType( kind[complx][type] ),
    428                         ast::ExplicitCast );
     400        Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][type] ), str, v ) );
     401        if ( explnth ) {                                                                        // explicit length ?
     402                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][type] ), false );
    429403        } // if
    430404
     
    441415} // sepString
    442416
    443 ast::Expr * build_constantChar( const CodeLocation & location, string & str ) {
     417Expression * build_constantChar( string & str ) {
    444418        string units;                                                                           // units
    445419        sepString( str, units, '\'' );                                          // separate constant from units
    446420
    447         ast::Expr * ret = new ast::ConstantExpr( location,
    448                 new ast::BasicType( ast::BasicType::Char ),
    449                 str,
    450                 (unsigned long long int)(unsigned char)str[1] );
     421        Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) );
    451422        if ( units.length() != 0 ) {
    452                 ret = new ast::UntypedExpr( location,
    453                         new ast::NameExpr( location, units ),
    454                         { ret } );
     423                ret = new UntypedExpr( new NameExpr( units ), { ret } );
    455424        } // if
    456425
     
    459428} // build_constantChar
    460429
    461 ast::Expr * build_constantStr(
    462                 const CodeLocation & location,
    463                 string & str ) {
     430Expression * build_constantStr( string & str ) {
    464431        assert( str.length() > 0 );
    465432        string units;                                                                           // units
    466433        sepString( str, units, '"' );                                           // separate constant from units
    467434
    468         ast::Type * strtype;
     435        Type * strtype;
    469436        switch ( str[0] ) {                                                                     // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1
    470         case 'u':
     437          case 'u':
    471438                if ( str[1] == '8' ) goto Default;                              // utf-8 characters => array of char
    472439                // lookup type of associated typedef
    473                 strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype );
     440                strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );
    474441                break;
    475         case 'U':
    476                 strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype );
     442          case 'U':
     443                strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );
    477444                break;
    478         case 'L':
    479                 strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype );
     445          case 'L':
     446                strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );
    480447                break;
    481         Default:                                                                                        // char default string type
    482         default:
    483                 strtype = new ast::BasicType( ast::BasicType::Char );
     448          Default:                                                                                      // char default string type
     449          default:
     450                strtype = new BasicType( Type::Qualifiers( ), BasicType::Char );
    484451        } // switch
    485         ast::ArrayType * at = new ast::ArrayType(
    486                 strtype,
    487                 // Length is adjusted: +1 for '\0' and -2 for '"'
    488                 ast::ConstantExpr::from_ulong( location, str.size() + 1 - 2 ),
    489                 ast::FixedLen,
    490                 ast::DynamicDim );
    491         ast::Expr * ret = new ast::ConstantExpr( location, at, str, std::nullopt );
     452        ArrayType * at = new ArrayType( noQualifiers, strtype,
     453                                                                        new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
     454                                                                        false, false );
     455        Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) );
    492456        if ( units.length() != 0 ) {
    493                 ret = new ast::UntypedExpr( location,
    494                         new ast::NameExpr( location, units ),
    495                         { ret } );
     457                ret = new UntypedExpr( new NameExpr( units ), { ret } );
    496458        } // if
    497459
     
    500462} // build_constantStr
    501463
    502 ast::Expr * build_field_name_FLOATING_FRACTIONconstant(
    503                 const CodeLocation & location, const string & str ) {
     464Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) {
    504465        if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str );
    505         ast::Expr * ret = build_constantInteger( location,
    506                 *new string( str.substr(1) ) );
     466        Expression * ret = build_constantInteger( *new string( str.substr(1) ) );
    507467        delete &str;
    508468        return ret;
    509469} // build_field_name_FLOATING_FRACTIONconstant
    510470
    511 ast::Expr * build_field_name_FLOATING_DECIMALconstant(
    512                 const CodeLocation & location, const string & str ) {
     471Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) {
    513472        if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str );
    514         ast::Expr * ret = build_constantInteger(
    515                 location, *new string( str.substr( 0, str.size()-1 ) ) );
     473        Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) );
    516474        delete &str;
    517475        return ret;
    518476} // build_field_name_FLOATING_DECIMALconstant
    519477
    520 ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location,
    521                 const string & str ) {
     478Expression * build_field_name_FLOATINGconstant( const string & str ) {
    522479        // str is of the form A.B -> separate at the . and return member expression
    523480        int a, b;
     
    525482        stringstream ss( str );
    526483        ss >> a >> dot >> b;
    527         auto ret = new ast::UntypedMemberExpr( location,
    528                 ast::ConstantExpr::from_int( location, b ),
    529                 ast::ConstantExpr::from_int( location, a )
    530         );
     484        UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) );
    531485        delete &str;
    532486        return ret;
    533487} // build_field_name_FLOATINGconstant
    534488
    535 ast::Expr * make_field_name_fraction_constants( const CodeLocation & location,
    536                 ast::Expr * fieldName,
    537                 ast::Expr * fracts ) {
    538         if ( nullptr == fracts ) {
    539                 return fieldName;
    540         } else if ( auto memberExpr = dynamic_cast<ast::UntypedMemberExpr *>( fracts ) ) {
    541                 memberExpr->member = make_field_name_fraction_constants( location,
    542                         fieldName,
    543                         ast::mutate( memberExpr->aggregate.get() ) );
    544                 return memberExpr;
    545         } else {
    546                 return new ast::UntypedMemberExpr( location, fracts, fieldName );
    547         } // if
     489Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) {
     490        if ( fracts ) {
     491                if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) {
     492                        memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) );
     493                        return memberExpr;
     494                } else {
     495                        return new UntypedMemberExpr( fracts, fieldName );
     496                } // if
     497        } // if
     498        return fieldName;
    548499} // make_field_name_fraction_constants
    549500
    550 ast::Expr * build_field_name_fraction_constants( const CodeLocation & location,
    551                 ast::Expr * fieldName,
    552                 ExpressionNode * fracts ) {
    553         return make_field_name_fraction_constants( location, fieldName, maybeMoveBuild( fracts ) );
     501Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) {
     502        return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) );
    554503} // build_field_name_fraction_constants
    555504
    556 ast::NameExpr * build_varref( const CodeLocation & location,
    557                 const string * name ) {
    558         ast::NameExpr * expr = new ast::NameExpr( location, *name );
     505NameExpr * build_varref( const string * name ) {
     506        NameExpr * expr = new NameExpr( *name );
    559507        delete name;
    560508        return expr;
    561509} // build_varref
    562510
    563 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
    564                 const DeclarationNode * decl_node,
    565                 const ast::NameExpr * name ) {
    566         ast::Decl * newDecl = maybeBuild( decl_node );
    567         if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
    568                 if ( const ast::Type * t = newDeclWithType->get_type() ) {
    569                         if ( auto typeInst = dynamic_cast<const ast::TypeInstType *>( t ) ) {
    570                                 newDecl = new ast::EnumDecl( location, typeInst->name );
     511QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name ) {
     512        Declaration * newDecl = maybeBuild< Declaration >(decl_node);
     513        if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) {
     514                const Type * t = newDeclWithType->get_type();
     515                if ( t ) {
     516                        if ( const TypeInstType * typeInst = dynamic_cast<const TypeInstType *>( t ) ) {
     517                                newDecl= new EnumDecl( typeInst->name );
    571518                        }
    572519                }
    573520        }
    574         return new ast::QualifiedNameExpr( location, newDecl, name->name );
     521        return new QualifiedNameExpr( newDecl, name->name );
    575522}
    576523
    577 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
    578                 const ast::EnumDecl * decl,
    579                 const ast::NameExpr * name ) {
    580         return new ast::QualifiedNameExpr( location, decl, name->name );
     524QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl_node, const NameExpr * name ) {
     525        EnumDecl * newDecl = const_cast< EnumDecl * >( decl_node );
     526        return new QualifiedNameExpr( newDecl, name->name );
    581527}
    582528
    583 ast::DimensionExpr * build_dimensionref( const CodeLocation & location,
    584                 const string * name ) {
    585         ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name );
     529DimensionExpr * build_dimensionref( const string * name ) {
     530        DimensionExpr * expr = new DimensionExpr( *name );
    586531        delete name;
    587532        return expr;
     
    599544}; // OperName
    600545
    601 ast::Expr * build_cast( const CodeLocation & location,
    602                 DeclarationNode * decl_node,
    603                 ExpressionNode * expr_node,
    604                 ast::CastExpr::CastKind kind ) {
    605         ast::Type * targetType = maybeMoveBuildType( decl_node );
    606         if ( dynamic_cast<ast::VoidType *>( targetType ) ) {
     546Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind ) {
     547        Type * targetType = maybeMoveBuildType( decl_node );
     548        if ( dynamic_cast< VoidType * >( targetType ) ) {
    607549                delete targetType;
    608                 return new ast::CastExpr( location,
    609                         maybeMoveBuild( expr_node ),
    610                         ast::ExplicitCast, kind );
     550                return new CastExpr( maybeMoveBuild< Expression >(expr_node), false, kind );
    611551        } else {
    612                 return new ast::CastExpr( location,
    613                         maybeMoveBuild( expr_node ),
    614                         targetType,
    615                         ast::ExplicitCast, kind );
     552                return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false, kind );
    616553        } // if
    617554} // build_cast
    618555
    619 ast::Expr * build_keyword_cast( const CodeLocation & location,
    620                 ast::AggregateDecl::Aggregate target,
    621                 ExpressionNode * expr_node ) {
    622         return new ast::KeywordCastExpr( location,
    623                 maybeMoveBuild( expr_node ),
    624                 target
    625         );
     556Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ) {
     557        return new KeywordCastExpr( maybeMoveBuild< Expression >(expr_node), target );
    626558}
    627559
    628 ast::Expr * build_virtual_cast( const CodeLocation & location,
    629                 DeclarationNode * decl_node,
    630                 ExpressionNode * expr_node ) {
    631         return new ast::VirtualCastExpr( location,
    632                 maybeMoveBuild( expr_node ),
    633                 maybeMoveBuildType( decl_node )
    634         );
     560Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {
     561        return new VirtualCastExpr( maybeMoveBuild< Expression >( expr_node ), maybeMoveBuildType( decl_node ) );
    635562} // build_virtual_cast
    636563
    637 ast::Expr * build_fieldSel( const CodeLocation & location,
    638                 ExpressionNode * expr_node,
    639                 ast::Expr * member ) {
    640         return new ast::UntypedMemberExpr( location,
    641                 member,
    642                 maybeMoveBuild( expr_node )
    643         );
     564Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) {
     565        return new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) );
    644566} // build_fieldSel
    645567
    646 ast::Expr * build_pfieldSel( const CodeLocation & location,
    647                 ExpressionNode * expr_node,
    648                 ast::Expr * member ) {
    649         auto deref = new ast::UntypedExpr( location,
    650                 new ast::NameExpr( location, "*?" )
    651         );
     568Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) {
     569        UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
    652570        deref->location = expr_node->location;
    653         deref->args.push_back( maybeMoveBuild( expr_node ) );
    654         auto ret = new ast::UntypedMemberExpr( location, member, deref );
     571        deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) );
     572        UntypedMemberExpr * ret = new UntypedMemberExpr( member, deref );
    655573        return ret;
    656574} // build_pfieldSel
    657575
    658 ast::Expr * build_offsetOf( const CodeLocation & location,
    659                 DeclarationNode * decl_node,
    660                 ast::NameExpr * member ) {
    661         ast::Expr * ret = new ast::UntypedOffsetofExpr( location,
    662                 maybeMoveBuildType( decl_node ),
    663                 member->name
    664         );
    665         ret->result = new ast::BasicType( ast::BasicType::LongUnsignedInt );
     576Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) {
     577        Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() );
    666578        delete member;
    667579        return ret;
    668580} // build_offsetOf
    669581
    670 ast::Expr * build_and_or( const CodeLocation & location,
    671                 ExpressionNode * expr_node1,
    672                 ExpressionNode * expr_node2,
    673                 ast::LogicalFlag flag ) {
    674         return new ast::LogicalExpr( location,
    675                 notZeroExpr( maybeMoveBuild( expr_node1 ) ),
    676                 notZeroExpr( maybeMoveBuild( expr_node2 ) ),
    677                 flag
    678         );
     582Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ) {
     583        return new LogicalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), notZeroExpr( maybeMoveBuild< Expression >(expr_node2) ), kind );
    679584} // build_and_or
    680585
    681 ast::Expr * build_unary_val( const CodeLocation & location,
    682                 OperKinds op,
    683                 ExpressionNode * expr_node ) {
    684         std::vector<ast::ptr<ast::Expr>> args;
    685         args.push_back( maybeMoveBuild( expr_node ) );
    686         return new ast::UntypedExpr( location,
    687                 new ast::NameExpr( location, OperName[ (int)op ] ),
    688                 std::move( args )
    689         );
     586Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ) {
     587        list< Expression * > args;
     588        args.push_back( maybeMoveBuild< Expression >(expr_node) );
     589        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    690590} // build_unary_val
    691591
    692 ast::Expr * build_binary_val( const CodeLocation & location,
    693                 OperKinds op,
    694                 ExpressionNode * expr_node1,
    695                 ExpressionNode * expr_node2 ) {
    696         std::vector<ast::ptr<ast::Expr>> args;
    697         args.push_back( maybeMoveBuild( expr_node1 ) );
    698         args.push_back( maybeMoveBuild( expr_node2 ) );
    699         return new ast::UntypedExpr( location,
    700                 new ast::NameExpr( location, OperName[ (int)op ] ),
    701                 std::move( args )
    702         );
     592Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
     593        list< Expression * > args;
     594        args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.
     595        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
     596} // build_unary_ptr
     597
     598Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
     599        list< Expression * > args;
     600        args.push_back( maybeMoveBuild< Expression >(expr_node1) );
     601        args.push_back( maybeMoveBuild< Expression >(expr_node2) );
     602        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    703603} // build_binary_val
    704604
    705 ast::Expr * build_cond( const CodeLocation & location,
    706                 ExpressionNode * expr_node1,
    707                 ExpressionNode * expr_node2,
    708                 ExpressionNode * expr_node3 ) {
    709         return new ast::ConditionalExpr( location,
    710                 notZeroExpr( maybeMoveBuild( expr_node1 ) ),
    711                 maybeMoveBuild( expr_node2 ),
    712                 maybeMoveBuild( expr_node3 )
    713         );
     605Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
     606        list< Expression * > args;
     607        args.push_back( maybeMoveBuild< Expression >(expr_node1) );
     608        args.push_back( maybeMoveBuild< Expression >(expr_node2) );
     609        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
     610} // build_binary_ptr
     611
     612Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ) {
     613        return new ConditionalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), maybeMoveBuild< Expression >(expr_node2), maybeMoveBuild< Expression >(expr_node3) );
    714614} // build_cond
    715615
    716 ast::Expr * build_tuple( const CodeLocation & location,
    717                 ExpressionNode * expr_node ) {
    718         std::vector<ast::ptr<ast::Expr>> exprs;
     616Expression * build_tuple( ExpressionNode * expr_node ) {
     617        list< Expression * > exprs;
    719618        buildMoveList( expr_node, exprs );
    720         return new ast::UntypedTupleExpr( location, std::move( exprs ) );
     619        return new UntypedTupleExpr( exprs );;
    721620} // build_tuple
    722621
    723 ast::Expr * build_func( const CodeLocation & location,
    724                 ExpressionNode * function,
    725                 ExpressionNode * expr_node ) {
    726         std::vector<ast::ptr<ast::Expr>> args;
     622Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) {
     623        list< Expression * > args;
    727624        buildMoveList( expr_node, args );
    728         return new ast::UntypedExpr( location,
    729                 maybeMoveBuild( function ),
    730                 std::move( args )
    731         );
     625        return new UntypedExpr( maybeMoveBuild< Expression >(function), args );
    732626} // build_func
    733627
    734 ast::Expr * build_compoundLiteral( const CodeLocation & location,
    735                 DeclarationNode * decl_node,
    736                 InitializerNode * kids ) {
    737         // compound literal type
    738         ast::Decl * newDecl = maybeBuild( decl_node );
    739         // non-sue compound-literal type
    740         if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
    741                 return new ast::CompoundLiteralExpr( location,
    742                         newDeclWithType->get_type(),
    743                         maybeMoveBuild( kids ) );
     628Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ) {
     629        Declaration * newDecl = maybeBuild< Declaration >(decl_node); // compound literal type
     630        if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type
     631                return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild< Initializer >(kids) );
    744632        // these types do not have associated type information
    745         } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) {
    746                 if ( newDeclStructDecl->body ) {
    747                         return new ast::CompoundLiteralExpr( location,
    748                                 new ast::StructInstType( newDeclStructDecl ),
    749                                 maybeMoveBuild( kids ) );
     633        } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl )  ) {
     634                if ( newDeclStructDecl->has_body() ) {
     635                        return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild< Initializer >(kids) );
    750636                } else {
    751                         return new ast::CompoundLiteralExpr( location,
    752                                 new ast::StructInstType( newDeclStructDecl->name ),
    753                                 maybeMoveBuild( kids ) );
    754                 } // if
    755         } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl )  ) {
    756                 if ( newDeclUnionDecl->body ) {
    757                         return new ast::CompoundLiteralExpr( location,
    758                                 new ast::UnionInstType( newDeclUnionDecl ),
    759                                 maybeMoveBuild( kids ) );
     637                        return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
     638                } // if
     639        } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl )  ) {
     640                if ( newDeclUnionDecl->has_body() ) {
     641                        return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild< Initializer >(kids) );
    760642                } else {
    761                         return new ast::CompoundLiteralExpr( location,
    762                                 new ast::UnionInstType( newDeclUnionDecl->name ),
    763                                 maybeMoveBuild( kids ) );
    764                 } // if
    765         } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl )  ) {
    766                 if ( newDeclEnumDecl->body ) {
    767                         return new ast::CompoundLiteralExpr( location,
    768                                 new ast::EnumInstType( newDeclEnumDecl ),
    769                                 maybeMoveBuild( kids ) );
     643                        return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
     644                } // if
     645        } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl )  ) {
     646                if ( newDeclEnumDecl->has_body() ) {
     647                        return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild< Initializer >(kids) );
    770648                } else {
    771                         return new ast::CompoundLiteralExpr( location,
    772                                 new ast::EnumInstType( newDeclEnumDecl->name ),
    773                                 maybeMoveBuild( kids ) );
     649                        return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
    774650                } // if
    775651        } else {
     
    780656// Local Variables: //
    781657// tab-width: 4 //
     658// mode: c++ //
     659// compile-command: "make install" //
    782660// End: //
  • src/Parser/InitializerNode.cc

    r24d6572 r34b4268  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:20:24 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr  4 11:18:00 2023
    13 // Update Count     : 27
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 28 23:27:20 2017
     13// Update Count     : 26
    1414//
    15 
    16 #include "InitializerNode.h"
    1715
    1816#include <iostream>                // for operator<<, ostream, basic_ostream
     
    2018#include <string>                  // for operator<<, string
    2119
    22 #include "AST/Expr.hpp"            // for Expr
    23 #include "AST/Init.hpp"            // for Designator, Init, ListInit, Sing...
     20using namespace std;
     21
    2422#include "Common/SemanticError.h"  // for SemanticError
    2523#include "Common/utility.h"        // for maybeBuild
    26 #include "ExpressionNode.h"        // for ExpressionNode
    27 #include "DeclarationNode.h"       // for buildList
    28 
    29 using namespace std;
    30 
    31 static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) {
    32         return maybeConstructed ? ast::MaybeConstruct : ast::NoConstruct;
    33 }
     24#include "ParseNode.h"             // for InitializerNode, ExpressionNode
     25#include "SynTree/Expression.h"    // for Expression
     26#include "SynTree/Initializer.h"   // for Initializer, ListInit, SingleInit
    3427
    3528InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des )
     
    4033        if ( kids )
    4134                set_last( nullptr );
    42 } // InitializerNode::InitializerNode
     35} // InitializerNode::InitializerNode
    4336
    4437InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des )
     
    9285} // InitializerNode::printOneLine
    9386
    94 ast::Init * InitializerNode::build() const {
     87Initializer * InitializerNode::build() const {
    9588        assertf( ! isDelete, "Should not build delete stmt InitializerNode" );
    9689        if ( aggregate ) {
    9790                // steal designators from children
    98                 std::vector<ast::ptr<ast::Designation>> designlist;
     91                std::list< Designation * > designlist;
    9992                InitializerNode * child = next_init();
    100                 for ( ; child != nullptr ; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
    101                         std::deque<ast::ptr<ast::Expr>> desList;
    102                         buildList( child->designator, desList );
    103                         designlist.push_back(
    104                                 new ast::Designation( location, std::move( desList ) ) );
     93                for ( ; child != nullptr; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
     94                        std::list< Expression * > desList;
     95                        buildList< Expression, ExpressionNode >( child->designator, desList );
     96                        designlist.push_back( new Designation( desList ) );
    10597                } // for
    106                 std::vector<ast::ptr<ast::Init>> initlist;
    107                 buildList( next_init(), initlist );
    108                 return new ast::ListInit( location,
    109                         std::move( initlist ),
    110                         std::move( designlist ),
    111                         toConstructFlag( maybeConstructed )
    112                 );
    113         } else if ( get_expression() ) {
    114                 assertf( get_expression()->expr, "The expression of initializer must have value" );
    115                 return new ast::SingleInit( location,
    116                         maybeBuild( get_expression() ),
    117                         toConstructFlag( maybeConstructed )
    118                 );
     98                std::list< Initializer * > initlist;
     99                buildList< Initializer, InitializerNode >( next_init(), initlist );
     100                return new ListInit( initlist, designlist, maybeConstructed );
     101        } else {
     102                if ( get_expression() ) {
     103                        assertf( get_expression()->expr, "The expression of initializer must have value" );
     104                        return new SingleInit( maybeBuild< Expression >( get_expression() ), maybeConstructed );
     105                } // if
    119106        } // if
    120107        return nullptr;
  • src/Parser/ParseNode.h

    r24d6572 r34b4268  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:28:16 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Apr  3 17:55:00 2023
    13 // Update Count     : 942
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Nov  2 21:27:07 2022
     13// Update Count     : 939
    1414//
    1515
     
    2424#include <string>                  // for string
    2525
    26 #include "AST/Expr.hpp"            // for Expr, NameExpr LogicalFlag
    27 #include "AST/Fwd.hpp"             // for ptr, Decl, DeclWithType,
    28 #include "AST/Stmt.hpp"            // for Stmt
    2926#include "Common/CodeLocation.h"   // for CodeLocation
    3027#include "Common/SemanticError.h"  // for SemanticError
    3128#include "Common/UniqueName.h"     // for UniqueName
    32 #include "Common/utility.h"        // for maybeClone
    33 #include "Parser/parserutility.h"  // for maybeBuild, maybeCopy
     29#include "Common/utility.h"        // for maybeClone, maybeBuild
     30#include "SynTree/LinkageSpec.h"   // for Spec
     31#include "SynTree/Declaration.h"   // for Aggregate
     32#include "SynTree/Expression.h"    // for Expression, ConstantExpr (ptr only)
     33#include "SynTree/Label.h"         // for Label
     34#include "SynTree/Statement.h"     // for Statement, BranchStmt, BranchStmt:...
     35#include "SynTree/Type.h"          // for Type, Type::FuncSpecifiers, Type::...
    3436
    3537class Attribute;
     
    3840class DeclarationWithType;
    3941class Initializer;
    40 class InitializerNode;
    4142class ExpressionNode;
    4243struct StatementNode;
     
    8081        CodeLocation location = yylloc;
    8182}; // ParseNode
     83
     84//##############################################################################
     85
     86class InitializerNode : public ParseNode {
     87  public:
     88        InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );
     89        InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
     90        InitializerNode( bool isDelete );
     91        ~InitializerNode();
     92        virtual InitializerNode * clone() const { assert( false ); return nullptr; }
     93
     94        ExpressionNode * get_expression() const { return expr; }
     95
     96        InitializerNode * set_designators( ExpressionNode * des ) { designator = des; return this; }
     97        ExpressionNode * get_designators() const { return designator; }
     98
     99        InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }
     100        bool get_maybeConstructed() const { return maybeConstructed; }
     101
     102        bool get_isDelete() const { return isDelete; }
     103
     104        InitializerNode * next_init() const { return kids; }
     105
     106        void print( std::ostream & os, int indent = 0 ) const;
     107        void printOneLine( std::ostream & ) const;
     108
     109        virtual Initializer * build() const;
     110  private:
     111        ExpressionNode * expr;
     112        bool aggregate;
     113        ExpressionNode * designator;                                            // may be list
     114        InitializerNode * kids;
     115        bool maybeConstructed;
     116        bool isDelete;
     117}; // InitializerNode
     118
     119//##############################################################################
     120
     121class ExpressionNode final : public ParseNode {
     122  public:
     123        ExpressionNode( Expression * expr = nullptr ) : expr( expr ) {}
     124        virtual ~ExpressionNode() {}
     125        virtual ExpressionNode * clone() const override { return expr ? static_cast<ExpressionNode*>((new ExpressionNode( expr->clone() ))->set_next( maybeClone( get_next() ) )) : nullptr; }
     126
     127        bool get_extension() const { return extension; }
     128        ExpressionNode * set_extension( bool exten ) { extension = exten; return this; }
     129
     130        virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {
     131                os << expr.get();
     132        }
     133        void printOneLine( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
     134
     135        template<typename T>
     136        bool isExpressionType() const { return nullptr != dynamic_cast<T>(expr.get()); }
     137
     138        Expression * build() const { return const_cast<ExpressionNode *>(this)->expr.release(); }
     139
     140        std::unique_ptr<Expression> expr;                                       // public because of lifetime implications
     141  private:
     142        bool extension = false;
     143}; // ExpressionNode
     144
     145template< typename T >
     146struct maybeBuild_t< Expression, T > {
     147        static inline Expression * doit( const T * orig ) {
     148                if ( orig ) {
     149                        Expression * p = orig->build();
     150                        p->set_extension( orig->get_extension() );
     151                        p->location = orig->location;
     152                        return p;
     153                } else {
     154                        return nullptr;
     155                } // if
     156        }
     157};
    82158
    83159// Must harmonize with OperName.
     
    96172
    97173struct LabelNode {
    98         std::vector<ast::Label> labels;
     174        std::list< Label > labels;
    99175};
    100176
     177Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string
     178Expression * build_constantFloat( std::string & str );
     179Expression * build_constantChar( std::string & str );
     180Expression * build_constantStr( std::string & str );
     181Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );
     182Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );
     183Expression * build_field_name_FLOATINGconstant( const std::string & str );
     184Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts );
     185
     186NameExpr * build_varref( const std::string * name );
     187QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name );
     188QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl, const NameExpr * name );
     189DimensionExpr * build_dimensionref( const std::string * name );
     190
     191Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind = CastExpr::Default );
     192Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node );
     193Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );
     194Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member );
     195Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member );
     196Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member );
     197Expression * build_and( ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
     198Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind );
     199Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node );
     200Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node );
     201Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
     202Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
     203Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 );
     204Expression * build_tuple( ExpressionNode * expr_node = nullptr );
     205Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node );
     206Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids );
     207
     208//##############################################################################
     209
     210struct TypeData;
     211
     212struct DeclarationNode : public ParseNode {
     213        // These enumerations must harmonize with their names in DeclarationNode.cc.
     214        enum BasicType { Void, Bool, Char, Int, Int128,
     215                                         Float, Double, LongDouble, uuFloat80, uuFloat128,
     216                                         uFloat16, uFloat32, uFloat32x, uFloat64, uFloat64x, uFloat128, uFloat128x, NoBasicType };
     217        static const char * basicTypeNames[];
     218        enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message
     219        static const char * complexTypeNames[];
     220        enum Signedness { Signed, Unsigned, NoSignedness };
     221        static const char * signednessNames[];
     222        enum Length { Short, Long, LongLong, NoLength };
     223        static const char * lengthNames[];
     224        enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };
     225        static const char * builtinTypeNames[];
     226
     227        static DeclarationNode * newStorageClass( Type::StorageClasses );
     228        static DeclarationNode * newFuncSpecifier( Type::FuncSpecifiers );
     229        static DeclarationNode * newTypeQualifier( Type::Qualifiers );
     230        static DeclarationNode * newBasicType( BasicType );
     231        static DeclarationNode * newComplexType( ComplexType );
     232        static DeclarationNode * newSignedNess( Signedness );
     233        static DeclarationNode * newLength( Length );
     234        static DeclarationNode * newBuiltinType( BuiltinType );
     235        static DeclarationNode * newForall( DeclarationNode * );
     236        static DeclarationNode * newFromTypedef( const std::string * );
     237        static DeclarationNode * newFromGlobalScope();
     238        static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );
     239        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
     240        static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
     241        static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr, EnumHiding hiding = EnumHiding::Visible );
     242        static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
     243        static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );
     244        static DeclarationNode * newEnumInLine( const std::string name );
     245        static DeclarationNode * newName( const std::string * );
     246        static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );
     247        static DeclarationNode * newTypeParam( TypeDecl::Kind, const std::string * );
     248        static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );
     249        static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
     250        static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );
     251        static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
     252        static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
     253        static DeclarationNode * newVarArray( DeclarationNode * qualifiers );
     254        static DeclarationNode * newBitfield( ExpressionNode * size );
     255        static DeclarationNode * newTuple( DeclarationNode * members );
     256        static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );
     257        static DeclarationNode * newVtableType( DeclarationNode * expr );
     258        static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
     259        static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement
     260        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
     261        static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );
     262
     263        DeclarationNode();
     264        ~DeclarationNode();
     265        DeclarationNode * clone() const override;
     266
     267        DeclarationNode * addQualifiers( DeclarationNode * );
     268        void checkQualifiers( const TypeData *, const TypeData * );
     269        void checkSpecifiers( DeclarationNode * );
     270        DeclarationNode * copySpecifiers( DeclarationNode * );
     271        DeclarationNode * addType( DeclarationNode * );
     272        DeclarationNode * addTypedef();
     273        DeclarationNode * addEnumBase( DeclarationNode * );
     274        DeclarationNode * addAssertions( DeclarationNode * );
     275        DeclarationNode * addName( std::string * );
     276        DeclarationNode * addAsmName( DeclarationNode * );
     277        DeclarationNode * addBitfield( ExpressionNode * size );
     278        DeclarationNode * addVarArgs();
     279        DeclarationNode * addFunctionBody( StatementNode * body, ExpressionNode * with = nullptr );
     280        DeclarationNode * addOldDeclList( DeclarationNode * list );
     281        DeclarationNode * setBase( TypeData * newType );
     282        DeclarationNode * copyAttribute( DeclarationNode * attr );
     283        DeclarationNode * addPointer( DeclarationNode * qualifiers );
     284        DeclarationNode * addArray( DeclarationNode * array );
     285        DeclarationNode * addNewPointer( DeclarationNode * pointer );
     286        DeclarationNode * addNewArray( DeclarationNode * array );
     287        DeclarationNode * addParamList( DeclarationNode * list );
     288        DeclarationNode * addIdList( DeclarationNode * list ); // old-style functions
     289        DeclarationNode * addInitializer( InitializerNode * init );
     290        DeclarationNode * addTypeInitializer( DeclarationNode * init );
     291
     292        DeclarationNode * cloneType( std::string * newName );
     293        DeclarationNode * cloneBaseType( DeclarationNode * newdecl );
     294
     295        DeclarationNode * appendList( DeclarationNode * node ) {
     296                return (DeclarationNode *)set_last( node );
     297        }
     298
     299        virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
     300        virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
     301
     302        Declaration * build() const;
     303        Type * buildType() const;
     304
     305        LinkageSpec::Spec get_linkage() const { return linkage; }
     306        DeclarationNode * extractAggregate() const;
     307        bool has_enumeratorValue() const { return (bool)enumeratorValue; }
     308        ExpressionNode * consume_enumeratorValue() const { return const_cast<DeclarationNode *>(this)->enumeratorValue.release(); }
     309
     310        bool get_extension() const { return extension; }
     311        DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }
     312
     313        bool get_inLine() const { return inLine; }
     314        DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }
     315
     316        DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
     317
     318        struct Variable_t {
     319//              const std::string * name;
     320                TypeDecl::Kind tyClass;
     321                DeclarationNode * assertions;
     322                DeclarationNode * initializer;
     323        };
     324        Variable_t variable;
     325
     326        struct Attr_t {
     327//              const std::string * name;
     328                ExpressionNode * expr;
     329                DeclarationNode * type;
     330        };
     331        Attr_t attr;
     332
     333        struct StaticAssert_t {
     334                ExpressionNode * condition;
     335                Expression * message;
     336        };
     337        StaticAssert_t assert;
     338
     339        BuiltinType builtin = NoBuiltinType;
     340
     341        TypeData * type = nullptr;
     342
     343        bool inLine = false;
     344        bool enumInLine = false;
     345        Type::FuncSpecifiers funcSpecs;
     346        Type::StorageClasses storageClasses;
     347
     348        ExpressionNode * bitfieldWidth = nullptr;
     349        std::unique_ptr<ExpressionNode> enumeratorValue;
     350        bool hasEllipsis = false;
     351        LinkageSpec::Spec linkage;
     352        Expression * asmName = nullptr;
     353        std::list< Attribute * > attributes;
     354        InitializerNode * initializer = nullptr;
     355        bool extension = false;
     356        std::string error;
     357        StatementNode * asmStmt = nullptr;
     358        StatementNode * directiveStmt = nullptr;
     359
     360        static UniqueName anonymous;
     361}; // DeclarationNode
     362
     363Type * buildType( TypeData * type );
     364
     365static inline Type * maybeMoveBuildType( const DeclarationNode * orig ) {
     366        Type * ret = orig ? orig->buildType() : nullptr;
     367        delete orig;
     368        return ret;
     369}
     370
     371//##############################################################################
     372
     373struct StatementNode final : public ParseNode {
     374        StatementNode() { stmt = nullptr; }
     375        StatementNode( Statement * stmt ) : stmt( stmt ) {}
     376        StatementNode( DeclarationNode * decl );
     377        virtual ~StatementNode() {}
     378
     379        virtual StatementNode * clone() const final { assert( false ); return nullptr; }
     380        Statement * build() const { return const_cast<StatementNode *>(this)->stmt.release(); }
     381
     382        virtual StatementNode * add_label( const std::string * name, DeclarationNode * attr = nullptr ) {
     383                stmt->get_labels().emplace_back( * name, nullptr, attr ? std::move( attr->attributes ) : std::list< Attribute * > {} );
     384                delete attr;
     385                delete name;
     386                return this;
     387        }
     388
     389        virtual StatementNode * append_last_case( StatementNode * );
     390
     391        virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {
     392                os << stmt.get() << std::endl;
     393        }
     394
     395        std::unique_ptr<Statement> stmt;
     396}; // StatementNode
     397
     398Statement * build_expr( ExpressionNode * ctl );
     399
     400struct CondCtl {
     401        CondCtl( DeclarationNode * decl, ExpressionNode * condition ) :
     402                init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}
     403
     404        StatementNode * init;
     405        ExpressionNode * condition;
     406};
     407
     408struct ForCtrl {
     409        ForCtrl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :
     410                init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {}
     411        ForCtrl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :
     412                init( new StatementNode( decl ) ), condition( condition ), change( change ) {}
     413
     414        StatementNode * init;
     415        ExpressionNode * condition;
     416        ExpressionNode * change;
     417};
     418
     419Expression * build_if_control( CondCtl * ctl, std::list< Statement * > & init );
     420Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ );
     421Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
     422Statement * build_case( ExpressionNode * ctl );
     423Statement * build_default();
     424Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
     425Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
     426Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );
     427Statement * build_branch( BranchStmt::Type kind );
     428Statement * build_branch( std::string * identifier, BranchStmt::Type kind );
     429Statement * build_computedgoto( ExpressionNode * ctl );
     430Statement * build_return( ExpressionNode * ctl );
     431Statement * build_throw( ExpressionNode * ctl );
     432Statement * build_resume( ExpressionNode * ctl );
     433Statement * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );
     434Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );
     435Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );
     436Statement * build_finally( StatementNode * stmt );
     437Statement * build_compound( StatementNode * first );
     438StatementNode * maybe_build_compound( StatementNode * first );
     439Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
     440Statement * build_directive( std::string * directive );
     441SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);
     442WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when );
     443WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when, WaitForStmt * existing );
     444WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );
     445WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
     446Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
     447Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );
     448
     449//##############################################################################
     450
     451template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >
     452void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > & outputList ) {
     453        SemanticErrorException errors;
     454        std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );
     455        const NodeType * cur = firstNode;
     456
     457        while ( cur ) {
     458                try {
     459                        SynTreeType * result = dynamic_cast< SynTreeType * >( maybeBuild< typename std::pointer_traits< decltype(cur->build())>::element_type >( cur ) );
     460                        if ( result ) {
     461                                result->location = cur->location;
     462                                * out++ = result;
     463                        } else {
     464                                SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );
     465                        } // if
     466                } catch( SemanticErrorException & e ) {
     467                        errors.append( e );
     468                } // try
     469                const ParseNode * temp = (cur->get_next());
     470                cur = dynamic_cast< const NodeType * >( temp ); // should not return nullptr
     471                if ( ! cur && temp ) {                                                  // non-homogeneous nodes ?
     472                        SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );
     473                } // if
     474        } // while
     475        if ( ! errors.isEmpty() ) {
     476                throw errors;
     477        } // if
     478}
     479
     480// in DeclarationNode.cc
     481void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList );
     482void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList );
     483void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList );
     484
     485template< typename SynTreeType, typename NodeType >
     486void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > & outputList ) {
     487        buildList( firstNode, outputList );
     488        delete firstNode;
     489}
     490
     491// in ParseNode.cc
    101492std::ostream & operator<<( std::ostream & out, const ParseNode * node );
    102493
  • src/Parser/ParserTypes.h

    r24d6572 r34b4268  
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 //
    7 // parser.hh --
    8 //
     6// 
     7// parser.hh -- 
     8// 
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Sep 22 08:58:10 2001
  • src/Parser/StatementNode.cc

    r24d6572 r34b4268  
    1010// Author           : Rodolfo G. Esteves
    1111// Created On       : Sat May 16 14:59:41 2015
    12 // Last Modified By : Andrew Beach
    13 // Last Modified On : Tue Apr 11 10:16:00 2023
    14 // Update Count     : 428
    15 //
    16 
    17 #include "StatementNode.h"
     12// Last Modified By : Peter A. Buhr
     13// Last Modified On : Wed Feb  2 20:29:30 2022
     14// Update Count     : 425
     15//
    1816
    1917#include <cassert>                 // for assert, strict_dynamic_cast, assertf
     18#include <list>                    // for list
    2019#include <memory>                  // for unique_ptr
    2120#include <string>                  // for string
    2221
    23 #include "AST/Label.hpp"           // for Label
    24 #include "AST/Stmt.hpp"            // for Stmt, AsmStmt, BranchStmt, CaseCla...
    2522#include "Common/SemanticError.h"  // for SemanticError
    2623#include "Common/utility.h"        // for maybeMoveBuild, maybeBuild
    27 #include "DeclarationNode.h"       // for DeclarationNode
    28 #include "ExpressionNode.h"        // for ExpressionNode
     24#include "ParseNode.h"             // for StatementNode, ExpressionNode, bui...
     25#include "SynTree/Expression.h"    // for Expression, ConstantExpr
     26#include "SynTree/Label.h"         // for Label, noLabels
     27#include "SynTree/Declaration.h"
     28#include "SynTree/Statement.h"     // for Statement, BranchStmt, CaseStmt
    2929#include "parserutility.h"         // for notZeroExpr
    3030
     
    3333using namespace std;
    3434
    35 // Some helpers for cases that really want a single node but check for lists.
    36 static const ast::Stmt * buildMoveSingle( StatementNode * node ) {
    37         std::vector<ast::ptr<ast::Stmt>> list;
    38         buildMoveList( node, list );
    39         assertf( list.size() == 1, "CFA Internal Error: Extra/Missing Nodes" );
    40         return list.front().release();
    41 }
    42 
    43 static const ast::Stmt * buildMoveOptional( StatementNode * node ) {
    44         std::vector<ast::ptr<ast::Stmt>> list;
    45         buildMoveList( node, list );
    46         assertf( list.size() <= 1, "CFA Internal Error: Extra Nodes" );
    47         return list.empty() ? nullptr : list.front().release();
    48 }
    4935
    5036StatementNode::StatementNode( DeclarationNode * decl ) {
     
    5238        DeclarationNode * agg = decl->extractAggregate();
    5339        if ( agg ) {
    54                 StatementNode * nextStmt = new StatementNode(
    55                         new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
     40                StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) );
    5641                set_next( nextStmt );
    5742                if ( decl->get_next() ) {
     
    6651                agg = decl;
    6752        } // if
    68         // Local copy to avoid accessing the pointer after it is moved from.
    69         CodeLocation declLocation = agg->location;
    70         stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) );
     53        stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) );
    7154} // StatementNode::StatementNode
    7255
    73 StatementNode * StatementNode::add_label(
    74                 const CodeLocation & location,
    75                 const std::string * name,
    76                 DeclarationNode * attr ) {
    77         stmt->labels.emplace_back( location,
    78                 *name,
    79                 attr ? std::move( attr->attributes )
    80                         : std::vector<ast::ptr<ast::Attribute>>{} );
    81         delete attr;
    82         delete name;
    83         return this;
    84 }
    85 
    86 ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) {
    87         ClauseNode * prev = this;
     56StatementNode * StatementNode::append_last_case( StatementNode * stmt ) {
     57        StatementNode * prev = this;
    8858        // find end of list and maintain previous pointer
    89         for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) {
    90                 ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr);
    91                 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
     59        for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {
     60                StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);
     61                assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );
    9262                prev = curr;
    9363        } // for
    94         ClauseNode * node = dynamic_cast< ClauseNode * >(prev);
    9564        // convert from StatementNode list to Statement list
    96         std::vector<ast::ptr<ast::Stmt>> stmts;
     65        StatementNode * node = dynamic_cast< StatementNode * >(prev);
     66        list< Statement * > stmts;
    9767        buildMoveList( stmt, stmts );
    9868        // splice any new Statements to end of current Statements
    99         auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() );
    100         for ( auto const & newStmt : stmts ) {
    101                 caseStmt->stmts.emplace_back( newStmt );
    102         }
    103         stmts.clear();
     69        CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get());
     70        caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
    10471        return this;
    105 } // ClauseNode::append_last_case
    106 
    107 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) {
    108         if ( ast::Expr * e = maybeMoveBuild( ctl ) ) {
    109                 return new ast::ExprStmt( location, e );
    110         } else {
    111                 return new ast::NullStmt( location );
    112         }
     72} // StatementNode::append_last_case
     73
     74Statement * build_expr( ExpressionNode * ctl ) {
     75        Expression * e = maybeMoveBuild< Expression >( ctl );
     76
     77        if ( e ) return new ExprStmt( e );
     78        else return new NullStmt();
    11379} // build_expr
    11480
    115 static ast::Expr * build_if_control( CondCtl * ctl,
    116                 std::vector<ast::ptr<ast::Stmt>> & inits ) {
    117         assert( inits.empty() );
    118         if ( nullptr != ctl->init ) {
    119                 buildMoveList( ctl->init, inits );
    120         } // if
    121 
    122         ast::Expr * cond = nullptr;
     81Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) {
     82        if ( ctl->init != 0 ) {
     83                buildMoveList( ctl->init, init );
     84        } // if
     85
     86        Expression * cond = nullptr;
    12387        if ( ctl->condition ) {
    12488                // compare the provided condition against 0
    125                 cond = notZeroExpr( maybeMoveBuild( ctl->condition ) );
     89                cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
    12690        } else {
    127                 for ( ast::ptr<ast::Stmt> & stmt : inits ) {
     91                for ( Statement * stmt : init ) {
    12892                        // build the && of all of the declared variables compared against 0
    129                         auto declStmt = stmt.strict_as<ast::DeclStmt>();
    130                         auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
    131                         ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) );
    132                         cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze;
     93                        DeclStmt * declStmt = strict_dynamic_cast< DeclStmt * >( stmt );
     94                        DeclarationWithType * dwt = strict_dynamic_cast< DeclarationWithType * >( declStmt->decl );
     95                        Expression * nze = notZeroExpr( new VariableExpr( dwt ) );
     96                        cond = cond ? new LogicalExpr( cond, nze, true ) : nze;
    13397                }
    13498        }
     
    137101} // build_if_control
    138102
    139 ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
    140         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
    141         ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    142 
    143         ast::Stmt const * astthen = buildMoveSingle( then );
    144         ast::Stmt const * astelse = buildMoveOptional( else_ );
    145 
    146         return new ast::IfStmt( location, astcond, astthen, astelse,
    147                 std::move( astinit )
    148         );
     103Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
     104        list< Statement * > astinit;                                            // maybe empty
     105        Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
     106
     107        Statement * astthen, * astelse = nullptr;
     108        list< Statement * > aststmt;
     109        buildMoveList< Statement, StatementNode >( then, aststmt );
     110        assert( aststmt.size() == 1 );
     111        astthen = aststmt.front();
     112
     113        if ( else_ ) {
     114                list< Statement * > aststmt;
     115                buildMoveList< Statement, StatementNode >( else_, aststmt );
     116                assert( aststmt.size() == 1 );
     117                astelse = aststmt.front();
     118        } // if
     119
     120        return new IfStmt( astcond, astthen, astelse, astinit );
    149121} // build_if
    150122
    151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) {
    152         std::vector<ast::ptr<ast::CaseClause>> aststmt;
    153         buildMoveList( stmt, aststmt );
    154         // If it is not a switch it is a choose statement.
    155         if ( ! isSwitch ) {
    156                 for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) {
    157                         // Code after "case" is the end of case list.
    158                         if ( !stmt->stmts.empty() ) {
    159                                 auto mutStmt = ast::mutate( stmt.get() );
    160                                 // I believe the stmts are actually always one block.
    161                                 auto stmts = mutStmt->stmts.front().get_and_mutate();
    162                                 auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts );
    163                                 block->kids.push_back( new ast::BranchStmt( block->location,
    164                                         ast::BranchStmt::Break,
    165                                         ast::Label( block->location ) ) );
    166                                 stmt = mutStmt;
     123Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
     124        list< Statement * > aststmt;
     125        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     126        if ( ! isSwitch ) {                                                                     // choose statement
     127                for ( Statement * stmt : aststmt ) {
     128                        CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
     129                        if ( ! caseStmt->stmts.empty() ) {                      // code after "case" => end of case list
     130                                CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
     131                                block->kids.push_back( new BranchStmt( "", BranchStmt::Break ) );
    167132                        } // if
    168133                } // for
    169134        } // if
    170135        // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
    171         return new ast::SwitchStmt( location,
    172                 maybeMoveBuild( ctl ), std::move( aststmt ) );
     136        return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt );
    173137} // build_switch
    174138
    175 ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) {
    176         // stmt starts empty and then added to
    177         auto expr = maybeMoveBuild( ctl );
    178         return new ast::CaseClause( location, expr, {} );
     139Statement * build_case( ExpressionNode * ctl ) {
     140        return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to
    179141} // build_case
    180142
    181 ast::CaseClause * build_default( const CodeLocation & location ) {
    182         // stmt starts empty and then added to
    183         return new ast::CaseClause( location, nullptr, {} );
     143Statement * build_default() {
     144        return new CaseStmt( nullptr, {}, true );                       // stmt starts empty and then added to
    184145} // build_default
    185146
    186 ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
    187         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
    188         ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    189 
    190         return new ast::WhileDoStmt( location,
    191                 astcond,
    192                 buildMoveSingle( stmt ),
    193                 buildMoveOptional( else_ ),
    194                 std::move( astinit ),
    195                 ast::While
    196         );
     147Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
     148        list< Statement * > astinit;                                            // maybe empty
     149        Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
     150
     151        list< Statement * > aststmt;                                            // loop body, compound created if empty
     152        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     153        assert( aststmt.size() == 1 );
     154
     155        list< Statement * > astelse;                                            // else clause, maybe empty
     156        buildMoveList< Statement, StatementNode >( else_, astelse );
     157
     158        return new WhileDoStmt( astcond, aststmt.front(), astelse.front(), astinit, false );
    197159} // build_while
    198160
    199 ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
     161Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
     162        list< Statement * > aststmt;                                            // loop body, compound created if empty
     163        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     164        assert( aststmt.size() == 1 );                                          // compound created if empty
     165
     166        list< Statement * > astelse;                                            // else clause, maybe empty
     167        buildMoveList< Statement, StatementNode >( else_, astelse );
     168
    200169        // do-while cannot have declarations in the contitional, so init is always empty
    201         return new ast::WhileDoStmt( location,
    202                 notZeroExpr( maybeMoveBuild( ctl ) ),
    203                 buildMoveSingle( stmt ),
    204                 buildMoveOptional( else_ ),
    205                 {},
    206                 ast::DoWhile
    207         );
     170        return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true );
    208171} // build_do_while
    209172
    210 ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
    211         std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
     173Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
     174        list< Statement * > astinit;                                            // maybe empty
    212175        buildMoveList( forctl->init, astinit );
    213176
    214         ast::Expr * astcond = nullptr;                                          // maybe empty
    215         astcond = notZeroExpr( maybeMoveBuild( forctl->condition ) );
    216 
    217         ast::Expr * astincr = nullptr;                                          // maybe empty
    218         astincr = maybeMoveBuild( forctl->change );
     177        Expression * astcond = nullptr;                                         // maybe empty
     178        astcond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) );
     179
     180        Expression * astincr = nullptr;                                         // maybe empty
     181        astincr = maybeMoveBuild< Expression >(forctl->change);
    219182        delete forctl;
    220183
    221         return new ast::ForStmt( location,
    222                 std::move( astinit ),
    223                 astcond,
    224                 astincr,
    225                 buildMoveSingle( stmt ),
    226                 buildMoveOptional( else_ )
    227         );
     184        list< Statement * > aststmt;                                            // loop body, compound created if empty
     185        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     186        assert( aststmt.size() == 1 );
     187
     188        list< Statement * > astelse;                                            // else clause, maybe empty
     189        buildMoveList< Statement, StatementNode >( else_, astelse );
     190
     191        return new ForStmt( astinit, astcond, astincr, aststmt.front(), astelse.front() );
    228192} // build_for
    229193
    230 ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) {
    231         return new ast::BranchStmt( location,
    232                 kind,
    233                 ast::Label( location )
    234         );
     194Statement * build_branch( BranchStmt::Type kind ) {
     195        Statement * ret = new BranchStmt( "", kind );
     196        return ret;
    235197} // build_branch
    236198
    237 ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) {
    238         ast::Stmt * ret = new ast::BranchStmt( location,
    239                 kind,
    240                 ast::Label( location, *identifier )
    241         );
     199Statement * build_branch( string * identifier, BranchStmt::Type kind ) {
     200        Statement * ret = new BranchStmt( * identifier, kind );
    242201        delete identifier;                                                                      // allocated by lexer
    243202        return ret;
    244203} // build_branch
    245204
    246 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) {
    247         ast::Expr * expr = maybeMoveBuild( ctl );
    248         return new ast::BranchStmt( expr->location, expr );
     205Statement * build_computedgoto( ExpressionNode * ctl ) {
     206        return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
    249207} // build_computedgoto
    250208
    251 ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) {
    252         std::vector<ast::ptr<ast::Expr>> exps;
     209Statement * build_return( ExpressionNode * ctl ) {
     210        list< Expression * > exps;
    253211        buildMoveList( ctl, exps );
    254         return new ast::ReturnStmt( location,
    255                 exps.size() > 0 ? exps.back().release() : nullptr
    256         );
     212        return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
    257213} // build_return
    258214
    259 static ast::Stmt * build_throw_stmt(
    260                 const CodeLocation & location,
    261                 ExpressionNode * ctl,
    262                 ast::ExceptionKind kind ) {
    263         std::vector<ast::ptr<ast::Expr>> exps;
     215Statement * build_throw( ExpressionNode * ctl ) {
     216        list< Expression * > exps;
    264217        buildMoveList( ctl, exps );
    265218        assertf( exps.size() < 2, "CFA internal error: leaking memory" );
    266         return new ast::ThrowStmt( location,
    267                 kind,
    268                 !exps.empty() ? exps.back().release() : nullptr,
    269                 (ast::Expr *)nullptr
    270         );
    271 }
    272 
    273 ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) {
    274         return build_throw_stmt( loc, ctl, ast::Terminate );
     219        return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
    275220} // build_throw
    276221
    277 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) {
    278         return build_throw_stmt( loc, ctl, ast::Resume );
     222Statement * build_resume( ExpressionNode * ctl ) {
     223        list< Expression * > exps;
     224        buildMoveList( ctl, exps );
     225        assertf( exps.size() < 2, "CFA internal error: leaking memory" );
     226        return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
    279227} // build_resume
    280228
    281 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
     229Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
    282230        (void)ctl;
    283231        (void)target;
     
    285233} // build_resume_at
    286234
    287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {
    288         std::vector<ast::ptr<ast::CatchClause>> aststmt;
    289         buildMoveList( catch_, aststmt );
    290         ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
    291         ast::FinallyClause * finallyBlock = nullptr;
    292         if ( finally_ ) {
    293                 finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() );
     235Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
     236        list< CatchStmt * > aststmt;
     237        buildMoveList< CatchStmt, StatementNode >( catch_, aststmt );
     238        CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_));
     239        FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_) );
     240        return new TryStmt( tryBlock, aststmt, finallyBlock );
     241} // build_try
     242
     243Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
     244        list< Statement * > aststmt;
     245        buildMoveList< Statement, StatementNode >( body, aststmt );
     246        assert( aststmt.size() == 1 );
     247        return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), aststmt.front() );
     248} // build_catch
     249
     250Statement * build_finally( StatementNode * stmt ) {
     251        list< Statement * > aststmt;
     252        buildMoveList< Statement, StatementNode >( stmt, aststmt );
     253        assert( aststmt.size() == 1 );
     254        return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) );
     255} // build_finally
     256
     257SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) {
     258        auto node = new SuspendStmt();
     259
     260        node->type = type;
     261
     262        list< Statement * > stmts;
     263        buildMoveList< Statement, StatementNode >( then, stmts );
     264        if(!stmts.empty()) {
     265                assert( stmts.size() == 1 );
     266                node->then = dynamic_cast< CompoundStmt * >( stmts.front() );
    294267        }
    295         return new ast::TryStmt( location,
    296                 tryBlock,
    297                 std::move( aststmt ),
    298                 finallyBlock
    299         );
    300 } // build_try
    301 
    302 ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
    303         return new ast::CatchClause( location,
    304                 kind,
    305                 maybeMoveBuild( decl ),
    306                 maybeMoveBuild( cond ),
    307                 buildMoveSingle( body )
    308         );
    309 } // build_catch
    310 
    311 ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) {
    312         return new ast::FinallyClause( location,
    313                 strict_dynamic_cast<const ast::CompoundStmt *>(
    314                         buildMoveSingle( stmt )
    315                 )
    316         );
    317 } // build_finally
    318 
    319 ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) {
    320         return new ast::SuspendStmt( location,
    321                 strict_dynamic_cast<const ast::CompoundStmt *, nullptr>(
    322                         buildMoveOptional( then )
    323                 ),
    324                 kind
    325         );
    326 } // build_suspend
    327 
    328 ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    329         auto clause = new ast::WaitForClause( location );
    330         clause->target = maybeBuild( targetExpr );
    331         clause->stmt = maybeMoveBuild( stmt );
    332         clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     268
     269        return node;
     270}
     271
     272WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
     273        auto node = new WaitForStmt();
     274
     275        WaitForStmt::Target target;
     276        target.function = maybeBuild<Expression>( targetExpr );
    333277
    334278        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
    335279        targetExpr->set_next( nullptr );
    336         buildMoveList( next, clause->target_args );
     280        buildMoveList< Expression >( next, target.arguments );
    337281
    338282        delete targetExpr;
    339283
    340         existing->clauses.insert( existing->clauses.begin(), clause );
    341 
    342         return existing;
     284        node->clauses.push_back( WaitForStmt::Clause{
     285                target,
     286                maybeMoveBuild<Statement >( stmt ),
     287                notZeroExpr( maybeMoveBuild<Expression>( when ) )
     288        });
     289
     290        return node;
    343291} // build_waitfor
    344292
    345 ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
    346         existing->else_stmt = maybeMoveBuild( stmt );
    347         existing->else_cond = notZeroExpr( maybeMoveBuild( when ) );
    348 
    349         (void)location;
    350         return existing;
    351 } // build_waitfor_else
    352 
    353 ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
    354         existing->timeout_time = maybeMoveBuild( timeout );
    355         existing->timeout_stmt = maybeMoveBuild( stmt );
    356         existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ) );
    357 
    358         (void)location;
    359         return existing;
     293WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) {
     294        WaitForStmt::Target target;
     295        target.function = maybeBuild<Expression>( targetExpr );
     296
     297        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
     298        targetExpr->set_next( nullptr );
     299        buildMoveList< Expression >( next, target.arguments );
     300
     301        delete targetExpr;
     302
     303        node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{
     304                std::move( target ),
     305                maybeMoveBuild<Statement >( stmt ),
     306                notZeroExpr( maybeMoveBuild<Expression>( when ) )
     307        });
     308
     309        return node;
     310} // build_waitfor
     311
     312WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) {
     313        auto node = new WaitForStmt();
     314
     315        if( timeout ) {
     316                node->timeout.time      = maybeMoveBuild<Expression>( timeout );
     317                node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
     318                node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
     319        } else {
     320                node->orelse.statement  = maybeMoveBuild<Statement >( stmt );
     321                node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( when ) );
     322        } // if
     323
     324        return node;
    360325} // build_waitfor_timeout
    361326
    362 ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    363     ast::WhenClause * clause = new ast::WhenClause( loc );
    364     clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    365     clause->stmt = maybeMoveBuild( stmt );
    366     clause->target = maybeMoveBuild( targetExpr );
    367     return new ast::WaitUntilStmt::ClauseNode( clause );
    368 }
    369 ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) {
    370     ast::WhenClause * clause = new ast::WhenClause( loc );
    371     clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    372     clause->stmt = maybeMoveBuild( stmt );
    373     return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause );
    374 }
    375 ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
    376     ast::WhenClause * clause = new ast::WhenClause( loc );
    377     clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    378     clause->stmt = maybeMoveBuild( stmt );
    379     clause->target = maybeMoveBuild( timeout );
    380     return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::TIMEOUT, clause );
    381 }
    382 
    383 ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) {
    384     ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc );
    385     retStmt->predicateTree = root;
    386    
    387     // iterative tree traversal
    388     std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal
    389     ast::WaitUntilStmt::ClauseNode * currNode = nullptr;
    390     ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr;
    391     ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout
    392     nodeStack.push_back(root);
    393 
    394     do {
    395         currNode = nodeStack.back();
    396         nodeStack.pop_back(); // remove node since it will be processed
    397 
    398         switch (currNode->op) {
    399             case ast::WaitUntilStmt::ClauseNode::LEAF:
    400                 retStmt->clauses.push_back(currNode->leaf);
    401                 break;
    402             case ast::WaitUntilStmt::ClauseNode::ELSE:
    403                 retStmt->else_stmt = currNode->leaf->stmt
    404                     ? ast::deepCopy( currNode->leaf->stmt )
    405                     : nullptr;
    406                
    407                 retStmt->else_cond = currNode->leaf->when_cond
    408                     ? ast::deepCopy( currNode->leaf->when_cond )
    409                     : nullptr;
    410 
    411                 delete currNode->leaf;
    412                 break;
    413             case ast::WaitUntilStmt::ClauseNode::TIMEOUT:
    414                 retStmt->timeout_time = currNode->leaf->target
    415                     ? ast::deepCopy( currNode->leaf->target )
    416                     : nullptr;
    417                 retStmt->timeout_stmt = currNode->leaf->stmt
    418                     ? ast::deepCopy( currNode->leaf->stmt )
    419                     : nullptr;
    420                 retStmt->timeout_cond = currNode->leaf->when_cond
    421                     ? ast::deepCopy( currNode->leaf->when_cond )
    422                     : nullptr;
    423 
    424                 delete currNode->leaf;
    425                 break;
    426             default:
    427                 nodeStack.push_back( currNode->right ); // process right after left
    428                 nodeStack.push_back( currNode->left );
    429 
    430                 // Cut else/timeout out of the tree
    431                 if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) {
    432                     if ( lastInternalNode )
    433                         lastInternalNode->right = currNode->left;
    434                     else    // if not set then root is LEFT_OR
    435                         retStmt->predicateTree = currNode->left;
    436    
    437                     currNode->left = nullptr;
    438                     cleanup = currNode;
    439                 }
    440                
    441                 lastInternalNode = currNode;
    442                 break;
    443         }
    444     } while ( !nodeStack.empty() );
    445 
    446     if ( cleanup ) delete cleanup;
    447 
    448     return retStmt;
    449 }
    450 
    451 ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
    452         std::vector<ast::ptr<ast::Expr>> e;
     327WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_, ExpressionNode * else_when ) {
     328        auto node = new WaitForStmt();
     329
     330        node->timeout.time      = maybeMoveBuild<Expression>( timeout );
     331        node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
     332        node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
     333
     334        node->orelse.statement  = maybeMoveBuild<Statement >( else_ );
     335        node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( else_when ) );
     336
     337        return node;
     338} // build_waitfor_timeout
     339
     340Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
     341        list< Expression * > e;
    453342        buildMoveList( exprs, e );
    454         ast::Stmt * s = maybeMoveBuild( stmt );
    455         return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );
     343        Statement * s = maybeMoveBuild<Statement>( stmt );
     344        return new DeclStmt( new WithStmt( e, s ) );
    456345} // build_with
    457346
    458 ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
    459         auto cs = new ast::CompoundStmt( location );
    460         buildMoveList( first, cs->kids );
     347Statement * build_compound( StatementNode * first ) {
     348        CompoundStmt * cs = new CompoundStmt();
     349        buildMoveList( first, cs->get_kids() );
    461350        return cs;
    462351} // build_compound
     
    466355// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
    467356// conical form for code generation.
    468 StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
     357StatementNode * maybe_build_compound( StatementNode * first ) {
    469358        // Optimization: if the control-structure statement is a compound statement, do not wrap it.
    470359        // e.g., if (...) {...} do not wrap the existing compound statement.
    471         if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
    472                 return new StatementNode( build_compound( location, first ) );
     360        if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
     361                CompoundStmt * cs = new CompoundStmt();
     362                buildMoveList( first, cs->get_kids() );
     363                return new StatementNode( cs );
    473364        } // if
    474365        return first;
     
    476367
    477368// Question
    478 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
    479         std::vector<ast::ptr<ast::Expr>> out, in;
    480         std::vector<ast::ptr<ast::ConstantExpr>> clob;
     369Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
     370        list< Expression * > out, in;
     371        list< ConstantExpr * > clob;
    481372
    482373        buildMoveList( output, out );
    483374        buildMoveList( input, in );
    484375        buildMoveList( clobber, clob );
    485         return new ast::AsmStmt( location,
    486                 is_volatile,
    487                 maybeMoveBuild( instruction ),
    488                 std::move( out ),
    489                 std::move( in ),
    490                 std::move( clob ),
    491                 gotolabels ? gotolabels->labels : std::vector<ast::Label>()
    492         );
     376        return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
    493377} // build_asm
    494378
    495 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
    496         auto stmt = new ast::DirectiveStmt( location, *directive );
    497         delete directive;
    498         return stmt;
     379Statement * build_directive( string * directive ) {
     380        return new DirectiveStmt( *directive );
    499381} // build_directive
    500382
    501 ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
    502         std::vector<ast::ptr<ast::Expr>> expList;
     383Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
     384        list< Expression * > expList;
    503385        buildMoveList( exprs, expList );
    504         ast::Stmt * body = maybeMoveBuild( stmt );
    505         return new ast::MutexStmt( location, body, std::move( expList ) );
     386        Statement * body = maybeMoveBuild<Statement>( stmt );
     387        return new MutexStmt( body, expList );
    506388} // build_mutex
    507389
  • src/Parser/TypeData.cc

    r24d6572 r34b4268  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 15:12:51 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr  4 13:39:00 2023
    13 // Update Count     : 680
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue May 10 22:36:52 2022
     13// Update Count     : 677
    1414//
    15 
    16 #include "TypeData.h"
    1715
    1816#include <cassert>                 // for assert
    1917#include <ostream>                 // for operator<<, ostream, basic_ostream
    2018
    21 #include "AST/Decl.hpp"            // for AggregateDecl, ObjectDecl, TypeDe...
    22 #include "AST/Init.hpp"            // for SingleInit, ListInit
    23 #include "AST/Print.hpp"           // for print
    2419#include "Common/SemanticError.h"  // for SemanticError
    25 #include "Common/utility.h"        // for splice, spliceBegin
    26 #include "Parser/ExpressionNode.h" // for ExpressionNode
    27 #include "Parser/StatementNode.h"  // for StatementNode
     20#include "Common/utility.h"        // for maybeClone, maybeBuild, maybeMoveB...
     21#include "Parser/ParseNode.h"      // for DeclarationNode, ExpressionNode
     22#include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, FunctionDecl
     23#include "SynTree/Expression.h"    // for Expression, ConstantExpr (ptr only)
     24#include "SynTree/Initializer.h"   // for SingleInit, Initializer (ptr only)
     25#include "SynTree/Statement.h"     // for CompoundStmt, Statement
     26#include "SynTree/Type.h"          // for BasicType, Type, Type::ForallList
     27#include "TypeData.h"
    2828
    2929class Attribute;
     
    3333TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {
    3434        switch ( kind ) {
    35         case Unknown:
    36         case Pointer:
    37         case Reference:
    38         case EnumConstant:
    39         case GlobalScope:
    40         case Basic:
    41                 // No unique data to initialize.
    42                 break;
    43         case Array:
     35          case Unknown:
     36          case Pointer:
     37          case Reference:
     38          case EnumConstant:
     39          case GlobalScope:
     40                // nothing else to initialize
     41                break;
     42          case Basic:
     43                // basic = new Basic_t;
     44                break;
     45          case Array:
     46                // array = new Array_t;
    4447                array.dimension = nullptr;
    4548                array.isVarLen = false;
    4649                array.isStatic = false;
    4750                break;
    48         case Function:
     51          case Function:
     52                // function = new Function_t;
    4953                function.params = nullptr;
    5054                function.idList = nullptr;
     
    5357                function.withExprs = nullptr;
    5458                break;
    55         case Enum:
     59                // Enum is an Aggregate, so both structures are initialized together.
     60          case Enum:
     61                // enumeration = new Enumeration_t;
    5662                enumeration.name = nullptr;
    5763                enumeration.constants = nullptr;
     
    5965                enumeration.anon = false;
    6066                break;
    61         case Aggregate:
    62                 aggregate.kind = ast::AggregateDecl::NoAggregate;
     67          case Aggregate:
     68                // aggregate = new Aggregate_t;
     69                aggregate.kind = AggregateDecl::NoAggregate;
    6370                aggregate.name = nullptr;
    6471                aggregate.params = nullptr;
     
    7077                aggregate.anon = false;
    7178                break;
    72         case AggregateInst:
     79          case AggregateInst:
     80                // aggInst = new AggInst_t;
    7381                aggInst.aggregate = nullptr;
    7482                aggInst.params = nullptr;
    7583                aggInst.hoistType = false;
    7684                break;
    77         case Symbolic:
    78         case SymbolicInst:
     85          case Symbolic:
     86          case SymbolicInst:
     87                // symbolic = new Symbolic_t;
    7988                symbolic.name = nullptr;
    8089                symbolic.params = nullptr;
     
    8291                symbolic.assertions = nullptr;
    8392                break;
    84         case Tuple:
     93          case Tuple:
     94                // tuple = new Tuple_t;
    8595                tuple = nullptr;
    8696                break;
    87         case Typeof:
    88         case Basetypeof:
     97          case Typeof:
     98          case Basetypeof:
     99                // typeexpr = new Typeof_t;
    89100                typeexpr = nullptr;
    90101                break;
    91         case Vtable:
    92         case Builtin:
    93                 // No unique data to initialize.
    94                 break;
    95         case Qualified:
     102          case Vtable:
     103                break;
     104          case Builtin:
     105                // builtin = new Builtin_t;
     106                case Qualified:
    96107                qualified.parent = nullptr;
    97108                qualified.child = nullptr;
     
    106117
    107118        switch ( kind ) {
    108         case Unknown:
    109         case Pointer:
    110         case Reference:
    111         case EnumConstant:
    112         case GlobalScope:
    113         case Basic:
    114                 // No unique data to deconstruct.
    115                 break;
    116         case Array:
     119          case Unknown:
     120          case Pointer:
     121          case Reference:
     122          case EnumConstant:
     123          case GlobalScope:
     124                // nothing to destroy
     125                break;
     126          case Basic:
     127                // delete basic;
     128                break;
     129          case Array:
    117130                delete array.dimension;
    118                 break;
    119         case Function:
     131                // delete array;
     132                break;
     133          case Function:
    120134                delete function.params;
    121135                delete function.idList;
     
    123137                delete function.body;
    124138                delete function.withExprs;
    125                 break;
    126         case Aggregate:
     139                // delete function;
     140                break;
     141          case Aggregate:
    127142                delete aggregate.name;
    128143                delete aggregate.params;
    129144                delete aggregate.actuals;
    130145                delete aggregate.fields;
    131                 break;
    132         case AggregateInst:
     146                // delete aggregate;
     147                break;
     148          case AggregateInst:
    133149                delete aggInst.aggregate;
    134150                delete aggInst.params;
    135                 break;
    136         case Enum:
     151                // delete aggInst;
     152                break;
     153          case Enum:
    137154                delete enumeration.name;
    138155                delete enumeration.constants;
    139                 break;
    140         case Symbolic:
    141         case SymbolicInst:
     156                // delete enumeration;
     157                break;
     158          case Symbolic:
     159          case SymbolicInst:
    142160                delete symbolic.name;
    143161                delete symbolic.params;
    144162                delete symbolic.actuals;
    145163                delete symbolic.assertions;
    146                 break;
    147         case Tuple:
     164                // delete symbolic;
     165                break;
     166          case Tuple:
     167                // delete tuple->members;
    148168                delete tuple;
    149169                break;
    150         case Typeof:
    151         case Basetypeof:
     170          case Typeof:
     171          case Basetypeof:
     172                // delete typeexpr->expr;
    152173                delete typeexpr;
    153174                break;
    154         case Vtable:
    155         case Builtin:
    156                 // No unique data to deconstruct.
    157                 break;
    158         case Qualified:
     175          case Vtable:
     176                break;
     177          case Builtin:
     178                // delete builtin;
     179                break;
     180          case Qualified:
    159181                delete qualified.parent;
    160182                delete qualified.child;
    161                 break;
    162183        } // switch
    163184} // TypeData::~TypeData
     
    171192
    172193        switch ( kind ) {
    173         case Unknown:
    174         case EnumConstant:
    175         case Pointer:
    176         case Reference:
    177         case GlobalScope:
     194          case Unknown:
     195          case EnumConstant:
     196          case Pointer:
     197          case Reference:
     198          case GlobalScope:
    178199                // nothing else to copy
    179200                break;
    180         case Basic:
     201          case Basic:
    181202                newtype->basictype = basictype;
    182203                newtype->complextype = complextype;
     
    184205                newtype->length = length;
    185206                break;
    186         case Array:
     207          case Array:
    187208                newtype->array.dimension = maybeClone( array.dimension );
    188209                newtype->array.isVarLen = array.isVarLen;
    189210                newtype->array.isStatic = array.isStatic;
    190211                break;
    191         case Function:
     212          case Function:
    192213                newtype->function.params = maybeClone( function.params );
    193214                newtype->function.idList = maybeClone( function.idList );
     
    196217                newtype->function.withExprs = maybeClone( function.withExprs );
    197218                break;
    198         case Aggregate:
     219          case Aggregate:
    199220                newtype->aggregate.kind = aggregate.kind;
    200221                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
     
    207228                newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;
    208229                break;
    209         case AggregateInst:
     230          case AggregateInst:
    210231                newtype->aggInst.aggregate = maybeClone( aggInst.aggregate );
    211232                newtype->aggInst.params = maybeClone( aggInst.params );
    212233                newtype->aggInst.hoistType = aggInst.hoistType;
    213234                break;
    214         case Enum:
     235          case Enum:
    215236                newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr;
    216237                newtype->enumeration.constants = maybeClone( enumeration.constants );
     
    218239                newtype->enumeration.anon = enumeration.anon;
    219240                break;
    220         case Symbolic:
    221         case SymbolicInst:
     241          case Symbolic:
     242          case SymbolicInst:
    222243                newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr;
    223244                newtype->symbolic.params = maybeClone( symbolic.params );
     
    226247                newtype->symbolic.isTypedef = symbolic.isTypedef;
    227248                break;
    228         case Tuple:
     249          case Tuple:
    229250                newtype->tuple = maybeClone( tuple );
    230251                break;
    231         case Typeof:
    232         case Basetypeof:
     252          case Typeof:
     253          case Basetypeof:
    233254                newtype->typeexpr = maybeClone( typeexpr );
    234255                break;
    235         case Vtable:
    236                 break;
    237         case Builtin:
     256          case Vtable:
     257                break;
     258          case Builtin:
    238259                assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One );
    239260                newtype->builtintype = builtintype;
    240261                break;
    241         case Qualified:
     262                case Qualified:
    242263                newtype->qualified.parent = maybeClone( qualified.parent );
    243264                newtype->qualified.child = maybeClone( qualified.child );
     
    249270
    250271void TypeData::print( ostream &os, int indent ) const {
    251         ast::print( os, qualifiers );
     272        for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) {
     273                if ( qualifiers[i] ) os << Type::QualifiersNames[ i ] << ' ';
     274        } // for
    252275
    253276        if ( forall ) {
     
    257280
    258281        switch ( kind ) {
    259         case Basic:
     282          case Basic:
    260283                if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " ";
    261284                if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " ";
     
    263286                if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " ";
    264287                break;
    265         case Pointer:
     288          case Pointer:
    266289                os << "pointer ";
    267290                if ( base ) {
     
    270293                } // if
    271294                break;
    272         case Reference:
     295          case Reference:
    273296                os << "reference ";
    274297                if ( base ) {
     
    277300                } // if
    278301                break;
    279         case Array:
     302          case Array:
    280303                if ( array.isStatic ) {
    281304                        os << "static ";
     
    293316                } // if
    294317                break;
    295         case Function:
     318          case Function:
    296319                os << "function" << endl;
    297320                if ( function.params ) {
     
    321344                } // if
    322345                break;
    323         case Aggregate:
    324                 os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
     346          case Aggregate:
     347                os << AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
    325348                if ( aggregate.params ) {
    326349                        os << string( indent + 2, ' ' ) << "with type parameters" << endl;
     
    339362                } // if
    340363                break;
    341         case AggregateInst:
     364          case AggregateInst:
    342365                if ( aggInst.aggregate ) {
    343366                        os << "instance of " ;
     
    351374                } // if
    352375                break;
    353         case Enum:
    354                 os << "enumeration " << *enumeration.name << endl;;
     376          case Enum:
     377                os << "enumeration ";
    355378                if ( enumeration.constants ) {
    356379                        os << "with constants" << endl;
     
    365388                } // if
    366389                break;
    367         case EnumConstant:
     390          case EnumConstant:
    368391                os << "enumeration constant ";
    369392                break;
    370         case Symbolic:
     393          case Symbolic:
    371394                if ( symbolic.isTypedef ) {
    372395                        os << "typedef definition ";
     
    388411                } // if
    389412                break;
    390         case SymbolicInst:
     413          case SymbolicInst:
    391414                os << *symbolic.name;
    392415                if ( symbolic.actuals ) {
     
    396419                } // if
    397420                break;
    398         case Tuple:
     421          case Tuple:
    399422                os << "tuple ";
    400423                if ( tuple ) {
     
    403426                } // if
    404427                break;
    405         case Basetypeof:
     428          case Basetypeof:
    406429                os << "base-";
    407430                #if defined(__GNUC__) && __GNUC__ >= 7
     
    409432                #endif
    410433                // FALL THROUGH
    411         case Typeof:
     434          case Typeof:
    412435                os << "type-of expression ";
    413436                if ( typeexpr ) {
     
    415438                } // if
    416439                break;
    417         case Vtable:
     440          case Vtable:
    418441                os << "vtable";
    419442                break;
    420         case Builtin:
     443          case Builtin:
    421444                os << DeclarationNode::builtinTypeNames[builtintype];
    422445                break;
    423         case GlobalScope:
    424                 break;
    425         case Qualified:
     446          case GlobalScope:
     447                break;
     448          case Qualified:
    426449                qualified.parent->print( os );
    427450                os << ".";
    428451                qualified.child->print( os );
    429452                break;
    430         case Unknown:
     453          case Unknown:
    431454                os << "entity of unknown type ";
    432455                break;
    433         default:
     456          default:
    434457                os << "internal error: TypeData::print " << kind << endl;
    435458                assert( false );
     
    439462const std::string * TypeData::leafName() const {
    440463        switch ( kind ) {
    441         case Unknown:
    442         case Pointer:
    443         case Reference:
    444         case EnumConstant:
    445         case GlobalScope:
    446         case Array:
    447         case Basic:
    448         case Function:
    449         case AggregateInst:
    450         case Tuple:
    451         case Typeof:
    452         case Basetypeof:
    453         case Builtin:
    454         case Vtable:
     464          case Unknown:
     465          case Pointer:
     466          case Reference:
     467          case EnumConstant:
     468          case GlobalScope:
     469          case Array:
     470          case Basic:
     471          case Function:
     472          case AggregateInst:
     473          case Tuple:
     474          case Typeof:
     475          case Basetypeof:
     476          case Builtin:
     477          case Vtable:
    455478                assertf(false, "Tried to get leaf name from kind without a name: %d", kind);
    456479                break;
    457         case Aggregate:
     480          case Aggregate:
    458481                return aggregate.name;
    459         case Enum:
     482          case Enum:
    460483                return enumeration.name;
    461         case Symbolic:
    462         case SymbolicInst:
     484          case Symbolic:
     485          case SymbolicInst:
    463486                return symbolic.name;
    464         case Qualified:
     487          case Qualified:
    465488                return qualified.child->leafName();
    466489        } // switch
     
    469492
    470493
    471 void buildForall(
    472                 const DeclarationNode * firstNode,
    473                 std::vector<ast::ptr<ast::TypeInstType>> &outputList ) {
    474         {
    475                 std::vector<ast::ptr<ast::Type>> tmpList;
    476                 buildTypeList( firstNode, tmpList );
    477                 for ( auto tmp : tmpList ) {
    478                         outputList.emplace_back(
    479                                 strict_dynamic_cast<const ast::TypeInstType *>(
    480                                         tmp.release() ) );
    481                 }
    482         }
     494template< typename ForallList >
     495void buildForall( const DeclarationNode * firstNode, ForallList &outputList ) {
     496        buildList( firstNode, outputList );
    483497        auto n = firstNode;
    484         for ( auto i = outputList.begin() ;
    485                         i != outputList.end() ;
    486                         ++i, n = (DeclarationNode*)n->get_next() ) {
    487                 // Only the object type class adds additional assertions.
    488                 if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
    489                         continue;
    490                 }
    491 
    492                 ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
    493                 std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
    494                 auto mutTypeDecl = ast::mutate( td );
    495                 const CodeLocation & location = mutTypeDecl->location;
    496                 *i = mutTypeDecl;
    497 
    498                 // add assertion parameters to `type' tyvars in reverse order
    499                 // add assignment operator:  T * ?=?(T *, T)
    500                 newAssertions.push_back( new ast::FunctionDecl(
    501                         location,
    502                         "?=?",
    503                         {}, // forall
    504                         {}, // assertions
    505                         {
    506                                 new ast::ObjectDecl(
    507                                         location,
    508                                         "",
    509                                         new ast::ReferenceType( i->get() ),
    510                                         (ast::Init *)nullptr,
    511                                         ast::Storage::Classes(),
    512                                         ast::Linkage::Cforall,
    513                                         (ast::Expr *)nullptr
    514                                 ),
    515                                 new ast::ObjectDecl(
    516                                         location,
    517                                         "",
    518                                         i->get(),
    519                                         (ast::Init *)nullptr,
    520                                         ast::Storage::Classes(),
    521                                         ast::Linkage::Cforall,
    522                                         (ast::Expr *)nullptr
    523                                 ),
    524                         }, // params
    525                         {
    526                                 new ast::ObjectDecl(
    527                                         location,
    528                                         "",
    529                                         i->get(),
    530                                         (ast::Init *)nullptr,
    531                                         ast::Storage::Classes(),
    532                                         ast::Linkage::Cforall,
    533                                         (ast::Expr *)nullptr
    534                                 ),
    535                         }, // returns
    536                         (ast::CompoundStmt *)nullptr,
    537                         ast::Storage::Classes(),
    538                         ast::Linkage::Cforall
    539                 ) );
    540 
    541                 // add default ctor:  void ?{}(T *)
    542                 newAssertions.push_back( new ast::FunctionDecl(
    543                         location,
    544                         "?{}",
    545                         {}, // forall
    546                         {}, // assertions
    547                         {
    548                                 new ast::ObjectDecl(
    549                                         location,
    550                                         "",
    551                                         new ast::ReferenceType( i->get() ),
    552                                         (ast::Init *)nullptr,
    553                                         ast::Storage::Classes(),
    554                                         ast::Linkage::Cforall,
    555                                         (ast::Expr *)nullptr
    556                                 ),
    557                         }, // params
    558                         {}, // returns
    559                         (ast::CompoundStmt *)nullptr,
    560                         ast::Storage::Classes(),
    561                         ast::Linkage::Cforall
    562                 ) );
    563 
    564                 // add copy ctor:  void ?{}(T *, T)
    565                 newAssertions.push_back( new ast::FunctionDecl(
    566                         location,
    567                         "?{}",
    568                         {}, // forall
    569                         {}, // assertions
    570                         {
    571                                 new ast::ObjectDecl(
    572                                         location,
    573                                         "",
    574                                         new ast::ReferenceType( i->get() ),
    575                                         (ast::Init *)nullptr,
    576                                         ast::Storage::Classes(),
    577                                         ast::Linkage::Cforall,
    578                                         (ast::Expr *)nullptr
    579                                 ),
    580                                 new ast::ObjectDecl(
    581                                         location,
    582                                         "",
    583                                         i->get(),
    584                                         (ast::Init *)nullptr,
    585                                         ast::Storage::Classes(),
    586                                         ast::Linkage::Cforall,
    587                                         (ast::Expr *)nullptr
    588                                 ),
    589                         }, // params
    590                         {}, // returns
    591                         (ast::CompoundStmt *)nullptr,
    592                         ast::Storage::Classes(),
    593                         ast::Linkage::Cforall
    594                 ) );
    595 
    596                 // add dtor:  void ^?{}(T *)
    597                 newAssertions.push_back( new ast::FunctionDecl(
    598                         location,
    599                         "^?{}",
    600                         {}, // forall
    601                         {}, // assertions
    602                         {
    603                                 new ast::ObjectDecl(
    604                                         location,
    605                                         "",
    606                                         new ast::ReferenceType( i->get() ),
    607                                         (ast::Init *)nullptr,
    608                                         ast::Storage::Classes(),
    609                                         ast::Linkage::Cforall,
    610                                         (ast::Expr *)nullptr
    611                                 ),
    612                         }, // params
    613                         {}, // returns
    614                         (ast::CompoundStmt *)nullptr,
    615                         ast::Storage::Classes(),
    616                         ast::Linkage::Cforall
    617                 ) );
    618 
    619                 spliceBegin( mutTypeDecl->assertions, newAssertions );
    620         } // for
    621 }
    622 
    623 
    624 void buildForall(
    625                 const DeclarationNode * firstNode,
    626                 std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) {
    627         buildList( firstNode, outputForall );
    628         auto n = firstNode;
    629         for ( auto i = outputForall.begin() ;
    630                         i != outputForall.end() ;
    631                         ++i, n = (DeclarationNode*)n->get_next() ) {
    632                 // Only the object type class adds additional assertions.
    633                 if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
    634                         continue;
    635                 }
    636 
    637                 ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
    638                 std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
    639                 auto mutTypeDecl = ast::mutate( td );
    640                 const CodeLocation & location = mutTypeDecl->location;
    641                 *i = mutTypeDecl;
    642 
    643                 // add assertion parameters to `type' tyvars in reverse order
    644                 // add assignment operator:  T * ?=?(T *, T)
    645                 newAssertions.push_back( new ast::FunctionDecl(
    646                         location,
    647                         "?=?",
    648                         {}, // forall
    649                         {}, // assertions
    650                         {
    651                                 new ast::ObjectDecl(
    652                                         location,
    653                                         "",
    654                                         new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ),
    655                                         (ast::Init *)nullptr,
    656                                         ast::Storage::Classes(),
    657                                         ast::Linkage::Cforall,
    658                                         (ast::Expr *)nullptr
    659                                 ),
    660                                 new ast::ObjectDecl(
    661                                         location,
    662                                         "",
    663                                         new ast::TypeInstType( td->name, *i ),
    664                                         (ast::Init *)nullptr,
    665                                         ast::Storage::Classes(),
    666                                         ast::Linkage::Cforall,
    667                                         (ast::Expr *)nullptr
    668                                 ),
    669                         }, // params
    670                         {
    671                                 new ast::ObjectDecl(
    672                                         location,
    673                                         "",
    674                                         new ast::TypeInstType( td->name, *i ),
    675                                         (ast::Init *)nullptr,
    676                                         ast::Storage::Classes(),
    677                                         ast::Linkage::Cforall,
    678                                         (ast::Expr *)nullptr
    679                                 ),
    680                         }, // returns
    681                         (ast::CompoundStmt *)nullptr,
    682                         ast::Storage::Classes(),
    683                         ast::Linkage::Cforall
    684                 ) );
    685 
    686                 // add default ctor:  void ?{}(T *)
    687                 newAssertions.push_back( new ast::FunctionDecl(
    688                         location,
    689                         "?{}",
    690                         {}, // forall
    691                         {}, // assertions
    692                         {
    693                                 new ast::ObjectDecl(
    694                                         location,
    695                                         "",
    696                                         new ast::ReferenceType(
    697                                                 new ast::TypeInstType( td->name, i->get() ) ),
    698                                         (ast::Init *)nullptr,
    699                                         ast::Storage::Classes(),
    700                                         ast::Linkage::Cforall,
    701                                         (ast::Expr *)nullptr
    702                                 ),
    703                         }, // params
    704                         {}, // returns
    705                         (ast::CompoundStmt *)nullptr,
    706                         ast::Storage::Classes(),
    707                         ast::Linkage::Cforall
    708                 ) );
    709 
    710                 // add copy ctor:  void ?{}(T *, T)
    711                 newAssertions.push_back( new ast::FunctionDecl(
    712                         location,
    713                         "?{}",
    714                         {}, // forall
    715                         {}, // assertions
    716                         {
    717                                 new ast::ObjectDecl(
    718                                         location,
    719                                         "",
    720                                         new ast::ReferenceType(
    721                                                 new ast::TypeInstType( td->name, *i ) ),
    722                                         (ast::Init *)nullptr,
    723                                         ast::Storage::Classes(),
    724                                         ast::Linkage::Cforall,
    725                                         (ast::Expr *)nullptr
    726                                 ),
    727                                 new ast::ObjectDecl(
    728                                         location,
    729                                         "",
    730                                         new ast::TypeInstType( td->name, *i ),
    731                                         (ast::Init *)nullptr,
    732                                         ast::Storage::Classes(),
    733                                         ast::Linkage::Cforall,
    734                                         (ast::Expr *)nullptr
    735                                 ),
    736                         }, // params
    737                         {}, // returns
    738                         (ast::CompoundStmt *)nullptr,
    739                         ast::Storage::Classes(),
    740                         ast::Linkage::Cforall
    741                 ) );
    742 
    743                 // add dtor:  void ^?{}(T *)
    744                 newAssertions.push_back( new ast::FunctionDecl(
    745                         location,
    746                         "^?{}",
    747                         {}, // forall
    748                         {}, // assertions
    749                         {
    750                                 new ast::ObjectDecl(
    751                                         location,
    752                                         "",
    753                                         new ast::ReferenceType(
    754                                                 new ast::TypeInstType( i->get() )
    755                                         ),
    756                                         (ast::Init *)nullptr,
    757                                         ast::Storage::Classes(),
    758                                         ast::Linkage::Cforall,
    759                                         (ast::Expr *)nullptr
    760                                 ),
    761                         }, // params
    762                         {}, // returns
    763                         (ast::CompoundStmt *)nullptr,
    764                         ast::Storage::Classes(),
    765                         ast::Linkage::Cforall
    766                 ) );
    767 
    768                 spliceBegin( mutTypeDecl->assertions, newAssertions );
     498        for ( typename ForallList::iterator i = outputList.begin(); i != outputList.end(); ++i, n = (DeclarationNode*)n->get_next() ) {
     499                TypeDecl * td = static_cast<TypeDecl *>(*i);
     500                if ( n->variable.tyClass == TypeDecl::Otype ) {
     501                        // add assertion parameters to `type' tyvars in reverse order
     502                        // add dtor:  void ^?{}(T *)
     503                        FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false );
     504                        dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     505                        td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) );
     506
     507                        // add copy ctor:  void ?{}(T *, T)
     508                        FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false );
     509                        copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     510                        copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
     511                        td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) );
     512
     513                        // add default ctor:  void ?{}(T *)
     514                        FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false );
     515                        ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     516                        td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) );
     517
     518                        // add assignment operator:  T * ?=?(T *, T)
     519                        FunctionType * assignType = new FunctionType( Type::Qualifiers(), false );
     520                        assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
     521                        assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
     522                        assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
     523                        td->get_assertions().push_front( new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Cforall, assignType, nullptr ) );
     524                } // if
    769525        } // for
    770526} // buildForall
    771527
    772528
    773 ast::Type * typebuild( const TypeData * td ) {
     529Type * typebuild( const TypeData * td ) {
    774530        assert( td );
    775531        switch ( td->kind ) {
    776         case TypeData::Unknown:
     532          case TypeData::Unknown:
    777533                // fill in implicit int
    778                 return new ast::BasicType(
    779                         ast::BasicType::SignedInt,
    780                         buildQualifiers( td )
    781                 );
    782         case TypeData::Basic:
     534                return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
     535          case TypeData::Basic:
    783536                return buildBasicType( td );
    784         case TypeData::Pointer:
     537          case TypeData::Pointer:
    785538                return buildPointer( td );
    786         case TypeData::Array:
     539          case TypeData::Array:
    787540                return buildArray( td );
    788         case TypeData::Reference:
     541          case TypeData::Reference:
    789542                return buildReference( td );
    790         case TypeData::Function:
    791                 return buildFunctionType( td );
    792         case TypeData::AggregateInst:
     543          case TypeData::Function:
     544                return buildFunction( td );
     545          case TypeData::AggregateInst:
    793546                return buildAggInst( td );
    794         case TypeData::EnumConstant:
    795                 return new ast::EnumInstType( "", buildQualifiers( td ) );
    796         case TypeData::SymbolicInst:
     547          case TypeData::EnumConstant:
     548                return new EnumInstType( buildQualifiers( td ), "" );
     549          case TypeData::SymbolicInst:
    797550                return buildSymbolicInst( td );
    798         case TypeData::Tuple:
     551          case TypeData::Tuple:
    799552                return buildTuple( td );
    800         case TypeData::Typeof:
    801         case TypeData::Basetypeof:
     553          case TypeData::Typeof:
     554          case TypeData::Basetypeof:
    802555                return buildTypeof( td );
    803         case TypeData::Vtable:
     556          case TypeData::Vtable:
    804557                return buildVtable( td );
    805         case TypeData::Builtin:
     558          case TypeData::Builtin:
    806559                switch ( td->builtintype ) {
    807                 case DeclarationNode::Zero:
    808                         return new ast::ZeroType();
    809                 case DeclarationNode::One:
    810                         return new ast::OneType();
    811                 default:
    812                         return new ast::VarArgsType( buildQualifiers( td ) );
     560                  case DeclarationNode::Zero:
     561                        return new ZeroType( noQualifiers );
     562                  case DeclarationNode::One:
     563                        return new OneType( noQualifiers );
     564                  default:
     565                        return new VarArgsType( buildQualifiers( td ) );
    813566                } // switch
    814         case TypeData::GlobalScope:
    815                 return new ast::GlobalScopeType();
    816         case TypeData::Qualified:
    817                 return new ast::QualifiedType(
    818                         typebuild( td->qualified.parent ),
    819                         typebuild( td->qualified.child ),
    820                         buildQualifiers( td )
    821                 );
    822         case TypeData::Symbolic:
    823         case TypeData::Enum:
    824         case TypeData::Aggregate:
     567          case TypeData::GlobalScope:
     568                return new GlobalScopeType();
     569          case TypeData::Qualified:
     570                return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) );
     571          case TypeData::Symbolic:
     572          case TypeData::Enum:
     573          case TypeData::Aggregate:
    825574                assert( false );
    826575        } // switch
     
    834583
    835584        switch ( td->kind ) {
    836         case TypeData::Aggregate:
     585          case TypeData::Aggregate:
    837586                if ( ! toplevel && td->aggregate.body ) {
    838587                        ret = td->clone();
    839588                } // if
    840589                break;
    841         case TypeData::Enum:
     590          case TypeData::Enum:
    842591                if ( ! toplevel && td->enumeration.body ) {
    843592                        ret = td->clone();
    844593                } // if
    845594                break;
    846         case TypeData::AggregateInst:
     595          case TypeData::AggregateInst:
    847596                if ( td->aggInst.aggregate ) {
    848597                        ret = typeextractAggregate( td->aggInst.aggregate, false );
    849598                } // if
    850599                break;
    851         default:
     600          default:
    852601                if ( td->base ) {
    853602                        ret = typeextractAggregate( td->base, false );
     
    858607
    859608
    860 ast::CV::Qualifiers buildQualifiers( const TypeData * td ) {
     609Type::Qualifiers buildQualifiers( const TypeData * td ) {
    861610        return td->qualifiers;
    862611} // buildQualifiers
     
    867616} // genTSError
    868617
    869 ast::Type * buildBasicType( const TypeData * td ) {
    870         ast::BasicType::Kind ret;
     618Type * buildBasicType( const TypeData * td ) {
     619        BasicType::Kind ret;
    871620
    872621        switch ( td->basictype ) {
    873         case DeclarationNode::Void:
     622          case DeclarationNode::Void:
    874623                if ( td->signedness != DeclarationNode::NoSignedness ) {
    875624                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
     
    878627                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    879628                } // if
    880                 return new ast::VoidType( buildQualifiers( td ) );
    881                 break;
    882 
    883         case DeclarationNode::Bool:
     629                return new VoidType( buildQualifiers( td ) );
     630                break;
     631
     632          case DeclarationNode::Bool:
    884633                if ( td->signedness != DeclarationNode::NoSignedness ) {
    885634                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
     
    889638                } // if
    890639
    891                 ret = ast::BasicType::Bool;
    892                 break;
    893 
    894         case DeclarationNode::Char:
     640                ret = BasicType::Bool;
     641                break;
     642
     643          case DeclarationNode::Char:
    895644                // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the
    896645                // character types. The implementation shall define char to have the same range, representation, and behavior as
    897646                // either signed char or unsigned char.
    898                 static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char };
     647                static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::Char };
    899648
    900649                if ( td->length != DeclarationNode::NoLength ) {
     
    905654                break;
    906655
    907         case DeclarationNode::Int:
    908                 static ast::BasicType::Kind inttype[2][4] = {
    909                         { ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt },
    910                         { ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt },
     656          case DeclarationNode::Int:
     657                static BasicType::Kind inttype[2][4] = {
     658                        { BasicType::ShortSignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt },
     659                        { BasicType::ShortUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt },
    911660                };
    912661
    913         Integral: ;
     662          Integral: ;
    914663                if ( td->signedness == DeclarationNode::NoSignedness ) {
    915664                        const_cast<TypeData *>(td)->signedness = DeclarationNode::Signed;
     
    918667                break;
    919668
    920         case DeclarationNode::Int128:
    921                 ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128;
     669          case DeclarationNode::Int128:
     670                ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
    922671                if ( td->length != DeclarationNode::NoLength ) {
    923672                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
     
    925674                break;
    926675
    927         case DeclarationNode::Float:
    928         case DeclarationNode::Double:
    929         case DeclarationNode::LongDouble:                                       // not set until below
    930         case DeclarationNode::uuFloat80:
    931         case DeclarationNode::uuFloat128:
    932         case DeclarationNode::uFloat16:
    933         case DeclarationNode::uFloat32:
    934         case DeclarationNode::uFloat32x:
    935         case DeclarationNode::uFloat64:
    936         case DeclarationNode::uFloat64x:
    937         case DeclarationNode::uFloat128:
    938         case DeclarationNode::uFloat128x:
    939                 static ast::BasicType::Kind floattype[2][12] = {
    940                         { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, (ast::BasicType::Kind)-1, (ast::BasicType::Kind)-1, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex, },
    941                         { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x, },
     676          case DeclarationNode::Float:
     677          case DeclarationNode::Double:
     678          case DeclarationNode::LongDouble:                                     // not set until below
     679          case DeclarationNode::uuFloat80:
     680          case DeclarationNode::uuFloat128:
     681          case DeclarationNode::uFloat16:
     682          case DeclarationNode::uFloat32:
     683          case DeclarationNode::uFloat32x:
     684          case DeclarationNode::uFloat64:
     685          case DeclarationNode::uFloat64x:
     686          case DeclarationNode::uFloat128:
     687          case DeclarationNode::uFloat128x:
     688                static BasicType::Kind floattype[2][12] = {
     689                        { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, (BasicType::Kind)-1, (BasicType::Kind)-1, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex, },
     690                        { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x, },
    942691                };
    943692
    944         FloatingPoint: ;
     693          FloatingPoint: ;
    945694                if ( td->signedness != DeclarationNode::NoSignedness ) {
    946695                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
     
    966715                break;
    967716
    968         case DeclarationNode::NoBasicType:
     717          case DeclarationNode::NoBasicType:
    969718                // No basic type in declaration => default double for Complex/Imaginary and int type for integral types
    970719                if ( td->complextype == DeclarationNode::Complex || td->complextype == DeclarationNode::Imaginary ) {
     
    975724                const_cast<TypeData *>(td)->basictype = DeclarationNode::Int;
    976725                goto Integral;
    977         default:
    978                 assertf( false, "unknown basic type" );
     726          default:
     727                assertf( false, "unknown basic type" );
    979728                return nullptr;
    980729        } // switch
    981730
    982         ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) );
     731        BasicType * bt = new BasicType( buildQualifiers( td ), ret );
     732        buildForall( td->forall, bt->get_forall() );
    983733        return bt;
    984734} // buildBasicType
    985735
    986736
    987 ast::PointerType * buildPointer( const TypeData * td ) {
    988         ast::PointerType * pt;
     737PointerType * buildPointer( const TypeData * td ) {
     738        PointerType * pt;
    989739        if ( td->base ) {
    990                 pt = new ast::PointerType(
    991                         typebuild( td->base ),
    992                         buildQualifiers( td )
    993                 );
     740                pt = new PointerType( buildQualifiers( td ), typebuild( td->base ) );
    994741        } else {
    995                 pt = new ast::PointerType(
    996                         new ast::BasicType( ast::BasicType::SignedInt ),
    997                         buildQualifiers( td )
    998                 );
     742                pt = new PointerType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    999743        } // if
     744        buildForall( td->forall, pt->get_forall() );
    1000745        return pt;
    1001746} // buildPointer
    1002747
    1003748
    1004 ast::ArrayType * buildArray( const TypeData * td ) {
    1005         ast::ArrayType * at;
     749ArrayType * buildArray( const TypeData * td ) {
     750        ArrayType * at;
    1006751        if ( td->base ) {
    1007                 at = new ast::ArrayType(
    1008                         typebuild( td->base ),
    1009                         maybeBuild( td->array.dimension ),
    1010                         td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
    1011                         td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
    1012                         buildQualifiers( td )
    1013                 );
     752                at = new ArrayType( buildQualifiers( td ), typebuild( td->base ), maybeBuild< Expression >( td->array.dimension ),
     753                                                        td->array.isVarLen, td->array.isStatic );
    1014754        } else {
    1015                 at = new ast::ArrayType(
    1016                         new ast::BasicType( ast::BasicType::SignedInt ),
    1017                         maybeBuild( td->array.dimension ),
    1018                         td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
    1019                         td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
    1020                         buildQualifiers( td )
    1021                 );
     755                at = new ArrayType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ),
     756                                                        maybeBuild< Expression >( td->array.dimension ), td->array.isVarLen, td->array.isStatic );
    1022757        } // if
     758        buildForall( td->forall, at->get_forall() );
    1023759        return at;
    1024760} // buildArray
    1025761
    1026762
    1027 ast::ReferenceType * buildReference( const TypeData * td ) {
    1028         ast::ReferenceType * rt;
     763ReferenceType * buildReference( const TypeData * td ) {
     764        ReferenceType * rt;
    1029765        if ( td->base ) {
    1030                 rt = new ast::ReferenceType(
    1031                         typebuild( td->base ),
    1032                         buildQualifiers( td )
    1033                 );
     766                rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) );
    1034767        } else {
    1035                 rt = new ast::ReferenceType(
    1036                         new ast::BasicType( ast::BasicType::SignedInt ),
    1037                         buildQualifiers( td )
    1038                 );
     768                rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    1039769        } // if
     770        buildForall( td->forall, rt->get_forall() );
    1040771        return rt;
    1041772} // buildReference
    1042773
    1043774
    1044 ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {
     775AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
    1045776        assert( td->kind == TypeData::Aggregate );
    1046         ast::AggregateDecl * at;
     777        AggregateDecl * at;
    1047778        switch ( td->aggregate.kind ) {
    1048         case ast::AggregateDecl::Struct:
    1049         case ast::AggregateDecl::Coroutine:
    1050         case ast::AggregateDecl::Exception:
    1051         case ast::AggregateDecl::Generator:
    1052         case ast::AggregateDecl::Monitor:
    1053         case ast::AggregateDecl::Thread:
    1054                 at = new ast::StructDecl( td->location,
    1055                         *td->aggregate.name,
    1056                         td->aggregate.kind,
    1057                         std::move( attributes ),
    1058                         linkage
    1059                 );
    1060                 buildForall( td->aggregate.params, at->params );
    1061                 break;
    1062         case ast::AggregateDecl::Union:
    1063                 at = new ast::UnionDecl( td->location,
    1064                         *td->aggregate.name,
    1065                         std::move( attributes ),
    1066                         linkage
    1067                 );
    1068                 buildForall( td->aggregate.params, at->params );
    1069                 break;
    1070         case ast::AggregateDecl::Trait:
    1071                 at = new ast::TraitDecl( td->location,
    1072                         *td->aggregate.name,
    1073                         std::move( attributes ),
    1074                         linkage
    1075                 );
    1076                 buildList( td->aggregate.params, at->params );
    1077                 break;
    1078         default:
     779          case AggregateDecl::Struct:
     780          case AggregateDecl::Coroutine:
     781          case AggregateDecl::Exception:
     782          case AggregateDecl::Generator:
     783          case AggregateDecl::Monitor:
     784          case AggregateDecl::Thread:
     785                at = new StructDecl( *td->aggregate.name, td->aggregate.kind, attributes, linkage );
     786                buildForall( td->aggregate.params, at->get_parameters() );
     787                break;
     788          case AggregateDecl::Union:
     789                at = new UnionDecl( *td->aggregate.name, attributes, linkage );
     790                buildForall( td->aggregate.params, at->get_parameters() );
     791                break;
     792          case AggregateDecl::Trait:
     793                at = new TraitDecl( *td->aggregate.name, attributes, linkage );
     794                buildList( td->aggregate.params, at->get_parameters() );
     795                break;
     796          default:
    1079797                assert( false );
    1080798        } // switch
    1081799
    1082         buildList( td->aggregate.fields, at->members );
     800        buildList( td->aggregate.fields, at->get_members() );
    1083801        at->set_body( td->aggregate.body );
    1084802
     
    1087805
    1088806
    1089 ast::BaseInstType * buildComAggInst(
    1090                 const TypeData * type,
    1091                 std::vector<ast::ptr<ast::Attribute>> && attributes,
    1092                 ast::Linkage::Spec linkage ) {
     807ReferenceToType * buildComAggInst( const TypeData * type, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
    1093808        switch ( type->kind ) {
    1094         case TypeData::Enum:
    1095                 if ( type->enumeration.body ) {
    1096                         ast::EnumDecl * typedecl =
    1097                                 buildEnum( type, std::move( attributes ), linkage );
    1098                         return new ast::EnumInstType(
    1099                                 typedecl,
    1100                                 buildQualifiers( type )
    1101                         );
    1102                 } else {
    1103                         return new ast::EnumInstType(
    1104                                 *type->enumeration.name,
    1105                                 buildQualifiers( type )
    1106                         );
    1107                 } // if
    1108                 break;
    1109         case TypeData::Aggregate:
    1110                 if ( type->aggregate.body ) {
    1111                         ast::AggregateDecl * typedecl =
    1112                                 buildAggregate( type, std::move( attributes ), linkage );
    1113                         switch ( type->aggregate.kind ) {
    1114                         case ast::AggregateDecl::Struct:
    1115                         case ast::AggregateDecl::Coroutine:
    1116                         case ast::AggregateDecl::Monitor:
    1117                         case ast::AggregateDecl::Thread:
    1118                                 return new ast::StructInstType(
    1119                                         strict_dynamic_cast<ast::StructDecl *>( typedecl ),
    1120                                         buildQualifiers( type )
    1121                                 );
    1122                         case ast::AggregateDecl::Union:
    1123                                 return new ast::UnionInstType(
    1124                                         strict_dynamic_cast<ast::UnionDecl *>( typedecl ),
    1125                                         buildQualifiers( type )
    1126                                 );
    1127                         case ast::AggregateDecl::Trait:
    1128                                 assert( false );
    1129                                 break;
    1130                         default:
    1131                                 assert( false );
    1132                         } // switch
    1133                 } else {
    1134                         switch ( type->aggregate.kind ) {
    1135                         case ast::AggregateDecl::Struct:
    1136                         case ast::AggregateDecl::Coroutine:
    1137                         case ast::AggregateDecl::Monitor:
    1138                         case ast::AggregateDecl::Thread:
    1139                                 return new ast::StructInstType(
    1140                                         *type->aggregate.name,
    1141                                         buildQualifiers( type )
    1142                                 );
    1143                         case ast::AggregateDecl::Union:
    1144                                 return new ast::UnionInstType(
    1145                                         *type->aggregate.name,
    1146                                         buildQualifiers( type )
    1147                                 );
    1148                         case ast::AggregateDecl::Trait:
    1149                                 return new ast::TraitInstType(
    1150                                         *type->aggregate.name,
    1151                                         buildQualifiers( type )
    1152                                 );
    1153                         default:
    1154                                 assert( false );
    1155                         } // switch
    1156                         break;
    1157                 } // if
    1158                 break;
    1159         default:
     809          case TypeData::Enum: {
     810                  if ( type->enumeration.body ) {
     811                          EnumDecl * typedecl = buildEnum( type, attributes, linkage );
     812                          return new EnumInstType( buildQualifiers( type ), typedecl );
     813                  } else {
     814                          return new EnumInstType( buildQualifiers( type ), *type->enumeration.name );
     815                  } // if
     816          }
     817          case TypeData::Aggregate: {
     818                  ReferenceToType * ret;
     819                  if ( type->aggregate.body ) {
     820                          AggregateDecl * typedecl = buildAggregate( type, attributes, linkage );
     821                          switch ( type->aggregate.kind ) {
     822                                case AggregateDecl::Struct:
     823                                case AggregateDecl::Coroutine:
     824                                case AggregateDecl::Monitor:
     825                                case AggregateDecl::Thread:
     826                                  ret = new StructInstType( buildQualifiers( type ), (StructDecl *)typedecl );
     827                                  break;
     828                                case AggregateDecl::Union:
     829                                  ret = new UnionInstType( buildQualifiers( type ), (UnionDecl *)typedecl );
     830                                  break;
     831                                case AggregateDecl::Trait:
     832                                  assert( false );
     833                                  //ret = new TraitInstType( buildQualifiers( type ), (TraitDecl *)typedecl );
     834                                  break;
     835                                default:
     836                                  assert( false );
     837                          } // switch
     838                  } else {
     839                          switch ( type->aggregate.kind ) {
     840                                case AggregateDecl::Struct:
     841                                case AggregateDecl::Coroutine:
     842                                case AggregateDecl::Monitor:
     843                                case AggregateDecl::Thread:
     844                                  ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name );
     845                                  break;
     846                                case AggregateDecl::Union:
     847                                  ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name );
     848                                  break;
     849                                case AggregateDecl::Trait:
     850                                  ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name );
     851                                  break;
     852                                default:
     853                                  assert( false );
     854                          } // switch
     855                  } // if
     856                  return ret;
     857          }
     858          default:
    1160859                assert( false );
    1161860        } // switch
    1162         assert( false );
    1163861} // buildAggInst
    1164862
    1165863
    1166 ast::BaseInstType * buildAggInst( const TypeData * td ) {
     864ReferenceToType * buildAggInst( const TypeData * td ) {
    1167865        assert( td->kind == TypeData::AggregateInst );
    1168866
    1169         ast::BaseInstType * ret = nullptr;
     867        // ReferenceToType * ret = buildComAggInst( td->aggInst.aggregate, std::list< Attribute * >() );
     868        ReferenceToType * ret = nullptr;
    1170869        TypeData * type = td->aggInst.aggregate;
    1171870        switch ( type->kind ) {
    1172         case TypeData::Enum:
    1173                 return new ast::EnumInstType(
    1174                         *type->enumeration.name,
    1175                         buildQualifiers( type )
    1176                 );
    1177         case TypeData::Aggregate:
    1178                 switch ( type->aggregate.kind ) {
    1179                 case ast::AggregateDecl::Struct:
    1180                 case ast::AggregateDecl::Coroutine:
    1181                 case ast::AggregateDecl::Monitor:
    1182                 case ast::AggregateDecl::Thread:
    1183                         ret = new ast::StructInstType(
    1184                                 *type->aggregate.name,
    1185                                 buildQualifiers( type )
    1186                         );
    1187                         break;
    1188                 case ast::AggregateDecl::Union:
    1189                         ret = new ast::UnionInstType(
    1190                                 *type->aggregate.name,
    1191                                 buildQualifiers( type )
    1192                         );
    1193                         break;
    1194                 case ast::AggregateDecl::Trait:
    1195                         ret = new ast::TraitInstType(
    1196                                 *type->aggregate.name,
    1197                                 buildQualifiers( type )
    1198                         );
    1199                         break;
    1200                 default:
    1201                         assert( false );
    1202                 } // switch
    1203                 break;
    1204         default:
     871          case TypeData::Enum: {
     872                  return new EnumInstType( buildQualifiers( type ), *type->enumeration.name );
     873          }
     874          case TypeData::Aggregate: {
     875                  switch ( type->aggregate.kind ) {
     876                        case AggregateDecl::Struct:
     877                        case AggregateDecl::Coroutine:
     878                        case AggregateDecl::Monitor:
     879                        case AggregateDecl::Thread:
     880                          ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name );
     881                          break;
     882                        case AggregateDecl::Union:
     883                          ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name );
     884                          break;
     885                        case AggregateDecl::Trait:
     886                          ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name );
     887                          break;
     888                        default:
     889                          assert( false );
     890                  } // switch
     891          }
     892          break;
     893          default:
    1205894                assert( false );
    1206895        } // switch
    1207896
    1208         ret->hoistType = td->aggInst.hoistType;
    1209         buildList( td->aggInst.params, ret->params );
     897        ret->set_hoistType( td->aggInst.hoistType );
     898        buildList( td->aggInst.params, ret->get_parameters() );
     899        buildForall( td->forall, ret->get_forall() );
    1210900        return ret;
    1211901} // buildAggInst
    1212902
    1213903
    1214 ast::NamedTypeDecl * buildSymbolic(
    1215                 const TypeData * td,
    1216                 std::vector<ast::ptr<ast::Attribute>> attributes,
    1217                 const std::string & name,
    1218                 ast::Storage::Classes scs,
    1219                 ast::Linkage::Spec linkage ) {
     904NamedTypeDecl * buildSymbolic( const TypeData * td, std::list< Attribute * > attributes, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) {
    1220905        assert( td->kind == TypeData::Symbolic );
    1221         ast::NamedTypeDecl * ret;
     906        NamedTypeDecl * ret;
    1222907        assert( td->base );
    1223908        if ( td->symbolic.isTypedef ) {
    1224                 ret = new ast::TypedefDecl(
    1225                         td->location,
    1226                         name,
    1227                         scs,
    1228                         typebuild( td->base ),
    1229                         linkage
    1230                 );
     909                ret = new TypedefDecl( name, td->location, scs, typebuild( td->base ), linkage );
    1231910        } else {
    1232                 ret = new ast::TypeDecl(
    1233                         td->location,
    1234                         name,
    1235                         scs,
    1236                         typebuild( td->base ),
    1237                         ast::TypeDecl::Dtype,
    1238                         true
    1239                 );
     911                ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true );
    1240912        } // if
    1241         buildList( td->symbolic.assertions, ret->assertions );
    1242         splice( ret->base.get_and_mutate()->attributes, attributes );
     913        buildList( td->symbolic.assertions, ret->get_assertions() );
     914        ret->base->attributes.splice( ret->base->attributes.end(), attributes );
    1243915        return ret;
    1244916} // buildSymbolic
    1245917
    1246918
    1247 ast::EnumDecl * buildEnum(
    1248                 const TypeData * td,
    1249                 std::vector<ast::ptr<ast::Attribute>> && attributes,
    1250                 ast::Linkage::Spec linkage ) {
     919EnumDecl * buildEnum( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
    1251920        assert( td->kind == TypeData::Enum );
    1252         ast::Type * baseType = td->base ? typebuild(td->base) : nullptr;
    1253         ast::EnumDecl * ret = new ast::EnumDecl(
    1254                 td->location,
    1255                 *td->enumeration.name,
    1256                 td->enumeration.typed,
    1257                 std::move( attributes ),
    1258                 linkage,
    1259                 baseType
    1260         );
    1261         buildList( td->enumeration.constants, ret->members );
    1262         auto members = ret->members.begin();
    1263         ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
     921        Type * baseType = td->base ? typebuild(td->base) : nullptr;
     922        EnumDecl * ret = new EnumDecl( *td->enumeration.name, attributes, td->enumeration.typed, linkage, baseType );
     923        buildList( td->enumeration.constants, ret->get_members() );
     924        list< Declaration * >::iterator members = ret->get_members().begin();
     925        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? EnumDecl::EnumHiding::Hide : EnumDecl::EnumHiding::Visible;
    1264926        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
    1265927                if ( cur->enumInLine ) {
     
    1268930                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
    1269931                } else if ( cur->has_enumeratorValue() ) {
    1270                         ast::Decl * member = members->get_and_mutate();
    1271                         ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
    1272                         object->init = new ast::SingleInit(
    1273                                 td->location,
    1274                                 maybeMoveBuild( cur->consume_enumeratorValue() ),
    1275                                 ast::NoConstruct
    1276                         );
     932                        ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members);
     933                        member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) );
    1277934                } else if ( !cur->initializer ) {
    1278                         if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
     935                        if ( baseType && (!dynamic_cast<BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isWholeNumber())) {
    1279936                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
    1280937                        }
     
    1283940                // if
    1284941        } // for
    1285         ret->body = td->enumeration.body;
     942        ret->set_body( td->enumeration.body );
    1286943        return ret;
    1287944} // buildEnum
    1288945
    1289946
    1290 ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {
     947TypeInstType * buildSymbolicInst( const TypeData * td ) {
    1291948        assert( td->kind == TypeData::SymbolicInst );
    1292         ast::TypeInstType * ret = new ast::TypeInstType(
    1293                 *td->symbolic.name,
    1294                 ast::TypeDecl::Dtype,
    1295                 buildQualifiers( td )
    1296         );
    1297         buildList( td->symbolic.actuals, ret->params );
     949        TypeInstType * ret = new TypeInstType( buildQualifiers( td ), *td->symbolic.name, false );
     950        buildList( td->symbolic.actuals, ret->get_parameters() );
     951        buildForall( td->forall, ret->get_forall() );
    1298952        return ret;
    1299953} // buildSymbolicInst
    1300954
    1301955
    1302 ast::TupleType * buildTuple( const TypeData * td ) {
     956TupleType * buildTuple( const TypeData * td ) {
    1303957        assert( td->kind == TypeData::Tuple );
    1304         std::vector<ast::ptr<ast::Type>> types;
     958        std::list< Type * > types;
    1305959        buildTypeList( td->tuple, types );
    1306         ast::TupleType * ret = new ast::TupleType(
    1307                 std::move( types ),
    1308                 buildQualifiers( td )
    1309         );
     960        TupleType * ret = new TupleType( buildQualifiers( td ), types );
     961        buildForall( td->forall, ret->get_forall() );
    1310962        return ret;
    1311963} // buildTuple
    1312964
    1313965
    1314 ast::TypeofType * buildTypeof( const TypeData * td ) {
     966TypeofType * buildTypeof( const TypeData * td ) {
    1315967        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
    1316968        assert( td->typeexpr );
    1317         return new ast::TypeofType(
    1318                 td->typeexpr->build(),
    1319                 td->kind == TypeData::Typeof
    1320                         ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof,
    1321                 buildQualifiers( td )
    1322         );
     969        // assert( td->typeexpr->expr );
     970        return new TypeofType{ buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof };
    1323971} // buildTypeof
    1324972
    1325973
    1326 ast::VTableType * buildVtable( const TypeData * td ) {
     974VTableType * buildVtable( const TypeData * td ) {
    1327975        assert( td->base );
    1328         return new ast::VTableType(
    1329                 typebuild( td->base ),
    1330                 buildQualifiers( td )
    1331         );
     976        return new VTableType{ buildQualifiers( td ), typebuild( td->base ) };
    1332977} // buildVtable
    1333978
    1334979
    1335 ast::FunctionDecl * buildFunctionDecl(
    1336                 const TypeData * td,
    1337                 const string &name,
    1338                 ast::Storage::Classes scs,
    1339                 ast::Function::Specs funcSpec,
    1340                 ast::Linkage::Spec linkage,
    1341                 ast::Expr * asmName,
    1342                 std::vector<ast::ptr<ast::Attribute>> && attributes ) {
    1343         assert( td->kind == TypeData::Function );
    1344         // For some reason FunctionDecl takes a bool instead of an ArgumentFlag.
    1345         bool isVarArgs = !td->function.params || td->function.params->hasEllipsis;
    1346         ast::CV::Qualifiers cvq = buildQualifiers( td );
    1347         std::vector<ast::ptr<ast::TypeDecl>> forall;
    1348         std::vector<ast::ptr<ast::DeclWithType>> assertions;
    1349         std::vector<ast::ptr<ast::DeclWithType>> params;
    1350         std::vector<ast::ptr<ast::DeclWithType>> returns;
    1351         buildList( td->function.params, params );
    1352         buildForall( td->forall, forall );
    1353         // Functions do not store their assertions there anymore.
    1354         for ( ast::ptr<ast::TypeDecl> & type_param : forall ) {
    1355                 auto mut = type_param.get_and_mutate();
    1356                 splice( assertions, mut->assertions );
    1357         }
    1358         if ( td->base ) {
    1359                 switch ( td->base->kind ) {
    1360                 case TypeData::Tuple:
    1361                         buildList( td->base->tuple, returns );
    1362                         break;
    1363                 default:
    1364                         returns.push_back( dynamic_cast<ast::DeclWithType *>(
    1365                                 buildDecl(
    1366                                         td->base,
    1367                                         "",
    1368                                         ast::Storage::Classes(),
    1369                                         (ast::Expr *)nullptr, // bitfieldWidth
    1370                                         ast::Function::Specs(),
    1371                                         ast::Linkage::Cforall,
    1372                                         (ast::Expr *)nullptr // asmName
    1373                                 )
    1374                         ) );
    1375                 } // switch
    1376         } else {
    1377                 returns.push_back( new ast::ObjectDecl(
    1378                         td->location,
    1379                         "",
    1380                         new ast::BasicType( ast::BasicType::SignedInt ),
    1381                         (ast::Init *)nullptr,
    1382                         ast::Storage::Classes(),
    1383                         ast::Linkage::Cforall
    1384                 ) );
    1385         } // if
    1386         ast::Stmt * stmt = maybeBuild( td->function.body );
    1387         ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt );
    1388         ast::FunctionDecl * decl = new ast::FunctionDecl( td->location,
    1389                 name,
    1390                 std::move( forall ),
    1391                 std::move( assertions ),
    1392                 std::move( params ),
    1393                 std::move( returns ),
    1394                 body,
    1395                 scs,
    1396                 linkage,
    1397                 std::move( attributes ),
    1398                 funcSpec,
    1399                 (isVarArgs) ? ast::VariableArgs : ast::FixedArgs
    1400         );
    1401         buildList( td->function.withExprs, decl->withExprs );
    1402         decl->asmName = asmName;
    1403         // This may be redundant on a declaration.
    1404         decl->type.get_and_mutate()->qualifiers = cvq;
    1405         return decl;
    1406 } // buildFunctionDecl
    1407 
    1408 
    1409 ast::Decl * buildDecl(
    1410                 const TypeData * td,
    1411                 const string &name,
    1412                 ast::Storage::Classes scs,
    1413                 ast::Expr * bitfieldWidth,
    1414                 ast::Function::Specs funcSpec,
    1415                 ast::Linkage::Spec linkage,
    1416                 ast::Expr * asmName,
    1417                 ast::Init * init,
    1418                 std::vector<ast::ptr<ast::Attribute>> && attributes ) {
     980Declaration * 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 ) {
    1419981        if ( td->kind == TypeData::Function ) {
    1420982                if ( td->function.idList ) {                                    // KR function ?
     
    1422984                } // if
    1423985
    1424                 return buildFunctionDecl(
    1425                         td, name, scs, funcSpec, linkage,
    1426                         asmName, std::move( attributes ) );
     986                FunctionDecl * decl;
     987                Statement * stmt = maybeBuild<Statement>( td->function.body );
     988                CompoundStmt * body = dynamic_cast< CompoundStmt * >( stmt );
     989                decl = new FunctionDecl( name, scs, linkage, buildFunction( td ), body, attributes, funcSpec );
     990                buildList( td->function.withExprs, decl->withExprs );
     991                return decl->set_asmName( asmName );
    1427992        } else if ( td->kind == TypeData::Aggregate ) {
    1428                 return buildAggregate( td, std::move( attributes ), linkage );
     993                return buildAggregate( td, attributes, linkage );
    1429994        } else if ( td->kind == TypeData::Enum ) {
    1430                 return buildEnum( td, std::move( attributes ), linkage );
     995                return buildEnum( td, attributes, linkage );
    1431996        } else if ( td->kind == TypeData::Symbolic ) {
    1432                 return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
     997                return buildSymbolic( td, attributes, name, scs, linkage );
    1433998        } else {
    1434                 auto ret = new ast::ObjectDecl( td->location,
    1435                         name,
    1436                         typebuild( td ),
    1437                         init,
    1438                         scs,
    1439                         linkage,
    1440                         bitfieldWidth,
    1441                         std::move( attributes )
    1442                 );
    1443                 ret->asmName = asmName;
    1444                 return ret;
     999                return (new ObjectDecl( name, scs, linkage, bitfieldWidth, typebuild( td ), init, attributes ))->set_asmName( asmName );
    14451000        } // if
    14461001        return nullptr;
     
    14481003
    14491004
    1450 ast::FunctionType * buildFunctionType( const TypeData * td ) {
     1005FunctionType * buildFunction( const TypeData * td ) {
    14511006        assert( td->kind == TypeData::Function );
    1452         ast::FunctionType * ft = new ast::FunctionType(
    1453                 ( !td->function.params || td->function.params->hasEllipsis )
    1454                         ? ast::VariableArgs : ast::FixedArgs,
    1455                 buildQualifiers( td )
    1456         );
    1457         buildTypeList( td->function.params, ft->params );
     1007        FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis );
     1008        buildList( td->function.params, ft->parameters );
    14581009        buildForall( td->forall, ft->forall );
    14591010        if ( td->base ) {
    14601011                switch ( td->base->kind ) {
    1461                 case TypeData::Tuple:
    1462                         buildTypeList( td->base->tuple, ft->returns );
     1012                  case TypeData::Tuple:
     1013                        buildList( td->base->tuple, ft->returnVals );
    14631014                        break;
    1464                 default:
    1465                         ft->returns.push_back( typebuild( td->base ) );
    1466                         break;
     1015                  default:
     1016                        ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType * >( buildDecl( td->base, "", Type::StorageClasses(), nullptr, Type::FuncSpecifiers(), LinkageSpec::Cforall, nullptr ) ) );
    14671017                } // switch
    14681018        } else {
    1469                 ft->returns.push_back(
    1470                         new ast::BasicType( ast::BasicType::SignedInt ) );
     1019                ft->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) );
    14711020        } // if
    14721021        return ft;
    1473 } // buildFunctionType
     1022} // buildFunction
    14741023
    14751024
     
    15021051                                param->type = decl->type;                               // set copy declaration type to parameter type
    15031052                                decl->type = nullptr;                                   // reset declaration type
    1504                                 // Copy and reset attributes from declaration to parameter:
    1505                                 splice( param->attributes, decl->attributes );
     1053                                param->attributes.splice( param->attributes.end(), decl->attributes ); // copy and reset attributes from declaration to parameter
    15061054                        } // if
    15071055                } // for
  • src/Parser/TypeData.h

    r24d6572 r34b4268  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat May 16 15:18:36 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Mar  1 10:44:00 2023
    13 // Update Count     : 206
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue May 10 22:18:49 2022
     13// Update Count     : 203
    1414//
    1515
    1616#pragma once
    1717
    18 #include <iosfwd>                                   // for ostream
    19 #include <list>                                     // for list
    20 #include <string>                                   // for string
     18#include <iosfwd>                                                                               // for ostream
     19#include <list>                                                                                 // for list
     20#include <string>                                                                               // for string
    2121
    22 #include "AST/Type.hpp"                             // for Type
    23 #include "DeclarationNode.h"                        // for DeclarationNode
     22#include "ParseNode.h"                                                                  // for DeclarationNode, DeclarationNode::Ag...
     23#include "SynTree/LinkageSpec.h"                                                // for Spec
     24#include "SynTree/Type.h"                                                               // for Type, ReferenceToType (ptr only)
     25#include "SynTree/SynTree.h"                                                    // for Visitor Nodes
    2426
    2527struct TypeData {
     
    2830
    2931        struct Aggregate_t {
    30                 ast::AggregateDecl::Aggregate kind;
     32                AggregateDecl::Aggregate kind;
    3133                const std::string * name = nullptr;
    3234                DeclarationNode * params = nullptr;
     
    3537                bool body;
    3638                bool anon;
     39
    3740                bool tagged;
    3841                const std::string * parent = nullptr;
     
    9194        DeclarationNode::BuiltinType builtintype = DeclarationNode::NoBuiltinType;
    9295
    93         ast::CV::Qualifiers qualifiers;
     96        Type::Qualifiers qualifiers;
    9497        DeclarationNode * forall = nullptr;
    9598
     
    112115};
    113116
    114 ast::Type * typebuild( const TypeData * );
     117Type * typebuild( const TypeData * );
    115118TypeData * typeextractAggregate( const TypeData * td, bool toplevel = true );
    116 ast::CV::Qualifiers buildQualifiers( const TypeData * td );
    117 ast::Type * buildBasicType( const TypeData * );
    118 ast::PointerType * buildPointer( const TypeData * );
    119 ast::ArrayType * buildArray( const TypeData * );
    120 ast::ReferenceType * buildReference( const TypeData * );
    121 ast::AggregateDecl * buildAggregate( const TypeData *, std::vector<ast::ptr<ast::Attribute>> );
    122 ast::BaseInstType * buildComAggInst( const TypeData *, std::vector<ast::ptr<ast::Attribute>> && attributes, ast::Linkage::Spec linkage );
    123 ast::BaseInstType * buildAggInst( const TypeData * );
    124 ast::TypeDecl * buildVariable( const TypeData * );
    125 ast::EnumDecl * buildEnum( const TypeData *, std::vector<ast::ptr<ast::Attribute>> &&, ast::Linkage::Spec );
    126 ast::TypeInstType * buildSymbolicInst( const TypeData * );
    127 ast::TupleType * buildTuple( const TypeData * );
    128 ast::TypeofType * buildTypeof( const TypeData * );
    129 ast::VTableType * buildVtable( const TypeData * );
    130 ast::Decl * buildDecl(
    131         const TypeData *, const std::string &, ast::Storage::Classes, ast::Expr *,
    132         ast::Function::Specs funcSpec, ast::Linkage::Spec, ast::Expr * asmName,
    133         ast::Init * init = nullptr, std::vector<ast::ptr<ast::Attribute>> && attributes = std::vector<ast::ptr<ast::Attribute>>() );
    134 ast::FunctionType * buildFunctionType( const TypeData * );
    135 ast::Decl * addEnumBase( Declaration *, const TypeData * );
     119Type::Qualifiers buildQualifiers( const TypeData * td );
     120Type * buildBasicType( const TypeData * );
     121PointerType * buildPointer( const TypeData * );
     122ArrayType * buildArray( const TypeData * );
     123ReferenceType * buildReference( const TypeData * );
     124AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > );
     125ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage );
     126ReferenceToType * buildAggInst( const TypeData * );
     127TypeDecl * buildVariable( const TypeData * );
     128EnumDecl * buildEnum( const TypeData *, std::list< Attribute * >, LinkageSpec::Spec );
     129TypeInstType * buildSymbolicInst( const TypeData * );
     130TupleType * buildTuple( const TypeData * );
     131TypeofType * buildTypeof( const TypeData * );
     132VTableType * buildVtable( const TypeData * );
     133Declaration * buildDecl( const TypeData *, const std::string &, Type::StorageClasses, Expression *, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec, Expression * asmName,
     134                                                 Initializer * init = nullptr, std::list< class Attribute * > attributes = std::list< class Attribute * >() );
     135FunctionType * buildFunction( const TypeData * );
     136Declaration * addEnumBase( Declaration *, const TypeData * );
    136137void buildKRFunction( const TypeData::Function_t & function );
    137138
  • src/Parser/TypedefTable.cc

    r24d6572 r34b4268  
    1616
    1717#include "TypedefTable.h"
    18 
    19 #include <cassert>                                // for assert
    20 #include <string>                                 // for string
    21 #include <iostream>                               // for iostream
    22 
    23 #include "ExpressionNode.h"                       // for LabelNode
    24 #include "ParserTypes.h"                          // for Token
    25 #include "StatementNode.h"                        // for CondCtl, ForCtrl
    26 // This (generated) header must come late as it is missing includes.
    27 #include "parser.hh"              // for IDENTIFIER, TYPEDEFname, TYPEGENname
    28 
     18#include <cassert>                                                                              // for assert
     19#include <iostream>
    2920using namespace std;
    3021
    3122#if 0
    3223#define debugPrint( code ) code
    33 
    34 static const char *kindName( int kind ) {
    35         switch ( kind ) {
    36         case IDENTIFIER: return "identifier";
    37         case TYPEDIMname: return "typedim";
    38         case TYPEDEFname: return "typedef";
    39         case TYPEGENname: return "typegen";
    40         default:
    41                 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
    42                 abort();
    43         } // switch
    44 } // kindName
    4524#else
    4625#define debugPrint( code )
    4726#endif
     27
     28using namespace std;                                                                    // string, iostream
     29
     30debugPrint(
     31        static const char *kindName( int kind ) {
     32                switch ( kind ) {
     33                  case IDENTIFIER: return "identifier";
     34                  case TYPEDIMname: return "typedim";
     35                  case TYPEDEFname: return "typedef";
     36                  case TYPEGENname: return "typegen";
     37                  default:
     38                        cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
     39                        abort();
     40                } // switch
     41        } // kindName
     42);
    4843
    4944TypedefTable::~TypedefTable() {
     
    8378                typedefTable.addToEnclosingScope( name, kind, "MTD" );
    8479        } // if
    85 } // TypedefTable::makeTypedef
    86 
    87 void TypedefTable::makeTypedef( const string & name ) {
    88         return makeTypedef( name, TYPEDEFname );
    8980} // TypedefTable::makeTypedef
    9081
  • src/Parser/TypedefTable.h

    r24d6572 r34b4268  
    1919
    2020#include "Common/ScopedMap.h"                                                   // for ScopedMap
     21#include "ParserTypes.h"
     22#include "parser.hh"                                                                    // for IDENTIFIER, TYPEDEFname, TYPEGENname
    2123
    2224class TypedefTable {
    2325        struct Note { size_t level; bool forall; };
    2426        typedef ScopedMap< std::string, int, Note > KindTable;
    25         KindTable kindTable;
     27        KindTable kindTable;   
    2628        unsigned int level = 0;
    2729  public:
     
    3133        bool existsCurr( const std::string & identifier ) const;
    3234        int isKind( const std::string & identifier ) const;
    33         void makeTypedef( const std::string & name, int kind );
    34         void makeTypedef( const std::string & name );
     35        void makeTypedef( const std::string & name, int kind = TYPEDEFname );
    3536        void addToScope( const std::string & identifier, int kind, const char * );
    3637        void addToEnclosingScope( const std::string & identifier, int kind, const char * );
  • src/Parser/lex.ll

    r24d6572 r34b4268  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Tue May  2 08:45:21 2023
    13  * Update Count     : 769
     12 * Last Modified On : Thu Oct 13 20:46:04 2022
     13 * Update Count     : 764
    1414 */
    1515
     
    2323// line-number directives) and C/C++ style comments, which are ignored.
    2424
    25 // *************************** Includes and Defines ****************************
     25//**************************** Includes and Defines ****************************
    2626
    2727#ifdef __clang__
     
    4444
    4545#include "config.h"                                                                             // configure info
    46 #include "DeclarationNode.h"                            // for DeclarationNode
    47 #include "ExpressionNode.h"                             // for LabelNode
    48 #include "InitializerNode.h"                            // for InitializerNode
    4946#include "ParseNode.h"
    50 #include "ParserTypes.h"                                // for Token
    51 #include "StatementNode.h"                              // for CondCtl, ForCtrl
    5247#include "TypedefTable.h"
    53 // This (generated) header must come late as it is missing includes.
    54 #include "parser.hh"                                    // generated info
    5548
    5649string * build_postfix_name( string * name );
     
    221214__alignof               { KEYWORD_RETURN(ALIGNOF); }                    // GCC
    222215__alignof__             { KEYWORD_RETURN(ALIGNOF); }                    // GCC
    223 and                             { QKEYWORD_RETURN(WAND); }                              // CFA
    224216asm                             { KEYWORD_RETURN(ASM); }
    225217__asm                   { KEYWORD_RETURN(ASM); }                                // GCC
     
    258250enable                  { KEYWORD_RETURN(ENABLE); }                             // CFA
    259251enum                    { KEYWORD_RETURN(ENUM); }
     252__extension__   { KEYWORD_RETURN(EXTENSION); }                  // GCC
    260253exception               { KEYWORD_RETURN(EXCEPTION); }                  // CFA
    261 __extension__   { KEYWORD_RETURN(EXTENSION); }                  // GCC
    262254extern                  { KEYWORD_RETURN(EXTERN); }
    263255fallthrough             { KEYWORD_RETURN(FALLTHROUGH); }                // CFA
     
    348340vtable                  { KEYWORD_RETURN(VTABLE); }                             // CFA
    349341waitfor                 { KEYWORD_RETURN(WAITFOR); }                    // CFA
    350 waituntil               { KEYWORD_RETURN(WAITUNTIL); }                  // CFA
    351342when                    { KEYWORD_RETURN(WHEN); }                               // CFA
    352343while                   { KEYWORD_RETURN(WHILE); }
     
    511502        SemanticErrorThrow = true;
    512503        cerr << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
    513                  << ": " << ErrorHelpers::error_str() << errmsg << " before token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
     504                 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
    514505}
    515506
  • src/Parser/module.mk

    r24d6572 r34b4268  
    2121SRC += \
    2222       Parser/DeclarationNode.cc \
    23        Parser/DeclarationNode.h \
    2423       Parser/ExpressionNode.cc \
    25        Parser/ExpressionNode.h \
    2624       Parser/InitializerNode.cc \
    27        Parser/InitializerNode.h \
    2825       Parser/lex.ll \
    2926       Parser/ParseNode.cc \
     
    3330       Parser/parserutility.cc \
    3431       Parser/parserutility.h \
    35        Parser/RunParser.cpp \
    36        Parser/RunParser.hpp \
    3732       Parser/StatementNode.cc \
    38        Parser/StatementNode.h \
    3933       Parser/TypeData.cc \
    4034       Parser/TypeData.h \
  • src/Parser/parser.yy

    r24d6572 r34b4268  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Apr 26 16:45:37 2023
    13 // Update Count     : 6330
     12// Last Modified On : Mon Nov 21 22:34:30 2022
     13// Update Count     : 5848
    1414//
    1515
     
    4444
    4545#include <cstdio>
    46 #include <sstream>
    4746#include <stack>
    4847using namespace std;
    4948
    50 #include "SynTree/Type.h"                               // for Type
    51 #include "DeclarationNode.h"                            // for DeclarationNode, ...
    52 #include "ExpressionNode.h"                             // for ExpressionNode, ...
    53 #include "InitializerNode.h"                            // for InitializerNode, ...
    54 #include "ParserTypes.h"
    55 #include "StatementNode.h"                              // for build_...
     49#include "SynTree/Declaration.h"
     50#include "ParseNode.h"
    5651#include "TypedefTable.h"
    5752#include "TypeData.h"
     53#include "SynTree/LinkageSpec.h"
    5854#include "Common/SemanticError.h"                                               // error_str
    5955#include "Common/utility.h"                                                             // for maybeMoveBuild, maybeBuild, CodeLo...
    6056
    61 #include "SynTree/Attribute.h"                                                  // for Attribute
     57#include "SynTree/Attribute.h"     // for Attribute
    6258
    6359// lex uses __null in a boolean context, it's fine.
     
    6763
    6864extern DeclarationNode * parseTree;
    69 extern ast::Linkage::Spec linkage;
     65extern LinkageSpec::Spec linkage;
    7066extern TypedefTable typedefTable;
    7167
    72 stack<ast::Linkage::Spec> linkageStack;
     68stack<LinkageSpec::Spec> linkageStack;
    7369
    7470bool appendStr( string & to, string & from ) {
     
    203199} // fieldDecl
    204200
    205 #define NEW_ZERO new ExpressionNode( build_constantInteger( yylloc, *new string( "0" ) ) )
    206 #define NEW_ONE  new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) )
     201#define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) )
     202#define NEW_ONE  new ExpressionNode( build_constantInteger( *new string( "1" ) ) )
    207203#define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right)
    208204#define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."
     
    210206#define MISSING_HIGH "Missing high value for down-to range so index is uninitialized."
    211207
    212 static ForCtrl * makeForCtrl(
    213                 const CodeLocation & location,
    214                 DeclarationNode * init,
    215                 enum OperKinds compop,
    216                 ExpressionNode * comp,
    217                 ExpressionNode * inc ) {
    218         // Wrap both comp/inc if they are non-null.
    219         if ( comp ) comp = new ExpressionNode( build_binary_val( location,
    220                 compop,
    221                 new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
    222                 comp ) );
    223         if ( inc ) inc = new ExpressionNode( build_binary_val( location,
    224                 // choose += or -= for upto/downto
    225                 compop == OperKinds::LThan || compop == OperKinds::LEThan ? OperKinds::PlusAssn : OperKinds::MinusAssn,
    226                 new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
    227                 inc ) );
    228         // The StatementNode call frees init->name, it must happen later.
    229         return new ForCtrl( new StatementNode( init ), comp, inc );
    230 }
    231 
    232 ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     208ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    233209        if ( index->initializer ) {
    234210                SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );
     
    237213                SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." );
    238214        } // if
    239         DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) );
    240         return makeForCtrl( location, initDecl, compop, comp, inc );
     215        return new ForCtrl( index->addInitializer( new InitializerNode( start ) ),
     216                // NULL comp/inc => leave blank
     217                comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index->name ) ) ), comp ) ) : nullptr,
     218                inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
     219                                                        OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index->name ) ) ), inc ) ) : nullptr );
    241220} // forCtrl
    242221
    243 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    244         ast::ConstantExpr * constant = dynamic_cast<ast::ConstantExpr *>(type->expr.get());
    245         if ( constant && (constant->rep == "0" || constant->rep == "1") ) {
    246                 type = new ExpressionNode( new ast::CastExpr( location, maybeMoveBuild(type), new ast::BasicType( ast::BasicType::SignedInt ) ) );
     222ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     223        ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get());
     224        if ( constant && (constant->get_constant()->get_value() == "0" || constant->get_constant()->get_value() == "1") ) {
     225                type = new ExpressionNode( new CastExpr( maybeMoveBuild<Expression>(type), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ) );
    247226        } // if
    248         DeclarationNode * initDecl = distAttr(
    249                 DeclarationNode::newTypeof( type, true ),
    250                 DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) )
    251         );
    252         return makeForCtrl( location, initDecl, compop, comp, inc );
     227//      type = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__for_control_index_constraints__" ) ) ), type ) );
     228        return new ForCtrl(
     229                distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
     230                // NULL comp/inc => leave blank
     231                comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : nullptr,
     232                inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
     233                                                        OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : nullptr );
    253234} // forCtrl
    254235
    255 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    256         if ( auto identifier = dynamic_cast<ast::NameExpr *>(index->expr.get()) ) {
    257                 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
    258         } else if ( auto commaExpr = dynamic_cast<ast::CommaExpr *>( index->expr.get() ) ) {
    259                 if ( auto identifier = commaExpr->arg1.as<ast::NameExpr>() ) {
    260                         return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
     236ForCtrl * forCtrl( ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     237        if ( NameExpr * identifier = dynamic_cast<NameExpr *>(index->expr.get()) ) {
     238                return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
     239        } else if ( CommaExpr * commaExpr = dynamic_cast<CommaExpr *>(index->expr.get()) ) {
     240                if ( NameExpr * identifier = dynamic_cast<NameExpr *>(commaExpr->arg1 ) ) {
     241                        return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
    261242                } else {
    262243                        SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
     
    300281%union {
    301282        Token tok;
    302         ExpressionNode * expr;
     283        ParseNode * pn;
     284        ExpressionNode * en;
    303285        DeclarationNode * decl;
    304         ast::AggregateDecl::Aggregate aggKey;
    305         ast::TypeDecl::Kind tclass;
    306         StatementNode * stmt;
    307         ClauseNode * clause;
    308         ast::WaitForStmt * wfs;
    309     ast::WaitUntilStmt::ClauseNode * wucn;
     286        AggregateDecl::Aggregate aggKey;
     287        TypeDecl::Kind tclass;
     288        StatementNode * sn;
     289        WaitForStmt * wfs;
     290        Expression * constant;
    310291        CondCtl * ifctl;
    311         ForCtrl * forctl;
    312         LabelNode * labels;
    313         InitializerNode * init;
    314         OperKinds oper;
     292        ForCtrl * fctl;
     293        OperKinds compop;
     294        LabelNode * label;
     295        InitializerNode * in;
     296        OperKinds op;
    315297        std::string * str;
    316         bool is_volatile;
    317         EnumHiding enum_hiding;
    318         ast::ExceptionKind except_kind;
    319         ast::GenericExpr * genexpr;
     298        bool flag;
     299        EnumHiding hide;
     300        CatchStmt::Kind catch_kind;
     301        GenericExpr * genexpr;
    320302}
    321303
    322 // ************************ TERMINAL TOKENS ********************************
     304//************************* TERMINAL TOKENS ********************************
    323305
    324306// keywords
     
    349331%token ATTRIBUTE EXTENSION                                                              // GCC
    350332%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
    351 %token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR WAITUNTIL // CFA
     333%token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR    // CFA
    352334%token DISABLE ENABLE TRY THROW THROWRESUME AT                  // CFA
    353335%token ASM                                                                                              // C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
     
    355337
    356338// names and constants: lexer differentiates between identifier and typedef names
    357 %token<tok> IDENTIFIER          TYPEDIMname             TYPEDEFname             TYPEGENname
    358 %token<tok> TIMEOUT                     WAND    WOR                     CATCH                   RECOVER                 CATCHRESUME             FIXUP           FINALLY         // CFA
     339%token<tok> IDENTIFIER          QUOTED_IDENTIFIER       TYPEDIMname             TYPEDEFname             TYPEGENname
     340%token<tok> TIMEOUT                     WOR                                     CATCH                   RECOVER                 CATCHRESUME             FIXUP           FINALLY         // CFA
    359341%token<tok> INTEGERconstant     CHARACTERconstant       STRINGliteral
    360342%token<tok> DIRECTIVE
     
    382364%type<tok> identifier                                   identifier_at                           identifier_or_type_name         attr_name
    383365%type<tok> quasi_keyword
    384 %type<expr> string_literal
     366%type<constant> string_literal
    385367%type<str> string_literal_list
    386368
    387 %type<enum_hiding> hide_opt                                     visible_hide_opt
     369%type<hide> hide_opt                                    visible_hide_opt
    388370
    389371// expressions
    390 %type<expr> constant
    391 %type<expr> tuple                                                       tuple_expression_list
    392 %type<oper> ptrref_operator                             unary_operator                          assignment_operator                     simple_assignment_operator      compound_assignment_operator
    393 %type<expr> primary_expression                  postfix_expression                      unary_expression
    394 %type<expr> cast_expression_list                        cast_expression                         exponential_expression          multiplicative_expression       additive_expression
    395 %type<expr> shift_expression                            relational_expression           equality_expression
    396 %type<expr> AND_expression                              exclusive_OR_expression         inclusive_OR_expression
    397 %type<expr> logical_AND_expression              logical_OR_expression
    398 %type<expr> conditional_expression              constant_expression                     assignment_expression           assignment_expression_opt
    399 %type<expr> comma_expression                            comma_expression_opt
    400 %type<expr> argument_expression_list_opt        argument_expression_list        argument_expression                     default_initializer_opt
     372%type<en> constant
     373%type<en> tuple                                                 tuple_expression_list
     374%type<op> ptrref_operator                               unary_operator                          assignment_operator                     simple_assignment_operator      compound_assignment_operator
     375%type<en> primary_expression                    postfix_expression                      unary_expression
     376%type<en> cast_expression_list                  cast_expression                         exponential_expression          multiplicative_expression       additive_expression
     377%type<en> shift_expression                              relational_expression           equality_expression
     378%type<en> AND_expression                                exclusive_OR_expression         inclusive_OR_expression
     379%type<en> logical_AND_expression                logical_OR_expression
     380%type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
     381%type<en> comma_expression                              comma_expression_opt
     382%type<en> argument_expression_list_opt  argument_expression_list        argument_expression                     default_initializer_opt
    401383%type<ifctl> conditional_declaration
    402 %type<forctl> for_control_expression            for_control_expression_list
    403 %type<oper> upupeq updown updowneq downupdowneq
    404 %type<expr> subrange
     384%type<fctl> for_control_expression              for_control_expression_list
     385%type<compop> upupeq updown updowneq downupdowneq
     386%type<en> subrange
    405387%type<decl> asm_name_opt
    406 %type<expr> asm_operands_opt                            asm_operands_list                       asm_operand
    407 %type<labels> label_list
    408 %type<expr> asm_clobbers_list_opt
    409 %type<is_volatile> asm_volatile_opt
    410 %type<expr> handler_predicate_opt
     388%type<en> asm_operands_opt                              asm_operands_list                       asm_operand
     389%type<label> label_list
     390%type<en> asm_clobbers_list_opt
     391%type<flag> asm_volatile_opt
     392%type<en> handler_predicate_opt
    411393%type<genexpr> generic_association              generic_assoc_list
    412394
    413395// statements
    414 %type<stmt> statement                                           labeled_statement                       compound_statement
    415 %type<stmt> statement_decl                              statement_decl_list                     statement_list_nodecl
    416 %type<stmt> selection_statement                 if_statement
    417 %type<clause> switch_clause_list_opt            switch_clause_list
    418 %type<expr> case_value
    419 %type<clause> case_clause                               case_value_list                         case_label                                      case_label_list
    420 %type<stmt> iteration_statement                 jump_statement
    421 %type<stmt> expression_statement                        asm_statement
    422 %type<stmt> with_statement
    423 %type<expr> with_clause_opt
    424 %type<stmt> exception_statement
    425 %type<clause> handler_clause                    finally_clause
    426 %type<except_kind> handler_key
    427 %type<stmt> mutex_statement
    428 %type<expr> when_clause                                 when_clause_opt                         waitfor         waituntil               timeout
    429 %type<stmt> waitfor_statement                           waituntil_statement
    430 %type<wfs> wor_waitfor_clause
    431 %type<wucn> waituntil_clause                    wand_waituntil_clause       wor_waituntil_clause
     396%type<sn> statement                                             labeled_statement                       compound_statement
     397%type<sn> statement_decl                                statement_decl_list                     statement_list_nodecl
     398%type<sn> selection_statement                   if_statement
     399%type<sn> switch_clause_list_opt                switch_clause_list
     400%type<en> case_value
     401%type<sn> case_clause                                   case_value_list                         case_label                                      case_label_list
     402%type<sn> iteration_statement                   jump_statement
     403%type<sn> expression_statement                  asm_statement
     404%type<sn> with_statement
     405%type<en> with_clause_opt
     406%type<sn> exception_statement                   handler_clause                          finally_clause
     407%type<catch_kind> handler_key
     408%type<sn> mutex_statement
     409%type<en> when_clause                                   when_clause_opt                         waitfor                                         timeout
     410%type<sn> waitfor_statement
     411%type<wfs> waitfor_clause
    432412
    433413// declarations
     
    441421%type<decl> assertion assertion_list assertion_list_opt
    442422
    443 %type<expr> bit_subrange_size_opt bit_subrange_size
     423%type<en> bit_subrange_size_opt bit_subrange_size
    444424
    445425%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type
     
    454434
    455435%type<decl> enumerator_list enum_type enum_type_nobody
    456 %type<init> enumerator_value_opt
     436%type<in> enumerator_value_opt
    457437
    458438%type<decl> external_definition external_definition_list external_definition_list_opt
     
    461441
    462442%type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract
    463 %type<expr> field field_name_list field_name fraction_constants_opt
     443%type<en> field field_name_list field_name fraction_constants_opt
    464444
    465445%type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
     
    502482%type<decl> typedef_name typedef_declaration typedef_expression
    503483
    504 %type<decl> variable_type_redeclarator variable_type_ptr variable_type_array variable_type_function
    505 %type<decl> general_function_declarator function_type_redeclarator function_type_array function_type_no_ptr function_type_ptr
     484%type<decl> variable_type_redeclarator type_ptr type_array type_function
    506485
    507486%type<decl> type_parameter_redeclarator type_parameter_ptr type_parameter_array type_parameter_function
     
    510489%type<decl> type_parameter type_parameter_list type_initializer_opt
    511490
    512 %type<expr> type_parameters_opt type_list array_type_list
     491%type<en> type_parameters_opt type_list array_type_list
    513492
    514493%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
     
    521500
    522501// initializers
    523 %type<init>  initializer initializer_list_opt initializer_opt
     502%type<in>  initializer initializer_list_opt initializer_opt
    524503
    525504// designators
    526 %type<expr>  designator designator_list designation
     505%type<en>  designator designator_list designation
    527506
    528507
     
    533512// Similar issues exit with the waitfor statement.
    534513
    535 // Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR
    536 // is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
     514// Order of these lines matters (low-to-high precedence). THEN is left associative over WOR/TIMEOUT/ELSE, WOR is left
     515// associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
    537516%precedence THEN                // rule precedence for IF/WAITFOR statement
    538 %precedence ANDAND              // token precedence for start of WAND in WAITFOR statement
    539 %precedence WAND                // token precedence for start of WAND in WAITFOR statement
    540 %precedence OROR                // token precedence for start of WOR in WAITFOR statement
    541517%precedence WOR                 // token precedence for start of WOR in WAITFOR statement
    542518%precedence TIMEOUT             // token precedence for start of TIMEOUT in WAITFOR statement
     
    616592constant:
    617593                // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration constant".
    618         INTEGERconstant                                                         { $$ = new ExpressionNode( build_constantInteger( yylloc, *$1 ) ); }
    619         | FLOATING_DECIMALconstant                                      { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
    620         | FLOATING_FRACTIONconstant                                     { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
    621         | FLOATINGconstant                                                      { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
    622         | CHARACTERconstant                                                     { $$ = new ExpressionNode( build_constantChar( yylloc, *$1 ) ); }
     594        INTEGERconstant                                                         { $$ = new ExpressionNode( build_constantInteger( *$1 ) ); }
     595        | FLOATING_DECIMALconstant                                      { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
     596        | FLOATING_FRACTIONconstant                                     { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
     597        | FLOATINGconstant                                                      { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
     598        | CHARACTERconstant                                                     { $$ = new ExpressionNode( build_constantChar( *$1 ) ); }
    623599        ;
    624600
    625601quasi_keyword:                                                                                  // CFA
    626602        TIMEOUT
    627         | WAND
    628603        | WOR
    629604        | CATCH
     
    646621
    647622string_literal:
    648         string_literal_list                                                     { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 ) ); }
     623        string_literal_list                                                     { $$ = build_constantStr( *$1 ); }
    649624        ;
    650625
     
    663638primary_expression:
    664639        IDENTIFIER                                                                                      // typedef name cannot be used as a variable name
    665                 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
     640                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    666641        | quasi_keyword
    667                 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
     642                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    668643        | TYPEDIMname                                                                           // CFA, generic length argument
    669644                // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); }
    670645                // { $$ = new ExpressionNode( build_varref( $1 ) ); }
    671                 { $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); }
     646                { $$ = new ExpressionNode( build_dimensionref( $1 ) ); }
    672647        | tuple
    673648        | '(' comma_expression ')'
    674649                { $$ = $2; }
    675650        | '(' compound_statement ')'                                            // GCC, lambda expression
    676                 { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); }
     651                { $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild<Statement>($2) ) ) ); }
    677652        | type_name '.' identifier                                                      // CFA, nested type
    678                 { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
     653                { $$ = new ExpressionNode( build_qualified_expr( $1, build_varref( $3 ) ) ); }
    679654        | type_name '.' '[' field_name_list ']'                         // CFA, nested type / tuple field selector
    680655                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     
    682657                {
    683658                        // add the missing control expression to the GenericExpr and return it
    684                         $5->control = maybeMoveBuild( $3 );
     659                        $5->control = maybeMoveBuild<Expression>( $3 );
    685660                        $$ = new ExpressionNode( $5 );
    686661                }
     
    708683                {
    709684                        // steal the association node from the singleton and delete the wrapper
    710                         assert( 1 == $3->associations.size() );
    711                         $1->associations.push_back( $3->associations.front() );
     685                        $1->associations.splice($1->associations.end(), $3->associations);
    712686                        delete $3;
    713687                        $$ = $1;
     
    719693                {
    720694                        // create a GenericExpr wrapper with one association pair
    721                         $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } );
     695                        $$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>( $3 ) } } );
    722696                }
    723697        | DEFAULT ':' assignment_expression
    724                 { $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); }
     698                { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>( $3 ) } } ); }
    725699        ;
    726700
     
    731705                // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
    732706                // Current: Commas in subscripts make tuples.
    733                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
     707                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
    734708        | postfix_expression '[' assignment_expression ']'
    735709                // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a
     
    737711                // little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is
    738712                // equivalent to the old x[i,j].
    739                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
     713                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
    740714        | constant '[' assignment_expression ']'                        // 3[a], 'a'[a], 3.5[a]
    741                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
     715                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
    742716        | string_literal '[' assignment_expression ']'          // "abc"[3], 3["abc"]
    743                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
     717                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }
    744718        | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
    745719                {
    746720                        Token fn;
    747721                        fn.str = new std::string( "?{}" );                      // location undefined - use location of '{'?
    748                         $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
     722                        $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    749723                }
    750724        | postfix_expression '(' argument_expression_list_opt ')'
    751                 { $$ = new ExpressionNode( build_func( yylloc, $1, $3 ) ); }
     725                { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
    752726        | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')'
    753727                // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; }
    754                 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ),
     728                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__builtin_va_arg") ) ),
    755729                                                                                           (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); }
    756730        | postfix_expression '`' identifier                                     // CFA, postfix call
    757                 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
     731                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); }
    758732        | constant '`' identifier                                                       // CFA, postfix call
    759                 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
     733                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); }
    760734        | string_literal '`' identifier                                         // CFA, postfix call
    761                 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
     735                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), new ExpressionNode( $1 ) ) ); }
    762736        | postfix_expression '.' identifier
    763                 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
     737                { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
    764738        | postfix_expression '.' INTEGERconstant                        // CFA, tuple index
    765                 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
     739                { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger( *$3 ) ) ); }
    766740        | postfix_expression FLOATING_FRACTIONconstant          // CFA, tuple index
    767                 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ) ) ); }
     741                { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
    768742        | postfix_expression '.' '[' field_name_list ']'        // CFA, tuple field selector
    769                 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
     743                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    770744        | postfix_expression '.' aggregate_control
    771                 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $3, $1 ) ); }
     745                { $$ = new ExpressionNode( build_keyword_cast( $3, $1 ) ); }
    772746        | postfix_expression ARROW identifier
    773                 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
     747                { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
    774748        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    775                 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
     749                { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
    776750        | postfix_expression ARROW '[' field_name_list ']'      // CFA, tuple field selector
    777                 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
     751                { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
    778752        | postfix_expression ICR
    779                 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::IncrPost, $1 ) ); }
     753                { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); }
    780754        | postfix_expression DECR
    781                 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::DecrPost, $1 ) ); }
     755                { $$ = new ExpressionNode( build_unary_ptr( OperKinds::DecrPost, $1 ) ); }
    782756        | '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal
    783                 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, new InitializerNode( $5, true ) ) ); }
     757                { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }
    784758        | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal
    785                 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
     759                { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
    786760        | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call
    787761                {
    788762                        Token fn;
    789763                        fn.str = new string( "^?{}" );                          // location undefined
    790                         $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
     764                        $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
    791765                }
    792766        ;
     
    807781        '@'                                                                                                     // CFA, default parameter
    808782                { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
    809                 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
     783                // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
    810784        | assignment_expression
    811785        ;
     
    819793        field_name
    820794        | FLOATING_DECIMALconstant field
    821                 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); }
     795                { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }
    822796        | FLOATING_DECIMALconstant '[' field_name_list ']'
    823                 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc, $3 ) ) ); }
     797                { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple( $3 ) ) ); }
    824798        | field_name '.' field
    825                 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
     799                { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
    826800        | field_name '.' '[' field_name_list ']'
    827                 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
     801                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    828802        | field_name ARROW field
    829                 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
     803                { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
    830804        | field_name ARROW '[' field_name_list ']'
    831                 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
     805                { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
    832806        ;
    833807
    834808field_name:
    835809        INTEGERconstant fraction_constants_opt
    836                 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc, *$1 ), $2 ) ); }
     810                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); }
    837811        | FLOATINGconstant fraction_constants_opt
    838                 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc, *$1 ), $2 ) ); }
     812                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
    839813        | identifier_at fraction_constants_opt                          // CFA, allow anonymous fields
    840814                {
    841                         $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc, $1 ), $2 ) );
     815                        $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
    842816                }
    843817        ;
     
    848822        | fraction_constants_opt FLOATING_FRACTIONconstant
    849823                {
    850                         ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 );
    851                         $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1, constant ) ) : new ExpressionNode( constant );
     824                        Expression * constant = build_field_name_FLOATING_FRACTIONconstant( *$2 );
     825                        $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1, constant ) ) : new ExpressionNode( constant );
    852826                }
    853827        ;
     
    859833        | constant
    860834        | string_literal
    861                 { $$ = $1; }
     835                { $$ = new ExpressionNode( $1 ); }
    862836        | EXTENSION cast_expression                                                     // GCC
    863837                { $$ = $2->set_extension( true ); }
     
    868842                {
    869843                        switch ( $1 ) {
    870                         case OperKinds::AddressOf:
    871                                 $$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) );
     844                          case OperKinds::AddressOf:
     845                                $$ = new ExpressionNode( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) );
    872846                                break;
    873                         case OperKinds::PointTo:
    874                                 $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) );
     847                          case OperKinds::PointTo:
     848                                $$ = new ExpressionNode( build_unary_val( $1, $2 ) );
    875849                                break;
    876                         case OperKinds::And:
    877                                 $$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) );
     850                          case OperKinds::And:
     851                                $$ = new ExpressionNode( new AddressExpr( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) ) );
    878852                                break;
    879                         default:
     853                          default:
    880854                                assert( false );
    881855                        }
    882856                }
    883857        | unary_operator cast_expression
    884                 { $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); }
     858                { $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
    885859        | ICR unary_expression
    886                 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Incr, $2 ) ); }
     860                { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Incr, $2 ) ); }
    887861        | DECR unary_expression
    888                 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Decr, $2 ) ); }
     862                { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Decr, $2 ) ); }
    889863        | SIZEOF unary_expression
    890                 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
     864                { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }
    891865        | SIZEOF '(' type_no_function ')'
    892                 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
     866                { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuildType( $3 ) ) ); }
    893867        | ALIGNOF unary_expression                                                      // GCC, variable alignment
    894                 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
     868                { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }
    895869        | ALIGNOF '(' type_no_function ')'                                      // GCC, type alignment
    896                 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
     870                { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); }
    897871        | OFFSETOF '(' type_no_function ',' identifier ')'
    898                 { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); }
     872                { $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) ); }
    899873        | TYPEID '(' type_no_function ')'
    900874                {
     
    921895        unary_expression
    922896        | '(' type_no_function ')' cast_expression
    923                 { $$ = new ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
     897                { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
    924898        | '(' aggregate_control '&' ')' cast_expression         // CFA
    925                 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
     899                { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
    926900        | '(' aggregate_control '*' ')' cast_expression         // CFA
    927                 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
     901                { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
    928902        | '(' VIRTUAL ')' cast_expression                                       // CFA
    929                 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }
     903                { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $4 ), maybeMoveBuildType( nullptr ) ) ); }
    930904        | '(' VIRTUAL type_no_function ')' cast_expression      // CFA
    931                 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
     905                { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $5 ), maybeMoveBuildType( $3 ) ) ); }
    932906        | '(' RETURN type_no_function ')' cast_expression       // CFA
    933                 { $$ = new ExpressionNode( build_cast( yylloc, $3, $5, ast::CastExpr::Return ) ); }
     907                { $$ = new ExpressionNode( build_cast( $3, $5, CastExpr::Return ) ); }
    934908        | '(' COERCE type_no_function ')' cast_expression       // CFA
    935909                { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; }
     
    937911                { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; }
    938912//      | '(' type_no_function ')' tuple
    939 //              { $$ = new ast::ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
     913//              { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
    940914        ;
    941915
     
    955929        cast_expression
    956930        | exponential_expression '\\' cast_expression
    957                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Exp, $1, $3 ) ); }
     931                { $$ = new ExpressionNode( build_binary_val( OperKinds::Exp, $1, $3 ) ); }
    958932        ;
    959933
     
    961935        exponential_expression
    962936        | multiplicative_expression '*' exponential_expression
    963                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mul, $1, $3 ) ); }
     937                { $$ = new ExpressionNode( build_binary_val( OperKinds::Mul, $1, $3 ) ); }
    964938        | multiplicative_expression '/' exponential_expression
    965                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Div, $1, $3 ) ); }
     939                { $$ = new ExpressionNode( build_binary_val( OperKinds::Div, $1, $3 ) ); }
    966940        | multiplicative_expression '%' exponential_expression
    967                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mod, $1, $3 ) ); }
     941                { $$ = new ExpressionNode( build_binary_val( OperKinds::Mod, $1, $3 ) ); }
    968942        ;
    969943
     
    971945        multiplicative_expression
    972946        | additive_expression '+' multiplicative_expression
    973                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Plus, $1, $3 ) ); }
     947                { $$ = new ExpressionNode( build_binary_val( OperKinds::Plus, $1, $3 ) ); }
    974948        | additive_expression '-' multiplicative_expression
    975                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Minus, $1, $3 ) ); }
     949                { $$ = new ExpressionNode( build_binary_val( OperKinds::Minus, $1, $3 ) ); }
    976950        ;
    977951
     
    979953        additive_expression
    980954        | shift_expression LS additive_expression
    981                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LShift, $1, $3 ) ); }
     955                { $$ = new ExpressionNode( build_binary_val( OperKinds::LShift, $1, $3 ) ); }
    982956        | shift_expression RS additive_expression
    983                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::RShift, $1, $3 ) ); }
     957                { $$ = new ExpressionNode( build_binary_val( OperKinds::RShift, $1, $3 ) ); }
    984958        ;
    985959
     
    987961        shift_expression
    988962        | relational_expression '<' shift_expression
    989                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LThan, $1, $3 ) ); }
     963                { $$ = new ExpressionNode( build_binary_val( OperKinds::LThan, $1, $3 ) ); }
    990964        | relational_expression '>' shift_expression
    991                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GThan, $1, $3 ) ); }
     965                { $$ = new ExpressionNode( build_binary_val( OperKinds::GThan, $1, $3 ) ); }
    992966        | relational_expression LE shift_expression
    993                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LEThan, $1, $3 ) ); }
     967                { $$ = new ExpressionNode( build_binary_val( OperKinds::LEThan, $1, $3 ) ); }
    994968        | relational_expression GE shift_expression
    995                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GEThan, $1, $3 ) ); }
     969                { $$ = new ExpressionNode( build_binary_val( OperKinds::GEThan, $1, $3 ) ); }
    996970        ;
    997971
     
    999973        relational_expression
    1000974        | equality_expression EQ relational_expression
    1001                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Eq, $1, $3 ) ); }
     975                { $$ = new ExpressionNode( build_binary_val( OperKinds::Eq, $1, $3 ) ); }
    1002976        | equality_expression NE relational_expression
    1003                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Neq, $1, $3 ) ); }
     977                { $$ = new ExpressionNode( build_binary_val( OperKinds::Neq, $1, $3 ) ); }
    1004978        ;
    1005979
     
    1007981        equality_expression
    1008982        | AND_expression '&' equality_expression
    1009                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitAnd, $1, $3 ) ); }
     983                { $$ = new ExpressionNode( build_binary_val( OperKinds::BitAnd, $1, $3 ) ); }
    1010984        ;
    1011985
     
    1013987        AND_expression
    1014988        | exclusive_OR_expression '^' AND_expression
    1015                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Xor, $1, $3 ) ); }
     989                { $$ = new ExpressionNode( build_binary_val( OperKinds::Xor, $1, $3 ) ); }
    1016990        ;
    1017991
     
    1019993        exclusive_OR_expression
    1020994        | inclusive_OR_expression '|' exclusive_OR_expression
    1021                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitOr, $1, $3 ) ); }
     995                { $$ = new ExpressionNode( build_binary_val( OperKinds::BitOr, $1, $3 ) ); }
    1022996        ;
    1023997
     
    1025999        inclusive_OR_expression
    10261000        | logical_AND_expression ANDAND inclusive_OR_expression
    1027                 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr ) ); }
     1001                { $$ = new ExpressionNode( build_and_or( $1, $3, true ) ); }
    10281002        ;
    10291003
     
    10311005        logical_AND_expression
    10321006        | logical_OR_expression OROR logical_AND_expression
    1033                 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr ) ); }
     1007                { $$ = new ExpressionNode( build_and_or( $1, $3, false ) ); }
    10341008        ;
    10351009
     
    10371011        logical_OR_expression
    10381012        | logical_OR_expression '?' comma_expression ':' conditional_expression
    1039                 { $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); }
     1013                { $$ = new ExpressionNode( build_cond( $1, $3, $5 ) ); }
    10401014                // FIX ME: computes $1 twice
    10411015        | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
    1042                 { $$ = new ExpressionNode( build_cond( yylloc, $1, $1, $4 ) ); }
     1016                { $$ = new ExpressionNode( build_cond( $1, $1, $4 ) ); }
    10431017        ;
    10441018
     
    10551029//                              SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
    10561030//                      } else {
    1057                                 $$ = new ExpressionNode( build_binary_val( yylloc, $2, $1, $3 ) );
     1031                                $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );
    10581032//                      } // if
    10591033                }
     
    11001074//              { $$ = new ExpressionNode( build_tuple( $3 ) ); }
    11011075        '[' ',' tuple_expression_list ']'
    1102                 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
     1076                { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
    11031077        | '[' push assignment_expression pop ',' tuple_expression_list ']'
    1104                 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); }
     1078                { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $6 ) ) )); }
    11051079        ;
    11061080
     
    11181092        assignment_expression
    11191093        | comma_expression ',' assignment_expression
    1120                 { $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
     1094                { $$ = new ExpressionNode( new CommaExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
    11211095        ;
    11221096
     
    11391113        | mutex_statement
    11401114        | waitfor_statement
    1141         | waituntil_statement
    11421115        | exception_statement
    11431116        | enable_disable_statement
     
    11451118        | asm_statement
    11461119        | DIRECTIVE
    1147                 { $$ = new StatementNode( build_directive( yylloc, $1 ) ); }
     1120                { $$ = new StatementNode( build_directive( $1 ) ); }
    11481121        ;
    11491122
     
    11511124                // labels cannot be identifiers 0 or 1
    11521125        identifier_or_type_name ':' attribute_list_opt statement
    1153                 { $$ = $4->add_label( yylloc, $1, $3 ); }
     1126                { $$ = $4->add_label( $1, $3 ); }
    11541127        | identifier_or_type_name ':' attribute_list_opt error // syntax error
    11551128                {
     
    11631136compound_statement:
    11641137        '{' '}'
    1165                 { $$ = new StatementNode( build_compound( yylloc, (StatementNode *)0 ) ); }
     1138                { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
    11661139        | '{' push
    11671140          local_label_declaration_opt                                           // GCC, local labels appear at start of block
    11681141          statement_decl_list                                                           // C99, intermix declarations and statements
    11691142          pop '}'
    1170                 { $$ = new StatementNode( build_compound( yylloc, $4 ) ); }
     1143                { $$ = new StatementNode( build_compound( $4 ) ); }
    11711144        ;
    11721145
     
    11991172expression_statement:
    12001173        comma_expression_opt ';'
    1201                 { $$ = new StatementNode( build_expr( yylloc, $1 ) ); }
     1174                { $$ = new StatementNode( build_expr( $1 ) ); }
     1175        | MUTEX '(' ')' comma_expression ';'
     1176                { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); }
    12021177        ;
    12031178
     
    12081183                { $$ = $2; }
    12091184        | SWITCH '(' comma_expression ')' case_clause
    1210                 { $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); }
     1185                { $$ = new StatementNode( build_switch( true, $3, $5 ) ); }
    12111186        | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    12121187                {
    1213                         StatementNode *sw = new StatementNode( build_switch( yylloc, true, $3, $8 ) );
     1188                        StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );
    12141189                        // The semantics of the declaration list is changed to include associated initialization, which is performed
    12151190                        // *before* the transfer to the appropriate case clause by hoisting the declarations into a compound
     
    12171192                        // therefore, are removed from the grammar even though C allows it. The change also applies to choose
    12181193                        // statement.
    1219                         $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
     1194                        $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    12201195                }
    12211196        | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, syntax error
    12221197                { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
    12231198        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    1224                 { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); }
     1199                { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
    12251200        | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    12261201                {
    1227                         StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) );
    1228                         $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
     1202                        StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );
     1203                        $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    12291204                }
    12301205        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, syntax error
     
    12351210        IF '(' conditional_declaration ')' statement            %prec THEN
    12361211                // explicitly deal with the shift/reduce conflict on if/else
    1237                 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
     1212                { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); }
    12381213        | IF '(' conditional_declaration ')' statement ELSE statement
    1239                 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
     1214                { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); }
    12401215        ;
    12411216
     
    12491224        | declaration comma_expression                                          // semi-colon separated
    12501225                { $$ = new CondCtl( $1, $2 ); }
    1251         ;
     1226        ;
    12521227
    12531228// CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
     
    12571232        constant_expression                                                     { $$ = $1; }
    12581233        | constant_expression ELLIPSIS constant_expression      // GCC, subrange
    1259                 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
     1234                { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
    12601235        | subrange                                                                                      // CFA, subrange
    12611236        ;
    12621237
    12631238case_value_list:                                                                                // CFA
    1264         case_value                                                                      { $$ = new ClauseNode( build_case( yylloc, $1 ) ); }
     1239        case_value                                                                      { $$ = new StatementNode( build_case( $1 ) ); }
    12651240                // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5"
    1266         | case_value_list ',' case_value                        { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3 ) ) ); }
     1241        | case_value_list ',' case_value                        { $$ = (StatementNode *)($1->set_last( new StatementNode( build_case( $3 ) ) ) ); }
    12671242        ;
    12681243
     
    12731248        | CASE case_value_list error                                            // syntax error
    12741249                { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; }
    1275         | DEFAULT ':'                                                           { $$ = new ClauseNode( build_default( yylloc ) ); }
     1250        | DEFAULT ':'                                                           { $$ = new StatementNode( build_default() ); }
    12761251                // A semantic check is required to ensure only one default clause per switch/choose statement.
    12771252        | DEFAULT error                                                                         //  syntax error
     
    12811256case_label_list:                                                                                // CFA
    12821257        case_label
    1283         | case_label_list case_label                            { $$ = $1->set_last( $2 ); }
     1258        | case_label_list case_label                            { $$ = (StatementNode *)( $1->set_last( $2 )); }
    12841259        ;
    12851260
    12861261case_clause:                                                                                    // CFA
    1287         case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( yylloc, $2 ) ); }
     1262        case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }
    12881263        ;
    12891264
     
    12961271switch_clause_list:                                                                             // CFA
    12971272        case_label_list statement_list_nodecl
    1298                 { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); }
     1273                { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }
    12991274        | switch_clause_list case_label_list statement_list_nodecl
    1300                 { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ); }
     1275                { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( $3 ) ) ) ) ); }
    13011276        ;
    13021277
    13031278iteration_statement:
    13041279        WHILE '(' ')' statement                                                         %prec THEN // CFA => while ( 1 )
    1305                 { $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); }
     1280                { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); }
    13061281        | WHILE '(' ')' statement ELSE statement                        // CFA
    13071282                {
    1308                         $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) );
    1309                         SemanticWarning( yylloc, Warning::SuperfluousElse );
     1283                        $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) );
     1284                        SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
    13101285                }
    13111286        | WHILE '(' conditional_declaration ')' statement       %prec THEN
    1312                 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
     1287                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
    13131288        | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
    1314                 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
     1289                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
    13151290        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    1316                 { $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); }
     1291                { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); }
    13171292        | DO statement WHILE '(' ')' ELSE statement                     // CFA
    13181293                {
    1319                         $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) );
    1320                         SemanticWarning( yylloc, Warning::SuperfluousElse );
     1294                        $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) );
     1295                        SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
    13211296                }
    13221297        | DO statement WHILE '(' comma_expression ')' ';'
    1323                 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ) ) ); }
     1298                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    13241299        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    1325                 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ), $8 ) ); }
     1300                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
    13261301        | FOR '(' ')' statement                                                         %prec THEN // CFA => for ( ;; )
    1327                 { $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); }
     1302                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
    13281303        | FOR '(' ')' statement ELSE statement                          // CFA
    13291304                {
    1330                         $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) );
    1331                         SemanticWarning( yylloc, Warning::SuperfluousElse );
     1305                        $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) );
     1306                        SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
    13321307                }
    13331308        | FOR '(' for_control_expression_list ')' statement     %prec THEN
    1334                 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
     1309                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
    13351310        | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
    1336                 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
     1311                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
    13371312        ;
    13381313
     
    13481323                        if ( $1->condition ) {
    13491324                                if ( $3->condition ) {
    1350                                         $1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr ) );
     1325                                        $1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true ) );
    13511326                                } // if
    13521327                        } else $1->condition = $3->condition;
    13531328                        if ( $1->change ) {
    13541329                                if ( $3->change ) {
    1355                                         $1->change->expr.reset( new ast::CommaExpr( yylloc, $1->change->expr.release(), $3->change->expr.release() ) );
     1330                                        $1->change->expr.reset( new CommaExpr( $1->change->expr.release(), $3->change->expr.release() ) );
    13561331                                } // if
    13571332                        } else $1->change = $3->change;
     
    13621337for_control_expression:
    13631338        ';' comma_expression_opt ';' comma_expression_opt
    1364                 { $$ = new ForCtrl( nullptr, $2, $4 ); }
     1339                { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); }
    13651340        | comma_expression ';' comma_expression_opt ';' comma_expression_opt
    1366                 {
    1367                         StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr;
    1368                         $$ = new ForCtrl( init, $3, $5 );
    1369                 }
     1341                { $$ = new ForCtrl( $1, $3, $5 ); }
    13701342        | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';'
    1371                 { $$ = new ForCtrl( new StatementNode( $1 ), $2, $4 ); }
     1343                { $$ = new ForCtrl( $1, $2, $4 ); }
    13721344
    13731345        | '@' ';' comma_expression                                                      // CFA, empty loop-index
    1374                 { $$ = new ForCtrl( nullptr, $3, nullptr ); }
     1346                { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, nullptr ); }
    13751347        | '@' ';' comma_expression ';' comma_expression         // CFA, empty loop-index
    1376                 { $$ = new ForCtrl( nullptr, $3, $5 ); }
     1348                { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, $5 ); }
    13771349
    13781350        | comma_expression                                                                      // CFA, anonymous loop-index
    1379                 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
     1351                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
    13801352        | downupdowneq comma_expression                                         // CFA, anonymous loop-index
    1381                 { $$ = forCtrl( yylloc, $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
     1353                { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
    13821354
    13831355        | comma_expression updowneq comma_expression            // CFA, anonymous loop-index
    1384                 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
     1356                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
    13851357        | '@' updowneq comma_expression                                         // CFA, anonymous loop-index
    13861358                {
    13871359                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1388                         else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
     1360                        else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
    13891361                }
    13901362        | comma_expression updowneq '@'                                         // CFA, anonymous loop-index
     
    13941366                }
    13951367        | comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
    1396                 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
     1368                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
    13971369        | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
    13981370                {
    13991371                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1400                         else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
     1372                        else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
    14011373                }
    14021374        | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index
     
    14171389
    14181390        | comma_expression ';' comma_expression                         // CFA
    1419                 { $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
     1391                { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
    14201392        | comma_expression ';' downupdowneq comma_expression // CFA
    1421                 { $$ = forCtrl( yylloc, $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
     1393                { $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
    14221394
    14231395        | comma_expression ';' comma_expression updowneq comma_expression // CFA
    1424                 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
     1396                { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
    14251397        | comma_expression ';' '@' updowneq comma_expression // CFA
    14261398                {
    14271399                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1428                         else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
     1400                        else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
    14291401                }
    14301402        | comma_expression ';' comma_expression updowneq '@' // CFA
     
    14321404                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14331405                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1434                         else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
     1406                        else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
    14351407                }
    14361408        | comma_expression ';' '@' updowneq '@'                         // CFA, error
     
    14381410
    14391411        | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA
    1440                 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
     1412                { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
    14411413        | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error
    14421414                {
    14431415                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1444                         else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, $7 );
     1416                        else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 );
    14451417                }
    14461418        | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA
     
    14481420                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14491421                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1450                         else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 );
     1422                        else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 );
    14511423                }
    14521424        | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA
    1453                 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
     1425                { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
    14541426        | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error
    14551427                {
    14561428                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1457                         else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, nullptr );
     1429                        else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr );
    14581430                }
    14591431        | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA
     
    14611433                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14621434                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1463                         else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr );
     1435                        else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr );
    14641436                }
    14651437        | comma_expression ';' '@' updowneq '@' '~' '@' // CFA
     
    14671439
    14681440        | declaration comma_expression                                          // CFA
    1469                 { $$ = forCtrl( yylloc, $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
     1441                { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
    14701442        | declaration downupdowneq comma_expression                     // CFA
    1471                 { $$ = forCtrl( yylloc, $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
     1443                { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
    14721444
    14731445        | declaration comma_expression updowneq comma_expression // CFA
    1474                 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
     1446                { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
    14751447        | declaration '@' updowneq comma_expression                     // CFA
    14761448                {
    14771449                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1478                         else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, NEW_ONE );
     1450                        else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE );
    14791451                }
    14801452        | declaration comma_expression updowneq '@'                     // CFA
     
    14821454                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14831455                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1484                         else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE );
     1456                        else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE );
    14851457                }
    14861458
    14871459        | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA
    1488                 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
     1460                { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
    14891461        | declaration '@' updowneq comma_expression '~' comma_expression // CFA
    14901462                {
    14911463                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1492                         else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, $6 );
     1464                        else $$ = forCtrl( $1, $4, $3, nullptr, $6 );
    14931465                }
    14941466        | declaration comma_expression updowneq '@' '~' comma_expression // CFA
     
    14961468                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14971469                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1498                         else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 );
     1470                        else $$ = forCtrl( $1, $2, $3, nullptr, $6 );
    14991471                }
    15001472        | declaration comma_expression updowneq comma_expression '~' '@' // CFA
    1501                 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
     1473                { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
    15021474        | declaration '@' updowneq comma_expression '~' '@' // CFA
    15031475                {
    15041476                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1505                         else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, nullptr );
     1477                        else $$ = forCtrl( $1, $4, $3, nullptr, nullptr );
    15061478                }
    15071479        | declaration comma_expression updowneq '@' '~' '@'     // CFA
     
    15091481                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    15101482                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1511                         else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr );
     1483                        else $$ = forCtrl( $1, $2, $3, nullptr, nullptr );
    15121484                }
    15131485        | declaration '@' updowneq '@' '~' '@'                          // CFA, error
     
    15241496                        SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
    15251497                }
    1526         ;
     1498        ;
    15271499
    15281500downupdowneq:
     
    15331505        | ErangeDownEq
    15341506                { $$ = OperKinds::GEThan; }
    1535         ;
     1507        ;
    15361508
    15371509updown:
     
    15401512        | ErangeDown
    15411513                { $$ = OperKinds::GThan; }
    1542         ;
     1514        ;
    15431515
    15441516updowneq:
     
    15481520        | ErangeDownEq
    15491521                { $$ = OperKinds::GEThan; }
    1550         ;
     1522        ;
    15511523
    15521524jump_statement:
    15531525        GOTO identifier_or_type_name ';'
    1554                 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); }
     1526                { $$ = new StatementNode( build_branch( $2, BranchStmt::Goto ) ); }
    15551527        | GOTO '*' comma_expression ';'                                         // GCC, computed goto
    15561528                // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3);
     
    15591531                // A semantic check is required to ensure fallthru appears only in the body of a choose statement.
    15601532        | fall_through_name ';'                                                         // CFA
    1561                 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); }
     1533                { $$ = new StatementNode( build_branch( BranchStmt::FallThrough ) ); }
    15621534        | fall_through_name identifier_or_type_name ';'         // CFA
    1563                 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); }
     1535                { $$ = new StatementNode( build_branch( $2, BranchStmt::FallThrough ) ); }
    15641536        | fall_through_name DEFAULT ';'                                         // CFA
    1565                 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); }
     1537                { $$ = new StatementNode( build_branch( BranchStmt::FallThroughDefault ) ); }
    15661538        | CONTINUE ';'
    15671539                // A semantic check is required to ensure this statement appears only in the body of an iteration statement.
    1568                 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); }
     1540                { $$ = new StatementNode( build_branch( BranchStmt::Continue ) ); }
    15691541        | CONTINUE identifier_or_type_name ';'                          // CFA, multi-level continue
    15701542                // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
    15711543                // the target of the transfer appears only at the start of an iteration statement.
    1572                 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); }
     1544                { $$ = new StatementNode( build_branch( $2, BranchStmt::Continue ) ); }
    15731545        | BREAK ';'
    15741546                // A semantic check is required to ensure this statement appears only in the body of an iteration statement.
    1575                 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); }
     1547                { $$ = new StatementNode( build_branch( BranchStmt::Break ) ); }
    15761548        | BREAK identifier_or_type_name ';'                                     // CFA, multi-level exit
    15771549                // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
    15781550                // the target of the transfer appears only at the start of an iteration statement.
    1579                 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); }
     1551                { $$ = new StatementNode( build_branch( $2, BranchStmt::Break ) ); }
    15801552        | RETURN comma_expression_opt ';'
    1581                 { $$ = new StatementNode( build_return( yylloc, $2 ) ); }
     1553                { $$ = new StatementNode( build_return( $2 ) ); }
    15821554        | RETURN '{' initializer_list_opt comma_opt '}' ';'
    15831555                { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
    15841556        | SUSPEND ';'
    1585                 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None ) ); }
     1557                { $$ = new StatementNode( build_suspend( nullptr ) ); }
    15861558        | SUSPEND compound_statement
    1587                 { $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None ) ); }
     1559                { $$ = new StatementNode( build_suspend( $2 ) ); }
    15881560        | SUSPEND COROUTINE ';'
    1589                 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); }
     1561                { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Coroutine ) ); }
    15901562        | SUSPEND COROUTINE compound_statement
    1591                 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); }
     1563                { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Coroutine ) ); }
    15921564        | SUSPEND GENERATOR ';'
    1593                 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); }
     1565                { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Generator ) ); }
    15941566        | SUSPEND GENERATOR compound_statement
    1595                 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); }
     1567                { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Generator ) ); }
    15961568        | THROW assignment_expression_opt ';'                           // handles rethrow
    1597                 { $$ = new StatementNode( build_throw( yylloc, $2 ) ); }
     1569                { $$ = new StatementNode( build_throw( $2 ) ); }
    15981570        | THROWRESUME assignment_expression_opt ';'                     // handles reresume
    1599                 { $$ = new StatementNode( build_resume( yylloc, $2 ) ); }
     1571                { $$ = new StatementNode( build_resume( $2 ) ); }
    16001572        | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume
    16011573                { $$ = new StatementNode( build_resume_at( $2, $4 ) ); }
     
    16091581with_statement:
    16101582        WITH '(' tuple_expression_list ')' statement
    1611                 { $$ = new StatementNode( build_with( yylloc, $3, $5 ) ); }
    1612         ;
    1613 
    1614 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so possibly change syntax to "with mutex".
     1583                { $$ = new StatementNode( build_with( $3, $5 ) ); }
     1584        ;
     1585
     1586// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".
    16151587mutex_statement:
    1616         MUTEX '(' argument_expression_list_opt ')' statement
    1617                 {
    1618                         if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; }
    1619                         $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) );
    1620                 }
     1588        MUTEX '(' argument_expression_list ')' statement
     1589                { $$ = new StatementNode( build_mutex( $3, $5 ) ); }
    16211590        ;
    16221591
     
    16291598                { $$ = nullptr; }
    16301599        | when_clause
     1600        ;
     1601
     1602waitfor:
     1603        WAITFOR '(' cast_expression ')'
     1604                { $$ = $3; }
     1605//      | WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'
     1606//              { $$ = (ExpressionNode *)$3->set_last( $5 ); }
     1607        | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
     1608                { $$ = (ExpressionNode *)($3->set_last( $5 )); }
    16311609        ;
    16321610
     
    16391617
    16401618timeout:
    1641         TIMEOUT '(' comma_expression ')'                        { $$ = $3; }
    1642         ;
    1643 
    1644 wor:
    1645         OROR
    1646         | WOR
    1647 
    1648 waitfor:
    1649         WAITFOR '(' cast_expression ')'
    1650                 { $$ = $3; }
    1651         | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
    1652                 { $$ = (ExpressionNode *)($3->set_last( $5 )); }
    1653         ;
    1654 
    1655 wor_waitfor_clause:
     1619        TIMEOUT '(' comma_expression ')'                        { $$ = $3; }
     1620        ;
     1621
     1622waitfor_clause:
    16561623        when_clause_opt waitfor statement                                       %prec THEN
    1657                 // Called first: create header for WaitForStmt.
    1658                 { $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); }
    1659         | wor_waitfor_clause wor when_clause_opt waitfor statement
    1660                 { $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
    1661         | wor_waitfor_clause wor when_clause_opt ELSE statement
    1662                 { $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); }
    1663         | wor_waitfor_clause wor when_clause_opt timeout statement      %prec THEN
    1664                 { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
     1624                { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); }
     1625        | when_clause_opt waitfor statement WOR waitfor_clause
     1626                { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); }
     1627        | when_clause_opt timeout statement                                     %prec THEN
     1628                { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); }
     1629        | when_clause_opt ELSE statement
     1630                { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
    16651631        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1666         | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
     1632        | when_clause_opt timeout statement WOR ELSE statement // syntax error
    16671633                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    1668         | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
    1669                 { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); }
     1634        | when_clause_opt timeout statement WOR when_clause ELSE statement
     1635                { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5 ); }
    16701636        ;
    16711637
    16721638waitfor_statement:
    1673         wor_waitfor_clause                                                                      %prec THEN
    1674                 { $$ = new StatementNode( $1 ); }
    1675         ;
    1676 
    1677 wand:
    1678         ANDAND
    1679         | WAND
    1680         ;
    1681 
    1682 waituntil:
    1683         WAITUNTIL '(' comma_expression ')'
    1684                 { $$ = $3; }
    1685         ;
    1686 
    1687 waituntil_clause:
    1688         when_clause_opt waituntil statement
    1689                 { $$ = build_waituntil_clause( yylloc, $1, $2, maybe_build_compound( yylloc, $3 ) ); }
    1690         | '(' wor_waituntil_clause ')'
    1691                 { $$ = $2; }
    1692         ;
    1693 
    1694 wand_waituntil_clause:
    1695         waituntil_clause                                                                        %prec THEN
    1696                 { $$ = $1; }
    1697         | waituntil_clause wand wand_waituntil_clause
    1698                 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::AND, $1, $3 ); }
    1699         ;
    1700 
    1701 wor_waituntil_clause:
    1702         wand_waituntil_clause
    1703                 { $$ = $1; }
    1704         | wor_waituntil_clause wor wand_waituntil_clause
    1705                 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, $1, $3 ); }
    1706         | wor_waituntil_clause wor when_clause_opt ELSE statement
    1707                 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_else( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    1708         | wor_waituntil_clause wor when_clause_opt timeout statement    %prec THEN
    1709                 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); }
    1710         // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1711         | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    1712                 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    1713         | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
    1714                 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1,
    1715                 new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR,
    1716                     build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ),
    1717                     build_waituntil_else( yylloc, $7, maybe_build_compound( yylloc, $9 ) ) ) ); }
    1718         ;
    1719 
    1720 waituntil_statement:
    1721         wor_waituntil_clause                                                            %prec THEN
    1722                 // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
    1723                 {
    1724             $$ = new StatementNode( build_waituntil_stmt( yylloc, $1 ) );
    1725             // $$ = new StatementNode( build_compound( yylloc, nullptr ) );
    1726         }
     1639        when_clause_opt waitfor statement                                       %prec THEN
     1640                { $$ = new StatementNode( build_waitfor( $2, $3, $1 ) ); }
     1641        | when_clause_opt waitfor statement WOR waitfor_clause
     1642                { $$ = new StatementNode( build_waitfor( $2, $3, $1, $5 ) ); }
    17271643        ;
    17281644
    17291645exception_statement:
    1730         TRY compound_statement handler_clause                                   %prec THEN
    1731                 { $$ = new StatementNode( build_try( yylloc, $2, $3, nullptr ) ); }
     1646        TRY compound_statement handler_clause                                   %prec THEN
     1647                { $$ = new StatementNode( build_try( $2, $3, 0 ) ); }
    17321648        | TRY compound_statement finally_clause
    1733                 { $$ = new StatementNode( build_try( yylloc, $2, nullptr, $3 ) ); }
     1649                { $$ = new StatementNode( build_try( $2, 0, $3 ) ); }
    17341650        | TRY compound_statement handler_clause finally_clause
    1735                 { $$ = new StatementNode( build_try( yylloc, $2, $3, $4 ) ); }
     1651                { $$ = new StatementNode( build_try( $2, $3, $4 ) ); }
    17361652        ;
    17371653
    17381654handler_clause:
    17391655        handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
    1740                 { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }
     1656                { $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); }
    17411657        | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
    1742                 { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }
     1658                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $5, $7, $9 ) ) ); }
    17431659        ;
    17441660
     
    17501666
    17511667handler_key:
    1752         CATCH                                                                           { $$ = ast::Terminate; }
    1753         | RECOVER                                                                       { $$ = ast::Terminate; }
    1754         | CATCHRESUME                                                           { $$ = ast::Resume; }
    1755         | FIXUP                                                                         { $$ = ast::Resume; }
     1668        CATCH                                                                           { $$ = CatchStmt::Terminate; }
     1669        | RECOVER                                                                       { $$ = CatchStmt::Terminate; }
     1670        | CATCHRESUME                                                           { $$ = CatchStmt::Resume; }
     1671        | FIXUP                                                                         { $$ = CatchStmt::Resume; }
    17561672        ;
    17571673
    17581674finally_clause:
    1759         FINALLY compound_statement                                      { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); }
     1675        FINALLY compound_statement                                      { $$ = new StatementNode( build_finally( $2 ) ); }
    17601676        ;
    17611677
     
    17831699asm_statement:
    17841700        ASM asm_volatile_opt '(' string_literal ')' ';'
    1785                 { $$ = new StatementNode( build_asm( yylloc, $2, $4, nullptr ) ); }
     1701                { $$ = new StatementNode( build_asm( $2, $4, 0 ) ); }
    17861702        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC
    1787                 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6 ) ); }
     1703                { $$ = new StatementNode( build_asm( $2, $4, $6 ) ); }
    17881704        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';'
    1789                 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8 ) ); }
     1705                { $$ = new StatementNode( build_asm( $2, $4, $6, $8 ) ); }
    17901706        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ':' asm_clobbers_list_opt ')' ';'
    1791                 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8, $10 ) ); }
     1707                { $$ = new StatementNode( build_asm( $2, $4, $6, $8, $10 ) ); }
    17921708        | ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';'
    1793                 { $$ = new StatementNode( build_asm( yylloc, $2, $5, nullptr, $8, $10, $12 ) ); }
     1709                { $$ = new StatementNode( build_asm( $2, $5, 0, $8, $10, $12 ) ); }
    17941710        ;
    17951711
     
    18151731asm_operand:                                                                                    // GCC
    18161732        string_literal '(' constant_expression ')'
    1817                 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
     1733                { $$ = new ExpressionNode( new AsmExpr( nullptr, $1, maybeMoveBuild<Expression>( $3 ) ) ); }
    18181734        | '[' IDENTIFIER ']' string_literal '(' constant_expression ')'
    1819                 {
    1820                         $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) );
    1821                         delete $2.str;
    1822                 }
     1735                { $$ = new ExpressionNode( new AsmExpr( $2, $4, maybeMoveBuild<Expression>( $6 ) ) ); }
    18231736        ;
    18241737
     
    18271740                { $$ = nullptr; }                                                               // use default argument
    18281741        | string_literal
    1829                 { $$ = $1; }
     1742                { $$ = new ExpressionNode( $1 ); }
    18301743        | asm_clobbers_list_opt ',' string_literal
    1831                 { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); }
     1744                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( $3 ) )); }
    18321745        ;
    18331746
     
    18351748        identifier
    18361749                {
    1837                         $$ = new LabelNode(); $$->labels.emplace_back( yylloc, *$1 );
     1750                        $$ = new LabelNode(); $$->labels.push_back( *$1 );
    18381751                        delete $1;                                                                      // allocated by lexer
    18391752                }
    18401753        | label_list ',' identifier
    18411754                {
    1842                         $$ = $1; $1->labels.emplace_back( yylloc, *$3 );
     1755                        $$ = $1; $1->labels.push_back( *$3 );
    18431756                        delete $3;                                                                      // allocated by lexer
    18441757                }
     
    18911804                {
    18921805                        // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" );
    1893                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     1806                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    18941807                        //   printf( "\tattr %s\n", attr->name.c_str() );
    18951808                        // } // for
     
    19011814static_assert:
    19021815        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    1903                 { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 ) ); }
     1816                { $$ = DeclarationNode::newStaticAssert( $3, $5 ); }
    19041817        | STATICASSERT '(' constant_expression ')' ';'          // CFA
    1905                 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); }
     1818                { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }
    19061819
    19071820// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
     
    19671880//      '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
    19681881//              {
    1969 //                      $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, nullptr, true );
     1882//                      $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, 0, true );
    19701883//              }
    19711884//      '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
    19721885//              {
    19731886//                      typedefTable.setNextIdentifier( *$5 );
    1974 //                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
     1887//                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
    19751888//              }
    19761889//      | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
    19771890//              {
    19781891//                      typedefTable.setNextIdentifier( *$5 );
    1979 //                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
     1892//                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
    19801893//              }
    19811894//      | '[' ']' typegen_name
     
    19891902        cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
    19901903                // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
    1991                 { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
     1904                { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 )->addQualifiers( $8 ); }
    19921905        | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
    1993                 { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
     1906                { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 )->addQualifiers( $8 ); }
    19941907        ;
    19951908
     
    20271940                {
    20281941                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" );
    2029                         if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) {
    2030                                 SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr;
    2031                         } else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3
     1942                        $$ = $3->addType( $2 )->addTypedef();
    20321943                }
    20331944        | typedef_declaration pop ',' push declarator
     
    20371948                }
    20381949        | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
    2039                 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
     1950                {
     1951                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" );
     1952                        $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
     1953                }
    20401954        | type_specifier TYPEDEF declarator
    2041                 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
     1955                {
     1956                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" );
     1957                        $$ = $3->addType( $1 )->addTypedef();
     1958                }
    20421959        | type_specifier TYPEDEF type_qualifier_list declarator
    2043                 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
     1960                {
     1961                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" );
     1962                        $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 );
     1963                }
    20441964        ;
    20451965
     
    20481968        TYPEDEF identifier '=' assignment_expression
    20491969                {
    2050                         SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     1970                        SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    20511971                }
    20521972        | typedef_expression pop ',' push identifier '=' assignment_expression
    20531973                {
    2054                         SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     1974                        SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    20551975                }
    20561976        ;
     
    20621982        | typedef_expression                                                            // deprecated GCC, naming expression type
    20631983        | sue_declaration_specifier
    2064                 {
    2065                         assert( $1->type );
    2066                         if ( $1->type->qualifiers.any() ) {                     // CV qualifiers ?
    2067                                 SemanticError( yylloc, "Useless type qualifier(s) in empty declaration." ); $$ = nullptr;
    2068                         }
    2069                         // enums are never empty declarations because there must have at least one enumeration.
    2070                         if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ?
    2071                                 SemanticError( yylloc, "Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;
    2072                         }
    2073                 }
    20741984        ;
    20751985
     
    20771987                // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static
    20781988                // storage-class
    2079         variable_declarator asm_name_opt initializer_opt
     1989        declarator asm_name_opt initializer_opt
    20801990                { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
    2081         | variable_type_redeclarator asm_name_opt initializer_opt
    2082                 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
    2083 
    2084         | general_function_declarator asm_name_opt
    2085                 { $$ = $1->addAsmName( $2 )->addInitializer( nullptr ); }
    2086         | general_function_declarator asm_name_opt '=' VOID
    2087                 { $$ = $1->addAsmName( $2 )->addInitializer( new InitializerNode( true ) ); }
    2088 
    20891991        | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
    20901992                { $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
    20911993        ;
    20921994
    2093 general_function_declarator:
    2094         function_type_redeclarator
    2095         | function_declarator
    2096         ;
    2097 
    20981995declaration_specifier:                                                                  // type specifier + storage class
    20991996        basic_declaration_specifier
     1997        | sue_declaration_specifier
    21001998        | type_declaration_specifier
    2101         | sue_declaration_specifier
    2102         | sue_declaration_specifier invalid_types
    2103                 {
    2104                         SemanticError( yylloc, ::toString( "Missing ';' after end of ",
    2105                                 $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ),
    2106                                 " declaration" ) );
    2107                         $$ = nullptr;
    2108                 }
    2109         ;
    2110 
    2111 invalid_types:
    2112         aggregate_key
    2113         | basic_type_name
    2114         | indirect_type
    21151999        ;
    21162000
     
    21292013        basic_type_specifier
    21302014        | sue_type_specifier
     2015                {
     2016                        // printf( "sue_type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
     2017                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2018                        //   printf( "\tattr %s\n", attr->name.c_str() );
     2019                        // } // for
     2020                }
    21312021        | type_type_specifier
    21322022        ;
     
    21752065                { $$ = DeclarationNode::newTypeQualifier( Type::Atomic ); }
    21762066        | forall
    2177                 { $$ = DeclarationNode::newForall( $1 ); }
    21782067        ;
    21792068
    21802069forall:
    21812070        FORALL '(' type_parameter_list ')'                                      // CFA
    2182                 { $$ = $3; }
     2071                { $$ = DeclarationNode::newForall( $3 ); }
    21832072        ;
    21842073
     
    23372226                { $$ = DeclarationNode::newTypeof( $3 ); }
    23382227        | BASETYPEOF '(' type ')'                                                       // CFA: basetypeof( x ) y;
    2339                 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ), true ); }
     2228                { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ), true ); }
    23402229        | BASETYPEOF '(' comma_expression ')'                           // CFA: basetypeof( a+b ) y;
    23412230                { $$ = DeclarationNode::newTypeof( $3, true ); }
     
    23502239                {
    23512240                        // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2352                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2241                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    23532242                        //   printf( "\tattr %s\n", attr->name.c_str() );
    23542243                        // } // for
     
    23662255                {
    23672256                        // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2368                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2257                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    23692258                        //   printf( "\tattr %s\n", attr->name.c_str() );
    23702259                        // } // for
     
    24442333                {
    24452334                        // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2446                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2335                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    24472336                        //   printf( "\tattr %s\n", attr->name.c_str() );
    24482337                        // } // for
     
    24682357          '{' field_declaration_list_opt '}' type_parameters_opt
    24692358                {
     2359                        // printf( "aggregate_type1 %s\n", $3.str->c_str() );
     2360                        // if ( $2 )
     2361                        //      for ( Attribute * attr: reverseIterate( $2->attributes ) ) {
     2362                        //              printf( "copySpecifiers12 %s\n", attr->name.c_str() );
     2363                        //      } // for
    24702364                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     2365                        // printf( "aggregate_type2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
     2366                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2367                        //      printf( "aggregate_type3 %s\n", attr->name.c_str() );
     2368                        // } // for
    24712369                }
    24722370        | aggregate_key attribute_list_opt TYPEDEFname          // unqualified type name
     
    24772375          '{' field_declaration_list_opt '}' type_parameters_opt
    24782376                {
     2377                        // printf( "AGG3\n" );
    24792378                        DeclarationNode::newFromTypedef( $3 );
    24802379                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    24872386          '{' field_declaration_list_opt '}' type_parameters_opt
    24882387                {
     2388                        // printf( "AGG4\n" );
    24892389                        DeclarationNode::newFromTypeGen( $3, nullptr );
    24902390                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    25132413                        // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and
    25142414                        // delete newFromTypeGen.
    2515                         if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) {
    2516                                 $$ = $3->addQualifiers( $2 );
    2517                         } else {
    2518                                 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
    2519                                 $3->type->symbolic.name = nullptr;                      // copied to $$
    2520                                 $3->type->symbolic.actuals = nullptr;
    2521                                 delete $3;
    2522                         }
     2415                        $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
     2416                        $3->type->symbolic.name = nullptr;
     2417                        $3->type->symbolic.actuals = nullptr;
     2418                        delete $3;
    25232419                }
    25242420        ;
     
    25312427aggregate_data:
    25322428        STRUCT vtable_opt
    2533                 { $$ = ast::AggregateDecl::Struct; }
     2429                { $$ = AggregateDecl::Struct; }
    25342430        | UNION
    2535                 { $$ = ast::AggregateDecl::Union; }
     2431                { $$ = AggregateDecl::Union; }
    25362432        | EXCEPTION                                                                                     // CFA
    2537                 { $$ = ast::AggregateDecl::Exception; }
    2538           //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; }
     2433                { $$ = AggregateDecl::Exception; }
     2434          //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    25392435        ;
    25402436
    25412437aggregate_control:                                                                              // CFA
    25422438        MONITOR
    2543                 { $$ = ast::AggregateDecl::Monitor; }
     2439                { $$ = AggregateDecl::Monitor; }
    25442440        | MUTEX STRUCT
    2545                 { $$ = ast::AggregateDecl::Monitor; }
     2441                { $$ = AggregateDecl::Monitor; }
    25462442        | GENERATOR
    2547                 { $$ = ast::AggregateDecl::Generator; }
     2443                { $$ = AggregateDecl::Generator; }
    25482444        | MUTEX GENERATOR
    2549                 {
    2550                         SemanticError( yylloc, "monitor generator is currently unimplemented." );
    2551                         $$ = ast::AggregateDecl::NoAggregate;
    2552                 }
     2445                { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    25532446        | COROUTINE
    2554                 { $$ = ast::AggregateDecl::Coroutine; }
     2447                { $$ = AggregateDecl::Coroutine; }
    25552448        | MUTEX COROUTINE
    2556                 {
    2557                         SemanticError( yylloc, "monitor coroutine is currently unimplemented." );
    2558                         $$ = ast::AggregateDecl::NoAggregate;
    2559                 }
     2449                { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    25602450        | THREAD
    2561                 { $$ = ast::AggregateDecl::Thread; }
     2451                { $$ = AggregateDecl::Thread; }
    25622452        | MUTEX THREAD
    2563                 {
    2564                         SemanticError( yylloc, "monitor thread is currently unimplemented." );
    2565                         $$ = ast::AggregateDecl::NoAggregate;
    2566                 }
     2453                { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    25672454        ;
    25682455
     
    25802467                        $$ = fieldDecl( $1, $2 );
    25812468                        // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2582                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2469                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    25832470                        //   printf( "\tattr %s\n", attr->name.c_str() );
    25842471                        // } // for
     
    25862473        | EXTENSION type_specifier field_declaring_list_opt ';' // GCC
    25872474                { $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
    2588         | STATIC type_specifier field_declaring_list_opt ';' // CFA
    2589                 { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
    25902475        | INLINE type_specifier field_abstract_list_opt ';'     // CFA
    25912476                {
     
    25982483                }
    25992484        | INLINE aggregate_control ';'                                          // CFA
    2600                 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
     2485                { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
    26012486        | typedef_declaration ';'                                                       // CFA
    26022487        | cfa_field_declaring_list ';'                                          // CFA, new style field declaration
     
    26242509                { $$ = $1->addBitfield( $2 ); }
    26252510        | variable_type_redeclarator bit_subrange_size_opt
    2626                 // A semantic check is required to ensure bit_subrange only appears on integral types.
    2627                 { $$ = $1->addBitfield( $2 ); }
    2628         | function_type_redeclarator bit_subrange_size_opt
    26292511                // A semantic check is required to ensure bit_subrange only appears on integral types.
    26302512                { $$ = $1->addBitfield( $2 ); }
     
    26812563                { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
    26822564        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    2683                 {
    2684                         if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() )
     2565                {
     2566                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 )
    26852567                        { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    26862568
     
    26932575        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
    26942576                {
    2695                         if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
     2577                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    26962578                        typedefTable.makeTypedef( *$6 );
    26972579                }
     
    27272609enum_type_nobody:                                                                               // enum - {...}
    27282610        ENUM attribute_list_opt identifier
    2729                 { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, nullptr, false, false )->addQualifiers( $2 ); }
     2611                { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, 0, false, false )->addQualifiers( $2 ); }
    27302612        | ENUM attribute_list_opt type_name
    2731                 { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, nullptr, false, false )->addQualifiers( $2 ); }
     2613                { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false, false )->addQualifiers( $2 ); }
    27322614        ;
    27332615
     
    28692751type_no_function:                                                                               // sizeof, alignof, cast (constructor)
    28702752        cfa_abstract_declarator_tuple                                           // CFA
    2871         | type_specifier                                                                        // cannot be type_specifier_nobody, e.g., (struct S {}){} is a thing
     2753        | type_specifier
    28722754        | type_specifier abstract_declarator
    28732755                { $$ = $2->addType( $1 ); }
     
    29142796        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    29152797        | identifier_at ':'                                                                     // GCC, field name
    2916                 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
     2798                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    29172799        ;
    29182800
     
    29262808designator:
    29272809        '.' identifier_at                                                                       // C99, field name
    2928                 { $$ = new ExpressionNode( build_varref( yylloc, $2 ) ); }
     2810                { $$ = new ExpressionNode( build_varref( $2 ) ); }
    29292811        | '[' push assignment_expression pop ']'                        // C99, single array element
    29302812                // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple.
     
    29332815                { $$ = $3; }
    29342816        | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
    2935                 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); }
     2817                { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $3 ), maybeMoveBuild<Expression>( $5 ) ) ); }
    29362818        | '.' '[' push field_name_list pop ']'                          // CFA, tuple field selector
    29372819                { $$ = $4; }
     
    29732855                {
    29742856                        typedefTable.addToScope( *$2, TYPEDEFname, "9" );
    2975                         if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
    2976                         if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
    2977                         if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
     2857                        if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
     2858                        if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
     2859                        if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
    29782860                }
    29792861          type_initializer_opt assertion_list_opt
     
    29862868                {
    29872869                        typedefTable.addToScope( *$2, TYPEDIMname, "9" );
    2988                         $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 );
     2870                        $$ = DeclarationNode::newTypeParam( TypeDecl::Dimension, $2 );
    29892871                }
    29902872        // | type_specifier identifier_parameter_declarator
    29912873        | assertion_list
    2992                 { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
     2874                { $$ = DeclarationNode::newTypeParam( TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
    29932875        ;
    29942876
    29952877new_type_class:                                                                                 // CFA
    29962878        // empty
    2997                 { $$ = ast::TypeDecl::Otype; }
     2879                { $$ = TypeDecl::Otype; }
    29982880        | '&'
    2999                 { $$ = ast::TypeDecl::Dtype; }
     2881                { $$ = TypeDecl::Dtype; }
    30002882        | '*'
    3001                 { $$ = ast::TypeDecl::DStype; }                                         // dtype + sized
     2883                { $$ = TypeDecl::DStype; }                                              // dtype + sized
    30022884        // | '(' '*' ')'
    3003         //      { $$ = ast::TypeDecl::Ftype; }
     2885        //      { $$ = TypeDecl::Ftype; }
    30042886        | ELLIPSIS
    3005                 { $$ = ast::TypeDecl::Ttype; }
     2887                { $$ = TypeDecl::Ttype; }
    30062888        ;
    30072889
    30082890type_class:                                                                                             // CFA
    30092891        OTYPE
    3010                 { $$ = ast::TypeDecl::Otype; }
     2892                { $$ = TypeDecl::Otype; }
    30112893        | DTYPE
    3012                 { $$ = ast::TypeDecl::Dtype; }
     2894                { $$ = TypeDecl::Dtype; }
    30132895        | FTYPE
    3014                 { $$ = ast::TypeDecl::Ftype; }
     2896                { $$ = TypeDecl::Ftype; }
    30152897        | TTYPE
    3016                 { $$ = ast::TypeDecl::Ttype; }
     2898                { $$ = TypeDecl::Ttype; }
    30172899        ;
    30182900
     
    30402922type_list:                                                                                              // CFA
    30412923        type
    3042                 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
     2924                { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
    30432925        | assignment_expression
    30442926        | type_list ',' type
    3045                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
     2927                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
    30462928        | type_list ',' assignment_expression
    30472929                { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
     
    30682950                {
    30692951                        typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
    3070                         $$ = DeclarationNode::newTypeDecl( $1, nullptr );
     2952                        $$ = DeclarationNode::newTypeDecl( $1, 0 );
    30712953                }
    30722954        | identifier_or_type_name '(' type_parameter_list ')'
     
    30792961trait_specifier:                                                                                // CFA
    30802962        TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    3081                 {
    3082                         SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
    3083                         $$ = DeclarationNode::newTrait( $2, $4, nullptr );
    3084                 }
    3085         | forall TRAIT identifier_or_type_name '{' '}'          // alternate
    3086                 { $$ = DeclarationNode::newTrait( $3, $1, nullptr ); }
     2963                { $$ = DeclarationNode::newTrait( $2, $4, 0 ); }
    30872964        | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    3088                 {
    3089                         SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
    3090                         $$ = DeclarationNode::newTrait( $2, $4, $8 );
    3091                 }
    3092         | forall TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate
    3093                 { $$ = DeclarationNode::newTrait( $3, $1, $6 ); }
     2965                { $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
    30942966        ;
    30952967
     
    31503022external_definition:
    31513023        DIRECTIVE
    3152                 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc, $1 ) ) ); }
     3024                { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( $1 ) ) ); }
    31533025        | declaration
    3154                 {
    3155                         // Variable declarations of anonymous types requires creating a unique type-name across multiple translation
    3156                         // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is
    3157                         // disallowed at the moment.
    3158                         if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) {
    3159                                 if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) {
    3160                                         SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr;
    3161                                 } else if ( $1->type->aggInst.aggregate->aggregate.anon ) { // handles struct or union
    3162                                         SemanticError( yylloc, "extern anonymous struct/union is currently unimplemented." ); $$ = nullptr;
    3163                                 }
    3164                         }
    3165                 }
    31663026        | IDENTIFIER IDENTIFIER
    31673027                { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; }
     
    31833043                }
    31843044        | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
    3185                 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc, false, $3, nullptr ) ) ); }
     3045                { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); }
    31863046        | EXTERN STRINGliteral
    31873047                {
    31883048                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    3189                         linkage = ast::Linkage::update( yylloc, linkage, $2 );
     3049                        linkage = LinkageSpec::update( yylloc, linkage, $2 );
    31903050                }
    31913051          up external_definition down
     
    31983058                {
    31993059                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    3200                         linkage = ast::Linkage::update( yylloc, linkage, $2 );
     3060                        linkage = LinkageSpec::update( yylloc, linkage, $2 );
    32013061                }
    32023062          '{' up external_definition_list_opt down '}'
     
    32093069        | type_qualifier_list
    32103070                {
    3211                         if ( $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3071                        if ( $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    32123072                        if ( $1->type->forall ) forall = true;          // remember generic type
    32133073                }
     
    32153075                {
    32163076                        distQual( $5, $1 );
    3217                         forall = false;
     3077                        forall = false;
    32183078                        $$ = $5;
    32193079                }
    32203080        | declaration_qualifier_list
    32213081                {
    3222                         if ( $1->type && $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3082                        if ( $1->type && $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    32233083                        if ( $1->type && $1->type->forall ) forall = true; // remember generic type
    32243084                }
     
    32263086                {
    32273087                        distQual( $5, $1 );
    3228                         forall = false;
     3088                        forall = false;
    32293089                        $$ = $5;
    32303090                }
    32313091        | declaration_qualifier_list type_qualifier_list
    32323092                {
    3233                         if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3093                        if ( ($1->type && $1->type->qualifiers.val) || ($2->type && $2->type->qualifiers.val) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    32343094                        if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type
    32353095                }
     
    32373097                {
    32383098                        distQual( $6, $1->addQualifiers( $2 ) );
    3239                         forall = false;
     3099                        forall = false;
    32403100                        $$ = $6;
    32413101                }
     
    32813141                        $$ = $2->addFunctionBody( $4, $3 )->addType( $1 );
    32823142                }
    3283         | declaration_specifier function_type_redeclarator with_clause_opt compound_statement
     3143        | declaration_specifier variable_type_redeclarator with_clause_opt compound_statement
    32843144                {
    32853145                        rebindForall( $1, $2 );
     
    33173177        | variable_type_redeclarator
    33183178        | function_declarator
    3319         | function_type_redeclarator
    33203179        ;
    33213180
    33223181subrange:
    33233182        constant_expression '~' constant_expression                     // CFA, integer subrange
    3324                 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
     3183                { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
    33253184        ;
    33263185
     
    33313190                {
    33323191                        DeclarationNode * name = new DeclarationNode();
    3333                         name->asmName = maybeMoveBuild( $3 );
     3192                        name->asmName = $3;
    33343193                        $$ = name->addQualifiers( $5 );
    33353194                }
     
    34283287variable_ptr:
    34293288        ptrref_operator variable_declarator
    3430                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3289                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    34313290        | ptrref_operator type_qualifier_list variable_declarator
    34323291                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    34443303        | '(' attribute_list variable_ptr ')' array_dimension
    34453304                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3446         | '(' variable_array ')' multi_array_dimension          // redundant parenthesis
     3305        | '(' variable_array ')' multi_array_dimension          // redundant parenthesis
    34473306                { $$ = $2->addArray( $4 ); }
    34483307        | '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis
     
    34923351function_ptr:
    34933352        ptrref_operator function_declarator
    3494                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3353                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    34953354        | ptrref_operator type_qualifier_list function_declarator
    34963355                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    35443403KR_function_ptr:
    35453404        ptrref_operator KR_function_declarator
    3546                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3405                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    35473406        | ptrref_operator type_qualifier_list KR_function_declarator
    35483407                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    35683427        ;
    35693428
    3570 // This pattern parses a declaration for a variable that redefines a type name, e.g.:
     3429// This pattern parses a declaration for a variable or function prototype that redefines a type name, e.g.:
    35713430//
    35723431//              typedef int foo;
     
    35743433//                 int foo; // redefine typedef name in new scope
    35753434//              }
     3435//
     3436// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
     3437// and functions versus pointers to arrays and functions.
    35763438
    35773439paren_type:
     
    35883450        paren_type attribute_list_opt
    35893451                { $$ = $1->addQualifiers( $2 ); }
    3590         | variable_type_ptr
    3591         | variable_type_array attribute_list_opt
     3452        | type_ptr
     3453        | type_array attribute_list_opt
    35923454                { $$ = $1->addQualifiers( $2 ); }
    3593         | variable_type_function attribute_list_opt
     3455        | type_function attribute_list_opt
    35943456                { $$ = $1->addQualifiers( $2 ); }
    35953457        ;
    35963458
    3597 variable_type_ptr:
     3459type_ptr:
    35983460        ptrref_operator variable_type_redeclarator
    3599                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3461                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    36003462        | ptrref_operator type_qualifier_list variable_type_redeclarator
    36013463                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    3602         | '(' variable_type_ptr ')' attribute_list_opt          // redundant parenthesis
     3464        | '(' type_ptr ')' attribute_list_opt                           // redundant parenthesis
    36033465                { $$ = $2->addQualifiers( $4 ); }
    3604         | '(' attribute_list variable_type_ptr ')' attribute_list_opt // redundant parenthesis
     3466        | '(' attribute_list type_ptr ')' attribute_list_opt // redundant parenthesis
    36053467                { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
    36063468        ;
    36073469
    3608 variable_type_array:
     3470type_array:
    36093471        paren_type array_dimension
    36103472                { $$ = $1->addArray( $2 ); }
    3611         | '(' variable_type_ptr ')' array_dimension
     3473        | '(' type_ptr ')' array_dimension
    36123474                { $$ = $2->addArray( $4 ); }
    3613         | '(' attribute_list variable_type_ptr ')' array_dimension
     3475        | '(' attribute_list type_ptr ')' array_dimension
    36143476                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3615         | '(' variable_type_array ')' multi_array_dimension     // redundant parenthesis
     3477        | '(' type_array ')' multi_array_dimension                      // redundant parenthesis
    36163478                { $$ = $2->addArray( $4 ); }
    3617         | '(' attribute_list variable_type_array ')' multi_array_dimension // redundant parenthesis
     3479        | '(' attribute_list type_array ')' multi_array_dimension // redundant parenthesis
    36183480                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3619         | '(' variable_type_array ')'                                           // redundant parenthesis
     3481        | '(' type_array ')'                                                            // redundant parenthesis
    36203482                { $$ = $2; }
    3621         | '(' attribute_list variable_type_array ')'            // redundant parenthesis
     3483        | '(' attribute_list type_array ')'                                     // redundant parenthesis
    36223484                { $$ = $3->addQualifiers( $2 ); }
    36233485        ;
    36243486
    3625 variable_type_function:
    3626         '(' variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    3627                 { $$ = $2->addParamList( $6 ); }
    3628         | '(' attribute_list variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    3629                 { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); }
    3630         | '(' variable_type_function ')'                                        // redundant parenthesis
    3631                 { $$ = $2; }
    3632         | '(' attribute_list variable_type_function ')'         // redundant parenthesis
    3633                 { $$ = $3->addQualifiers( $2 ); }
    3634         ;
    3635 
    3636 // This pattern parses a declaration for a function prototype that redefines a type name.  It precludes declaring an
    3637 // array of functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to
    3638 // arrays and functions.
    3639 
    3640 function_type_redeclarator:
    3641         function_type_no_ptr attribute_list_opt
    3642                 { $$ = $1->addQualifiers( $2 ); }
    3643         | function_type_ptr
    3644         | function_type_array attribute_list_opt
    3645                 { $$ = $1->addQualifiers( $2 ); }
    3646         ;
    3647 
    3648 function_type_no_ptr:
     3487type_function:
    36493488        paren_type '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    36503489                { $$ = $1->addParamList( $4 ); }
    3651         | '(' function_type_ptr ')' '(' push parameter_type_list_opt pop ')'
     3490        | '(' type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    36523491                { $$ = $2->addParamList( $6 ); }
    3653         | '(' attribute_list function_type_ptr ')' '(' push parameter_type_list_opt pop ')'
     3492        | '(' attribute_list type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    36543493                { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); }
    3655         | '(' function_type_no_ptr ')'                                          // redundant parenthesis
     3494        | '(' type_function ')'                                                         // redundant parenthesis
    36563495                { $$ = $2; }
    3657         | '(' attribute_list function_type_no_ptr ')'           // redundant parenthesis
    3658                 { $$ = $3->addQualifiers( $2 ); }
    3659         ;
    3660 
    3661 function_type_ptr:
    3662         ptrref_operator function_type_redeclarator
    3663                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    3664         | ptrref_operator type_qualifier_list function_type_redeclarator
    3665                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    3666         | '(' function_type_ptr ')' attribute_list_opt
    3667                 { $$ = $2->addQualifiers( $4 ); }
    3668         | '(' attribute_list function_type_ptr ')' attribute_list_opt
    3669                 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
    3670         ;
    3671 
    3672 function_type_array:
    3673         '(' function_type_ptr ')' array_dimension
    3674                 { $$ = $2->addArray( $4 ); }
    3675         | '(' attribute_list function_type_ptr ')' array_dimension
    3676                 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3677         | '(' function_type_array ')' multi_array_dimension     // redundant parenthesis
    3678                 { $$ = $2->addArray( $4 ); }
    3679         | '(' attribute_list function_type_array ')' multi_array_dimension // redundant parenthesis
    3680                 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3681         | '(' function_type_array ')'                                           // redundant parenthesis
    3682                 { $$ = $2; }
    3683         | '(' attribute_list function_type_array ')'            // redundant parenthesis
     3496        | '(' attribute_list type_function ')'                          // redundant parenthesis
    36843497                { $$ = $3->addQualifiers( $2 ); }
    36853498        ;
     
    37043517identifier_parameter_ptr:
    37053518        ptrref_operator identifier_parameter_declarator
    3706                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3519                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    37073520        | ptrref_operator type_qualifier_list identifier_parameter_declarator
    37083521                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    37613574type_parameter_ptr:
    37623575        ptrref_operator type_parameter_redeclarator
    3763                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3576                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    37643577        | ptrref_operator type_qualifier_list type_parameter_redeclarator
    37653578                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    38043617abstract_ptr:
    38053618        ptrref_operator
    3806                 { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
     3619                { $$ = DeclarationNode::newPointer( 0, $1 ); }
    38073620        | ptrref_operator type_qualifier_list
    38083621                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    38093622        | ptrref_operator abstract_declarator
    3810                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3623                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    38113624        | ptrref_operator type_qualifier_list abstract_declarator
    38123625                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    38373650                // Only the first dimension can be empty.
    38383651        '[' ']'
    3839                 { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
     3652                { $$ = DeclarationNode::newArray( 0, 0, false ); }
    38403653        | '[' ']' multi_array_dimension
    3841                 { $$ = DeclarationNode::newArray( nullptr, nullptr, false )->addArray( $3 ); }
     3654                { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $3 ); }
    38423655                // Cannot use constant_expression because of tuples => semantic check
    38433656        | '[' push assignment_expression pop ',' comma_expression ']' // CFA
    3844                 { $$ = DeclarationNode::newArray( $3, nullptr, false )->addArray( DeclarationNode::newArray( $6, nullptr, false ) ); }
     3657                { $$ = DeclarationNode::newArray( $3, 0, false )->addArray( DeclarationNode::newArray( $6, 0, false ) ); }
    38453658                // { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; }
    38463659        | '[' push array_type_list pop ']'                                      // CFA
     
    38513664array_type_list:
    38523665        basic_type_name
    3853                 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
     3666                { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
    38543667        | type_name
    3855                 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
     3668                { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
    38563669        | assignment_expression upupeq assignment_expression
    38573670        | array_type_list ',' basic_type_name
    3858                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    3859         | array_type_list ',' type_name
    3860                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
     3671                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
     3672        | array_type_list ',' type_name 
     3673                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
    38613674        | array_type_list ',' assignment_expression upupeq assignment_expression
    38623675        ;
     
    38673680        | ErangeUpEq
    38683681                { $$ = OperKinds::LEThan; }
    3869         ;
     3682        ;
    38703683
    38713684multi_array_dimension:
    38723685        '[' push assignment_expression pop ']'
    3873                 { $$ = DeclarationNode::newArray( $3, nullptr, false ); }
     3686                { $$ = DeclarationNode::newArray( $3, 0, false ); }
    38743687        | '[' push '*' pop ']'                                                          // C99
    38753688                { $$ = DeclarationNode::newVarArray( 0 ); }
    38763689        | multi_array_dimension '[' push assignment_expression pop ']'
    3877                 { $$ = $1->addArray( DeclarationNode::newArray( $4, nullptr, false ) ); }
     3690                { $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
    38783691        | multi_array_dimension '[' push '*' pop ']'            // C99
    38793692                { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
     
    39723785array_parameter_1st_dimension:
    39733786        '[' ']'
    3974                 { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
     3787                { $$ = DeclarationNode::newArray( 0, 0, false ); }
    39753788                // multi_array_dimension handles the '[' '*' ']' case
    39763789        | '[' push type_qualifier_list '*' pop ']'                      // remaining C99
    39773790                { $$ = DeclarationNode::newVarArray( $3 ); }
    39783791        | '[' push type_qualifier_list pop ']'
    3979                 { $$ = DeclarationNode::newArray( nullptr, $3, false ); }
     3792                { $$ = DeclarationNode::newArray( 0, $3, false ); }
    39803793                // multi_array_dimension handles the '[' assignment_expression ']' case
    39813794        | '[' push type_qualifier_list assignment_expression pop ']'
     
    40063819variable_abstract_ptr:
    40073820        ptrref_operator
    4008                 { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
     3821                { $$ = DeclarationNode::newPointer( 0, $1 ); }
    40093822        | ptrref_operator type_qualifier_list
    40103823                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    40113824        | ptrref_operator variable_abstract_declarator
    4012                 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3825                { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    40133826        | ptrref_operator type_qualifier_list variable_abstract_declarator
    40143827                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    40523865                // No SUE declaration in parameter list.
    40533866        ptrref_operator type_specifier_nobody
    4054                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3867                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    40553868        | type_qualifier_list ptrref_operator type_specifier_nobody
    40563869                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    40573870        | ptrref_operator cfa_abstract_function
    4058                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3871                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    40593872        | type_qualifier_list ptrref_operator cfa_abstract_function
    40603873                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    40613874        | ptrref_operator cfa_identifier_parameter_declarator_tuple
    4062                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3875                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    40633876        | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple
    40643877                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
     
    40693882                // shift/reduce conflict with new-style empty (void) function return type.
    40703883        '[' ']' type_specifier_nobody
    4071                 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
     3884                { $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    40723885        | cfa_array_parameter_1st_dimension type_specifier_nobody
    40733886                { $$ = $2->addNewArray( $1 ); }
    40743887        | '[' ']' multi_array_dimension type_specifier_nobody
    4075                 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
     3888                { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    40763889        | cfa_array_parameter_1st_dimension multi_array_dimension type_specifier_nobody
    40773890                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
     
    40803893
    40813894        | '[' ']' cfa_identifier_parameter_ptr
    4082                 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
     3895                { $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    40833896        | cfa_array_parameter_1st_dimension cfa_identifier_parameter_ptr
    40843897                { $$ = $2->addNewArray( $1 ); }
    40853898        | '[' ']' multi_array_dimension cfa_identifier_parameter_ptr
    4086                 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
     3899                { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    40873900        | cfa_array_parameter_1st_dimension multi_array_dimension cfa_identifier_parameter_ptr
    40883901                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
     
    41403953cfa_abstract_ptr:                                                                               // CFA
    41413954        ptrref_operator type_specifier
    4142                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3955                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    41433956        | type_qualifier_list ptrref_operator type_specifier
    41443957                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    41453958        | ptrref_operator cfa_abstract_function
    4146                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3959                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    41473960        | type_qualifier_list ptrref_operator cfa_abstract_function
    41483961                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    41493962        | ptrref_operator cfa_abstract_declarator_tuple
    4150                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3963                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
    41513964        | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple
    41523965                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
  • src/Parser/parserutility.cc

    r24d6572 r34b4268  
    1010// Created On       : Sat May 16 15:30:39 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Mar  1 10:42:00 2023
    13 // Update Count     : 9
     12// Last Modified On : Tus Jul 18 10:12:00 2017
     13// Update Count     : 8
    1414//
    1515
     
    1919#include <string>                // for string
    2020
    21 #include "AST/Expr.hpp"          // for UntypedExpr, CastExpr, ConstantExpr
    22 #include "AST/Type.hpp"          // for BasicType, ZeroType, BasicType::Kind...
     21#include "SynTree/Constant.h"    // for Constant
     22#include "SynTree/Expression.h"  // for UntypedExpr, CastExpr, ConstantExpr
     23#include "SynTree/Type.h"        // for BasicType, ZeroType, BasicType::Kind...
    2324
    2425// rewrite
     
    2728//    if ( (int)(x != 0) ) ...
    2829
    29 ast::Expr * notZeroExpr( ast::Expr * orig ) {
    30         return ( !orig ) ? nullptr : new ast::CastExpr( orig->location,
    31                 ast::UntypedExpr::createCall( orig->location,
    32                         "?!=?",
    33                         {
    34                                 orig,
    35                                 new ast::ConstantExpr( orig->location,
    36                                         new ast::ZeroType(),
    37                                         "0",
    38                                         std::optional<unsigned long long>( 0 )
    39                                 ),
    40                         }
    41                 ),
    42                 new ast::BasicType( ast::BasicType::SignedInt )
    43         );
     30Expression *notZeroExpr( Expression *orig ) {
     31        if( !orig ) return nullptr;
     32        UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) );
     33        comparison->get_args().push_back( orig );
     34        comparison->get_args().push_back( new ConstantExpr( Constant( new ZeroType( noQualifiers ), "0", (unsigned long long int)0 ) ) );
     35        return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    4436}
    4537
  • src/Parser/parserutility.h

    r24d6572 r34b4268  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // parserutility.h -- Collected utilities for the parser.
     7// parserutility.h --
    88//
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 15:31:46 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr  4 14:03:00 2023
    13 // Update Count     : 7
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:32:58 2017
     13// Update Count     : 4
    1414//
    1515
    1616#pragma once
    1717
    18 #include "AST/Copy.hpp"            // for shallowCopy
    19 namespace ast {
    20         class Expr;
    21 }
     18class Expression;
    2219
    23 ast::Expr * notZeroExpr( ast::Expr *orig );
    24 
    25 template< typename T >
    26 static inline auto maybeBuild( T * orig ) -> decltype(orig->build()) {
    27         return (orig) ? orig->build() : nullptr;
    28 }
    29 
    30 template< typename T >
    31 static inline auto maybeMoveBuild( T * orig ) -> decltype(orig->build()) {
    32         auto ret = maybeBuild<T>(orig);
    33         delete orig;
    34         return ret;
    35 }
    36 
    37 template<typename node_t>
    38 node_t * maybeCopy( node_t const * node ) {
    39         return node ? ast::shallowCopy( node ) : nullptr;
    40 }
     20Expression *notZeroExpr( Expression *orig );
    4121
    4222// Local Variables: //
  • src/ResolvExpr/AlternativeFinder.cc

    r24d6572 r34b4268  
    1414//
    1515
    16 #include "AlternativeFinder.h"
    17 
    1816#include <algorithm>               // for copy
    1917#include <cassert>                 // for strict_dynamic_cast, assert, assertf
     
    2826
    2927#include "CompilationState.h"      // for resolvep
    30 #include "AdjustExprType.hpp"      // for adjustExprType
    3128#include "Alternative.h"           // for AltList, Alternative
     29#include "AlternativeFinder.h"
    3230#include "AST/Expr.hpp"
    3331#include "AST/SymbolTable.hpp"
    3432#include "AST/Type.hpp"
    35 #include "CastCost.hpp"            // for castCost
    3633#include "Common/SemanticError.h"  // for SemanticError
    3734#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
    38 #include "ConversionCost.h"        // for conversionCost
    3935#include "Cost.h"                  // for Cost, Cost::zero, operator<<, Cost...
    4036#include "ExplodedActual.h"        // for ExplodedActual
    4137#include "InitTweak/InitTweak.h"   // for getFunctionName
    42 #include "PolyCost.hpp"            // for polyCost
    4338#include "RenameVars.h"            // for RenameVars, global_renamer
    4439#include "ResolveAssertions.h"     // for resolveAssertions
    4540#include "ResolveTypeof.h"         // for resolveTypeof
    4641#include "Resolver.h"              // for resolveStmtExpr
    47 #include "SpecCost.hpp"            // for specCost
    4842#include "SymTab/Indexer.h"        // for Indexer
    4943#include "SymTab/Mangler.h"        // for Mangler
     
    5751#include "Tuples/Explode.h"        // for explode
    5852#include "Tuples/Tuples.h"         // for isTtype, handleTupleAssignment
    59 #include "typeops.h"               // for combos
    6053#include "Unify.h"                 // for unify
     54#include "typeops.h"               // for adjustExprType, polyCost, castCost
    6155
    6256#define PRINT( text ) if ( resolvep ) { text }
  • src/ResolvExpr/AlternativeFinder.h

    r24d6572 r34b4268  
    3434namespace ResolvExpr {
    3535        struct ArgPack;
    36 
    37         Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
    38                 const SymTab::Indexer & indexer, const TypeEnvironment & env );
    39 
    40         void referenceToRvalueConversion( Expression *& expr, Cost & cost );
    4136
    4237        /// First index is which argument, second index is which alternative for that argument,
  • src/ResolvExpr/Candidate.cpp

    r24d6572 r34b4268  
    1717
    1818#include <iostream>
    19 #include <sstream>
    2019
    2120#include "AST/Print.hpp"
     
    4544        sorted.reserve(cands.size());
    4645        for(const auto & c : cands) {
    47                 std::ostringstream ss;
     46                std::stringstream ss;
    4847                print( ss, *c, indent );
    4948                sorted.push_back(ss.str());
  • src/ResolvExpr/CandidateFinder.cpp

    r24d6572 r34b4268  
    2323#include <vector>
    2424
    25 #include "AdjustExprType.hpp"
    2625#include "Candidate.hpp"
    2726#include "CompilationState.h"
    2827#include "Cost.h"
    29 #include "CastCost.hpp"
    30 #include "PolyCost.hpp"
    31 #include "SpecCost.hpp"
    32 #include "ConversionCost.h"
    3328#include "ExplodedArg.hpp"
    3429#include "RenameVars.h"           // for renameTyVars
     
    408403                                                        unify(
    409404                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    410                                                                 newResult.open )
     405                                                                newResult.open, symtab )
    411406                                                ) {
    412407                                                        finalResults.emplace_back( std::move( newResult ) );
     
    479474                                )
    480475
    481                                 if ( unify( paramType, argType, env, need, have, open ) ) {
     476                                if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
    482477                                        unsigned nextExpl = results[i].nextExpl + 1;
    483478                                        if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
     
    498493                                        ast::OpenVarSet open = results[i].open;
    499494
    500                                         if ( unify( paramType, cnst->result, env, need, have, open ) ) {
     495                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    501496                                                results.emplace_back(
    502497                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),
     
    541536
    542537                                // attempt to unify types
    543                                 if ( unify( paramType, argType, env, need, have, open ) ) {
     538                                if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
    544539                                        // add new result
    545540                                        results.emplace_back(
     
    708703                                if ( selfFinder.strictMode ) {
    709704                                        if ( ! unifyExact(
    710                                                 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden() ) // xxx - is no widening correct?
     705                                                returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden(), symtab ) // xxx - is no widening correct?
    711706                                        ) {
    712707                                                // unification failed, do not pursue this candidate
     
    716711                                else {
    717712                                        if ( ! unify(
    718                                                 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen )
     713                                                returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    719714                                        ) {
    720715                                                // unification failed, do not pursue this candidate
     
    11611156
    11621157                                // unification run for side-effects
    1163                                 unify( toType, cand->expr->result, cand->env, need, have, open );
     1158                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    11641159                                Cost thisCost =
    11651160                                        (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)
     
    15021497                                                if (
    15031498                                                        unify(
    1504                                                                 r2->expr->result, r3->expr->result, env, need, have, open,
     1499                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
    15051500                                                                common )
    15061501                                                ) {
     
    15761571                                        if (
    15771572                                                unify(
    1578                                                         r1->expr->result, r2->expr->result, env, need, have, open,
     1573                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
    15791574                                                        common )
    15801575                                        ) {
     
    16821677
    16831678                                        // unification run for side-effects
    1684                                         bool canUnify = unify( toType, cand->expr->result, env, need, have, open );
     1679                                        bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );
    16851680                                        (void) canUnify;
    16861681                                        Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
  • src/ResolvExpr/CandidateFinder.hpp

    r24d6572 r34b4268  
    6565        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    6666
    67 /// Create an expression that preforms reference to rvalue conversion on
    68 /// the given expression and update the cost of the expression.
    69 const ast::Expr * referenceToRvalueConversion(
    70         const ast::Expr * expr, Cost & cost );
    71 
    7267} // namespace ResolvExpr
    7368
  • src/ResolvExpr/CastCost.cc

    r24d6572 r34b4268  
    1313// Update Count     : 9
    1414//
    15 
    16 #include "CastCost.hpp"
    1715
    1816#include <cassert>                       // for assert
     
    2422#include "ConversionCost.h"              // for ConversionCost
    2523#include "Cost.h"                        // for Cost, Cost::infinity
    26 #include "ResolvExpr/ConversionCost.h"   // for conversionCost
    27 #include "ResolvExpr/PtrsCastable.hpp"   // for ptrsCastable
    2824#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment, EqvClass
    29 #include "ResolvExpr/typeops.h"          // for ptrsCastable
    30 #include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    3125#include "SymTab/Indexer.h"              // for Indexer
    3226#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    3327#include "SynTree/Type.h"                // for PointerType, Type, TypeInstType
     28#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
    3429
    3530#if 0
     
    165160                                if (
    166161                                        pointerType->qualifiers <= ptr->qualifiers
    167                                         && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, env )
     162                                        && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
    168163                                ) {
    169164                                        cost = Cost::safe;
     
    232227        )
    233228
    234         if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
     229        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
    235230                PRINT( std::cerr << "compatible!" << std::endl; )
    236231                if (dynamic_cast<const ast::ZeroType *>(dst) || dynamic_cast<const ast::OneType *>(dst)) {
  • src/ResolvExpr/CommonType.cc

    r24d6572 r34b4268  
    1414//
    1515
    16 #include "CommonType.hpp"
    17 
    1816#include <cassert>                       // for strict_dynamic_cast
    1917#include <map>                           // for _Rb_tree_const_iterator
     
    2119
    2220#include "AST/Decl.hpp"
    23 #include "AST/Pass.hpp"
    2421#include "AST/Type.hpp"
    2522#include "Common/PassVisitor.h"
     
    676673                const ast::Type * type2;
    677674                WidenMode widen;
     675                const ast::SymbolTable & symtab;
    678676                ast::TypeEnvironment & tenv;
    679677                const ast::OpenVarSet & open;
     
    685683
    686684                CommonType_new(
    687                         const ast::Type * t2, WidenMode w,
     685                        const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
    688686                        ast::TypeEnvironment & env, const ast::OpenVarSet & o,
    689687                        ast::AssertionSet & need, ast::AssertionSet & have )
    690                 : type2( t2 ), widen( w ), tenv( env ), open( o ), need (need), have (have) ,result() {}
     688                : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), need (need), have (have) ,result() {}
    691689
    692690                void previsit( const ast::Node * ) { visit_children = false; }
     
    766764                                        ast::AssertionSet need, have;
    767765                                        if ( ! tenv.bindVar(
    768                                                 var, voidPtr->base, entry->second, need, have, open, widen )
     766                                                var, voidPtr->base, entry->second, need, have, open, widen, symtab )
    769767                                        ) return;
    770768                                }
     
    779777                                ast::OpenVarSet newOpen{ open };
    780778                                if (enumInst->base->base
    781                                 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) {
     779                                && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen, symtab)) {
    782780                                        result = type1;
    783781                                        return true;
     
    816814
    817815                                        ast::OpenVarSet newOpen{ open };
    818                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) {
     816                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    819817                                                result = pointer;
    820818                                                if ( q1.val != q2.val ) {
     
    859857                                                                if (unifyExact(
    860858                                                                        arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
    861                                                                         noWiden() )) {
     859                                                                        noWiden(), symtab )) {
    862860                                                                                break;
    863861
     
    868866                                                                if (unifyExact(
    869867                                                                        tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open,
    870                                                                         noWiden() )) {
     868                                                                        noWiden(), symtab )) {
    871869                                                                                break;
    872870
     
    892890
    893891                                                                                if ( ! unifyExact(
    894                                                                                         base1, base2, tenv, need, have, open, noWiden() )
     892                                                                                        base1, base2, tenv, need, have, open, noWiden(), symtab )
    895893                                                                                ) return;
    896894                                                                        }       
     
    912910
    913911                                                                                if ( ! unifyExact(
    914                                                                                         base1, base2, tenv, need, have, open, noWiden() )
     912                                                                                        base1, base2, tenv, need, have, open, noWiden(), symtab )
    915913                                                                                ) return;
    916914                                                                        }       
     
    920918                                                        }
    921919                                                        else if (! unifyExact(
    922                                                                 arg1, arg2, tenv, need, have, open, noWiden() )) return;
     920                                                                arg1, arg2, tenv, need, have, open, noWiden(), symtab )) return;
    923921
    924922                                                        ++crnt1; ++crnt2;
     
    930928                                                        if (! unifyExact(
    931929                                                                t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
    932                                                                 noWiden() )) return;
     930                                                                noWiden(), symtab )) return;
    933931                                                } else if ( crnt2 != end2 ) {
    934932                                                        // try unifying empty tuple with ttype
     
    937935                                                        if (! unifyExact(
    938936                                                                tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open,
    939                                                                 noWiden() )) return;
     937                                                                noWiden(), symtab )) return;
    940938                                                }
    941939                                                if ((f1->returns.size() == 0 && f2->returns.size() == 0)
    942                                                   || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden()))) {
     940                                                  || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden(), symtab))) {
    943941                                                        result = pointer;
    944942
     
    997995
    998996                                        ast::OpenVarSet newOpen{ open };
    999                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) {
     997                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    1000998                                                result = ref;
    1001999                                                if ( q1.val != q2.val ) {
     
    10121010                        } else {
    10131011                                if (!dynamic_cast<const ast::EnumInstType *>(type2))
    1014                                         result = commonType( type2, ref, tenv, need, have, open, widen );
     1012                                        result = commonType( type2, ref, tenv, need, have, open, widen, symtab );
    10151013                        }
    10161014                }
     
    10301028                void postvisit( const ast::EnumInstType * enumInst ) {
    10311029                        if (!dynamic_cast<const ast::EnumInstType *>(type2))
    1032                                 result = commonType( type2, enumInst, tenv, need, have, open, widen);
     1030                                result = commonType( type2, enumInst, tenv, need, have, open, widen, symtab);
    10331031                }
    10341032
    10351033                void postvisit( const ast::TraitInstType * ) {}
    10361034
    1037                 void postvisit( const ast::TypeInstType * inst ) {}
     1035                void postvisit( const ast::TypeInstType * inst ) {
     1036                        if ( ! widen.first ) return;
     1037                        if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
     1038                                if ( const ast::Type * base =
     1039                                                strict_dynamic_cast< const ast::TypeDecl * >( nt )->base
     1040                                ) {
     1041                                        ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers;
     1042
     1043                                        // force t{1,2} to be cloned if their qualifiers must be mutated
     1044                                        ast::ptr< ast::Type > t1{ base }, t2{ type2 };
     1045                                        reset_qualifiers( t1, q1 );
     1046                                        reset_qualifiers( t2 );
     1047
     1048                                        ast::OpenVarSet newOpen{ open };
     1049                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     1050                                                result = type2;
     1051                                                reset_qualifiers( result, q1 | q2 );
     1052                                        } else {
     1053                                                tryResolveWithTypedEnum( t1 );
     1054                                        }
     1055                                }
     1056                        }
     1057                }
    10381058
    10391059                void postvisit( const ast::TupleType * tuple) {
     
    10981118                ast::ptr< ast::Type > handleReference(
    10991119                        const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen,
    1100                         ast::TypeEnvironment & env,
     1120                        const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    11011121                        const ast::OpenVarSet & open
    11021122                ) {
     
    11061126
    11071127                        // need unify to bind type variables
    1108                         if ( unify( t1, t2, env, have, need, newOpen, common ) ) {
     1128                        if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) {
    11091129                                ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers;
    11101130                                PRINT(
     
    11301150                        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    11311151                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1132                         const ast::OpenVarSet & open, WidenMode widen
     1152                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
    11331153        ) {
    11341154                unsigned depth1 = type1->referenceDepth();
     
    11451165                        if ( depth1 > depth2 ) {
    11461166                                assert( ref1 );
    1147                                 result = handleReference( ref1->base, type2, widen, env, open );
     1167                                result = handleReference( ref1->base, type2, widen, symtab, env, open );
    11481168                        } else {  // implies depth1 < depth2
    11491169                                assert( ref2 );
    1150                                 result = handleReference( type1, ref2->base, widen, env, open );
     1170                                result = handleReference( type1, ref2->base, widen, symtab, env, open );
    11511171                        }
    11521172
     
    11661186                }
    11671187                // otherwise both are reference types of the same depth and this is handled by the visitor
    1168                 ast::Pass<CommonType_new> visitor{ type2, widen, env, open, need, have };
     1188                ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open, need, have };
    11691189                type1->accept( visitor );
    1170                 // ast::ptr< ast::Type > result = visitor.core.result;
    1171 
    1172                 return visitor.core.result;
     1190                ast::ptr< ast::Type > result = visitor.core.result;
     1191
     1192                // handling for opaque type declarations (?)
     1193                if ( ! result && widen.second ) {
     1194                        if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) {
     1195                                if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
     1196                                        auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt );
     1197                                        if ( type->base ) {
     1198                                                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
     1199                                                ast::OpenVarSet newOpen{ open };
     1200
     1201                                                // force t{1,2} to be cloned if its qualifiers must be stripped, so that
     1202                                                // type1 and type->base are left unchanged; calling convention forces
     1203                                                // {type1,type->base}->strong_ref >= 1
     1204                                                ast::ptr<ast::Type> t1{ type1 }, t2{ type->base };
     1205                                                reset_qualifiers( t1 );
     1206                                                reset_qualifiers( t2, q1 );
     1207
     1208                                                if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) {
     1209                                                        result = t1;
     1210                                                        reset_qualifiers( result, q1 | q2 );
     1211                                                }
     1212                                        }
     1213                                }
     1214                        }
     1215                }
     1216
     1217                return result;
    11731218        }
    11741219
  • src/ResolvExpr/ConversionCost.cc

    r24d6572 r34b4268  
    2222#include "ResolvExpr/Cost.h"             // for Cost
    2323#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    24 #include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    25 #include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
     24#include "ResolvExpr/Unify.h"
    2625#include "SymTab/Indexer.h"              // for Indexer
    2726#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    2827#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
     28#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
    2929
    3030
     
    532532                }
    533533        }
    534         if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
     534        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
    535535                return Cost::zero;
    536536        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     
    566566                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
    567567                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    568                                         srcAsRef->base, dstAsRef->base, env ) ) {
     568                                        srcAsRef->base, dstAsRef->base, symtab, env ) ) {
    569569                                if ( tq1 == tq2 ) {
    570570                                        return Cost::zero;
     
    587587                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
    588588                assert( dstAsRef );
    589                 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, env ) ) {
     589                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
    590590                        if ( srcIsLvalue ) {
    591591                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
     
    653653                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
    654654                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    655                                 pointerType->base, dstAsPtr->base, env ) ) {
     655                                pointerType->base, dstAsPtr->base, symtab, env ) ) {
    656656                        if ( tq1 == tq2 ) {
    657657                                cost = Cost::zero;
  • src/ResolvExpr/ConversionCost.h

    r24d6572 r34b4268  
    3232namespace ResolvExpr {
    3333        class TypeEnvironment;
    34 
    35         Cost conversionCost(
    36                 const Type * src, const Type * dest, bool srcIsLvalue,
    37                 const SymTab::Indexer & indexer, const TypeEnvironment & env );
    3834
    3935        typedef std::function<Cost(const Type *, const Type *, bool,
     
    8480        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    8581
    86 Cost conversionCost(
    87         const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    88         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    89 
    90 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    91         bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
    92         PtrsCalculation func );
    93 
    9482#warning when the old ConversionCost is removed, get ride of the _new suffix.
    9583class ConversionCost_new : public ast::WithShortCircuiting {
     
    131119};
    132120
     121Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
     122        bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
     123        PtrsCalculation func );
     124
    133125} // namespace ResolvExpr
    134126
  • src/ResolvExpr/CurrentObject.cc

    r24d6572 r34b4268  
    99// Author           : Rob Schluntz
    1010// Created On       : Tue Jun 13 15:28:32 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Apr 10  9:40:00 2023
    13 // Update Count     : 18
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul  1 09:16:01 2022
     13// Update Count     : 15
    1414//
    1515
     
    2626#include "AST/Init.hpp"                // for Designation
    2727#include "AST/Node.hpp"                // for readonly
    28 #include "AST/Print.hpp"               // for readonly
     28#include "AST/Print.hpp"                // for readonly
    2929#include "AST/Type.hpp"
    30 #include "Common/Eval.h"               // for eval
    3130#include "Common/Indenter.h"           // for Indenter, operator<<
    3231#include "Common/SemanticError.h"      // for SemanticError
     
    593592
    594593namespace ast {
    595         /// Iterates members of a type by initializer.
    596         class MemberIterator {
    597         public:
    598                 virtual ~MemberIterator() {}
    599 
    600                 /// Internal set position based on iterator ranges.
    601                 virtual void setPosition(
    602                         std::deque< ptr< Expr > >::const_iterator it,
    603                         std::deque< ptr< Expr > >::const_iterator end ) = 0;
    604 
    605                 /// Walks the current object using the given designators as a guide.
    606                 void setPosition( const std::deque< ptr< Expr > > & designators ) {
    607                         setPosition( designators.begin(), designators.end() );
    608                 }
    609 
    610                 /// Retrieve the list of possible (Type,Designation) pairs for the
    611                 /// current position in the current object.
    612                 virtual std::deque< InitAlternative > operator* () const = 0;
    613 
    614                 /// True if the iterator is not currently at the end.
    615                 virtual operator bool() const = 0;
    616 
    617                 /// Moves the iterator by one member in the current object.
    618                 virtual MemberIterator & bigStep() = 0;
    619 
    620                 /// Moves the iterator by one member in the current subobject.
    621                 virtual MemberIterator & smallStep() = 0;
    622 
    623                 /// The type of the current object.
    624                 virtual const Type * getType() = 0;
    625 
    626                 /// The type of the current subobject.
    627                 virtual const Type * getNext() = 0;
    628 
    629                 /// Helper for operator*; aggregates must add designator to each init
    630                 /// alternative, but adding designators in operator* creates duplicates.
    631                 virtual std::deque< InitAlternative > first() const = 0;
    632         };
    633 
    634594        /// create a new MemberIterator that traverses a type correctly
    635595        MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
     
    671631        };
    672632
    673         /// Iterates over an indexed type:
    674         class IndexIterator : public MemberIterator {
    675         protected:
     633        /// Iterates array types
     634        class ArrayIterator final : public MemberIterator {
    676635                CodeLocation location;
     636                const ArrayType * array = nullptr;
     637                const Type * base = nullptr;
    677638                size_t index = 0;
    678639                size_t size = 0;
    679                 std::unique_ptr<MemberIterator> memberIter;
    680         public:
    681                 IndexIterator( const CodeLocation & loc, size_t size ) :
    682                         location( loc ), size( size )
    683                 {}
     640                std::unique_ptr< MemberIterator > memberIter;
     641
     642                void setSize( const Expr * expr ) {
     643                        auto res = eval( expr );
     644                        if ( ! res.second ) {
     645                                SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
     646                        }
     647                        size = res.first;
     648                }
     649
     650        public:
     651                ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : location( loc ), array( at ), base( at->base ) {
     652                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
     653                        memberIter.reset( createMemberIterator( loc, base ) );
     654                        if ( at->isVarLen ) {
     655                                SemanticError( location, at, "VLA initialization does not support @=: " );
     656                        }
     657                        setSize( at->dimension );
     658                }
    684659
    685660                void setPosition( const Expr * expr ) {
     
    690665                        auto arg = eval( expr );
    691666                        index = arg.first;
     667                        return;
    692668
    693669                        // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     
    707683
    708684                void setPosition(
    709                         std::deque<ast::ptr<ast::Expr>>::const_iterator begin,
    710                         std::deque<ast::ptr<ast::Expr>>::const_iterator end
     685                        std::deque< ptr< Expr > >::const_iterator begin,
     686                        std::deque< ptr< Expr > >::const_iterator end
    711687                ) override {
    712688                        if ( begin == end ) return;
     
    719695
    720696                operator bool() const override { return index < size; }
    721         };
    722 
    723         /// Iterates over the members of array types:
    724         class ArrayIterator final : public IndexIterator {
    725                 const ArrayType * array = nullptr;
    726                 const Type * base = nullptr;
    727 
    728                 size_t getSize( const Expr * expr ) {
    729                         auto res = eval( expr );
    730                         if ( !res.second ) {
    731                                 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
    732                         }
    733                         return res.first;
    734                 }
    735 
    736         public:
    737                 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) :
    738                                 IndexIterator( loc, getSize( at->dimension) ),
    739                                 array( at ), base( at->base ) {
    740                         PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    741                         memberIter.reset( createMemberIterator( loc, base ) );
    742                         if ( at->isVarLen ) {
    743                                 SemanticError( location, at, "VLA initialization does not support @=: " );
    744                         }
    745                 }
    746697
    747698                ArrayIterator & bigStep() override {
     
    882833
    883834                const Type * getNext() final {
    884                         bool hasMember = memberIter && *memberIter;
    885                         return hasMember ? memberIter->getType() : nullptr;
     835                        return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr;
    886836                }
    887837
     
    947897        };
    948898
    949         /// Iterates across the positions in a tuple:
    950         class TupleIterator final : public IndexIterator {
    951                 ast::TupleType const * const tuple;
    952 
    953                 const ast::Type * typeAtIndex() const {
    954                         assert( index < size );
    955                         return tuple->types[ index ].get();
    956                 }
    957 
    958         public:
    959                 TupleIterator( const CodeLocation & loc, const TupleType * type )
    960                 : IndexIterator( loc, type->size() ), tuple( type ) {
    961                         PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; )
    962                         memberIter.reset( createMemberIterator( loc, typeAtIndex() ) );
     899        class TupleIterator final : public AggregateIterator {
     900        public:
     901                TupleIterator( const CodeLocation & loc, const TupleType * inst )
     902                : AggregateIterator(
     903                        loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
     904                ) {}
     905
     906                operator bool() const override {
     907                        return curMember != members.end() || (memberIter && *memberIter);
    963908                }
    964909
    965910                TupleIterator & bigStep() override {
    966                         ++index;
    967                         memberIter.reset( index < size ?
    968                                 createMemberIterator( location, typeAtIndex() ) : nullptr );
     911                        PRINT( std::cerr << "bigStep in " << kind << std::endl; )
     912                        atbegin = false;
     913                        memberIter = nullptr;
     914                        curType = nullptr;
     915                        while ( curMember != members.end() ) {
     916                                ++curMember;
     917                                if ( init() ) return *this;
     918                        }
    969919                        return *this;
    970                 }
    971 
    972                 TupleIterator & smallStep() override {
    973                         if ( memberIter ) {
    974                                 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
    975                                 memberIter->smallStep();
    976                                 if ( !memberIter ) {
    977                                         PRINT( std::cerr << "has valid member iter" << std::endl; )
    978                                         return *this;
    979                                 }
    980                         }
    981                         return bigStep();
    982                 }
    983 
    984                 const ast::Type * getType() override {
    985                         return tuple;
    986                 }
    987 
    988                 const ast::Type * getNext() override {
    989                         bool hasMember = memberIter && *memberIter;
    990                         return hasMember ? memberIter->getType() : nullptr;
    991                 }
    992 
    993                 std::deque< InitAlternative > first() const override {
    994                         PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; )
    995                         if ( memberIter && *memberIter ) {
    996                                 std::deque< InitAlternative > ret = memberIter->first();
    997                                 for ( InitAlternative & alt : ret ) {
    998                                         alt.designation.get_and_mutate()->designators.emplace_front(
    999                                                 ConstantExpr::from_ulong( location, index ) );
    1000                                 }
    1001                                 return ret;
    1002                         }
    1003                         return {};
    1004920                }
    1005921        };
  • src/ResolvExpr/CurrentObject.h

    r24d6572 r34b4268  
    99// Author           : Rob Schluntz
    1010// Created On       : Thu Jun  8 11:07:25 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Apr  6 16:14:00 2023
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:36:48 2017
     13// Update Count     : 3
    1414//
    1515
     
    6565
    6666        /// Iterates members of a type by initializer
    67         class MemberIterator;
     67        class MemberIterator {
     68        public:
     69                virtual ~MemberIterator() {}
     70
     71                /// Internal set position based on iterator ranges
     72                virtual void setPosition(
     73                        std::deque< ptr< Expr > >::const_iterator it,
     74                        std::deque< ptr< Expr > >::const_iterator end ) = 0;
     75
     76                /// walks the current object using the given designators as a guide
     77                void setPosition( const std::deque< ptr< Expr > > & designators ) {
     78                        setPosition( designators.begin(), designators.end() );
     79                }
     80
     81                /// retrieve the list of possible (Type,Designation) pairs for the current position in the
     82                /// current object
     83                virtual std::deque< InitAlternative > operator* () const = 0;
     84
     85                /// true if the iterator is not currently at the end
     86                virtual operator bool() const = 0;
     87
     88                /// moves the iterator by one member in the current object
     89                virtual MemberIterator & bigStep() = 0;
     90
     91                /// moves the iterator by one member in the current subobject
     92                virtual MemberIterator & smallStep() = 0;
     93
     94                /// the type of the current object
     95                virtual const Type * getType() = 0;
     96
     97                /// the type of the current subobject
     98                virtual const Type * getNext() = 0;
     99       
     100                /// helper for operator*; aggregates must add designator to each init alternative, but
     101                /// adding designators in operator* creates duplicates
     102                virtual std::deque< InitAlternative > first() const = 0;
     103        };
    68104
    69105        /// Builds initializer lists in resolution
  • src/ResolvExpr/ExplodedArg.hpp

    r24d6572 r34b4268  
    3535        ExplodedArg() : env(), cost( Cost::zero ), exprs() {}
    3636        ExplodedArg( const Candidate & arg, const ast::SymbolTable & symtab );
    37 
     37       
    3838        ExplodedArg( ExplodedArg && ) = default;
    3939        ExplodedArg & operator= ( ExplodedArg && ) = default;
  • src/ResolvExpr/PolyCost.cc

    r24d6572 r34b4268  
    1515
    1616#include "AST/SymbolTable.hpp"
    17 #include "AST/Pass.hpp"
    1817#include "AST/Type.hpp"
    1918#include "AST/TypeEnvironment.hpp"
  • src/ResolvExpr/PtrsAssignable.cc

    r24d6572 r34b4268  
    1414//
    1515
    16 #include "PtrsAssignable.hpp"
     16#include "typeops.h"
    1717
    1818#include "AST/Pass.hpp"
  • src/ResolvExpr/PtrsCastable.cc

    r24d6572 r34b4268  
    1414//
    1515
    16 #include "PtrsCastable.hpp"
    17 
    1816#include "AST/Decl.hpp"
    1917#include "AST/Pass.hpp"
     
    2119#include "AST/TypeEnvironment.hpp"
    2220#include "Common/PassVisitor.h"
    23 #include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
    2421#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2522#include "SymTab/Indexer.h"              // for Indexer
     
    2724#include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
    2825#include "SynTree/Visitor.h"             // for Visitor
     26#include "typeops.h"                     // for ptrsAssignable
    2927
    3028namespace ResolvExpr {
     
    293291                return objectCast( src, env, symtab );
    294292        } else {
    295                 return ast::Pass<PtrsCastable_new>::read( src, dst, env, symtab );
     293                ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
     294                src->accept( ptrs );
     295                return ptrs.core.result;
    296296        }
    297297}
  • src/ResolvExpr/RenameVars.cc

    r24d6572 r34b4268  
    8383
    8484                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
     85                        // rename
    8586                        auto it = idMap.find( type->name );
    86                         if ( it == idMap.end() ) return type;
    87 
    88                         // Unconditionally mutate because map will *always* have different name.
    89                         ast::TypeInstType * mut = ast::shallowCopy( type );
    90                         // Reconcile base node since some copies might have been made.
    91                         mut->base = it->second.base;
    92                         mut->formal_usage = it->second.formal_usage;
    93                         mut->expr_id = it->second.expr_id;
    94                         return mut;
     87                        if ( it != idMap.end() ) {
     88                                // unconditionally mutate because map will *always* have different name
     89                                ast::TypeInstType * mut = ast::shallowCopy( type );
     90                                // reconcile base node since some copies might have been made
     91                                mut->base = it->second.base;
     92                                mut->formal_usage = it->second.formal_usage;
     93                                mut->expr_id = it->second.expr_id;
     94                    type = mut;
     95                        }
     96
     97                        return type;
    9598                }
    9699
     
    184187
    185188const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) {
     189        // ast::Type *tc = ast::deepCopy(t);
    186190        ast::Pass<RenameVars_new> renamer;
    187191        renamer.core.mode = mode;
  • src/ResolvExpr/ResolveAssertions.cc

    r24d6572 r34b4268  
    2626#include <vector>                   // for vector
    2727
    28 #include "AdjustExprType.hpp"       // for adjustExprType
    2928#include "Alternative.h"            // for Alternative, AssertionItem, AssertionList
    3029#include "Common/FilterCombos.h"    // for filterCombos
    3130#include "Common/Indenter.h"        // for Indenter
     31#include "Common/utility.h"         // for sort_mins
    3232#include "GenPoly/GenPoly.h"        // for getFunctionType
    33 #include "ResolvExpr/AlternativeFinder.h"  // for computeConversionCost
    3433#include "ResolvExpr/RenameVars.h"  // for renameTyVars
    35 #include "SpecCost.hpp"             // for specCost
    3634#include "SymTab/Indexer.h"         // for Indexer
    3735#include "SymTab/Mangler.h"         // for Mangler
    3836#include "SynTree/Expression.h"     // for InferredParams
    3937#include "TypeEnvironment.h"        // for TypeEnvironment, etc.
     38#include "typeops.h"                // for adjustExprType, specCost
    4039#include "Unify.h"                  // for unify
    4140
  • src/ResolvExpr/Resolver.cc

    r24d6572 r34b4268  
    3838#include "AST/SymbolTable.hpp"
    3939#include "AST/Type.hpp"
    40 #include "Common/Eval.h"                 // for eval
    41 #include "Common/Iterate.hpp"            // for group_iterate
    4240#include "Common/PassVisitor.h"          // for PassVisitor
    4341#include "Common/SemanticError.h"        // for SemanticError
    4442#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    45 #include "Common/ToString.hpp"           // for toCString
     43#include "Common/utility.h"              // for ValueGuard, group_iterate
    4644#include "InitTweak/GenInit.h"
    4745#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
     
    11091107                void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
    11101108                        if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
    1111                                 if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) {
     1109                                if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
    11121110                                        // cast is to the same type as its argument, remove it
    11131111                                        swap_and_save_env( expr, castExpr->arg );
     
    17311729
    17321730                        // Find all candidates for a function in canonical form
    1733                         funcFinder.find( clause.target, ResolvMode::withAdjustment() );
     1731                        funcFinder.find( clause.target_func, ResolvMode::withAdjustment() );
    17341732
    17351733                        if ( funcFinder.candidates.empty() ) {
    17361734                                stringstream ss;
    17371735                                ss << "Use of undeclared indentifier '";
    1738                                 ss << clause.target.strict_as< ast::NameExpr >()->name;
     1736                                ss << clause.target_func.strict_as< ast::NameExpr >()->name;
    17391737                                ss << "' in call to waitfor";
    17401738                                SemanticError( stmt->location, ss.str() );
     
    18351833                                                                if (
    18361834                                                                        ! unify(
    1837                                                                                 arg->expr->result, *param, resultEnv, need, have, open )
     1835                                                                                arg->expr->result, *param, resultEnv, need, have, open,
     1836                                                                                symtab )
    18381837                                                                ) {
    18391838                                                                        // Type doesn't match
     
    19221921                        auto clause2 = new ast::WaitForClause( clause.location );
    19231922
    1924                         clause2->target = funcCandidates.front()->expr;
     1923                        clause2->target_func = funcCandidates.front()->expr;
    19251924
    19261925                        clause2->target_args.reserve( clause.target_args.size() );
     
    19451944
    19461945                        // Resolve the conditions as if it were an IfStmt, statements normally
    1947                         clause2->when_cond = findSingleExpression( clause.when_cond, context );
     1946                        clause2->cond = findSingleExpression( clause.cond, context );
    19481947                        clause2->stmt = clause.stmt->accept( *visitor );
    19491948
  • src/ResolvExpr/Resolver.h

    r24d6572 r34b4268  
    3434        class Decl;
    3535        class DeletedExpr;
    36         class Expr;
    3736        class Init;
    3837        class StmtExpr;
  • src/ResolvExpr/SatisfyAssertions.cpp

    r24d6572 r34b4268  
    2424#include <vector>
    2525
    26 #include "AdjustExprType.hpp"
    2726#include "Candidate.hpp"
    2827#include "CandidateFinder.hpp"
    29 #include "CommonType.hpp"
    3028#include "Cost.h"
    3129#include "RenameVars.h"
    32 #include "SpecCost.hpp"
    3330#include "typeops.h"
    3431#include "Unify.h"
     
    184181                                .strict_as<ast::FunctionType>()->params[0]
    185182                                .strict_as<ast::ReferenceType>()->base;
    186                         // sat.cand->env.apply(thisArgType);
    187 
    188                         if (auto inst = thisArgType.as<ast::TypeInstType>()) {
    189                                 auto cls = sat.cand->env.lookup(*inst);
    190                                 if (cls && cls->bound) thisArgType = cls->bound;
    191                         }
     183                        sat.cand->env.apply(thisArgType);
    192184
    193185                        std::string otypeKey = "";
     
    226218                        ast::TypeEnvironment tempNewEnv {newEnv};
    227219
    228                         if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
     220                        if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
    229221                                // set up binding slot for recursive assertions
    230222                                ast::UniqueId crntResnSlot = 0;
     
    242234                                // newEnv = sat.cand->env;
    243235                                // newNeed.clear();
    244                                 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
     236                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
    245237                                        // set up binding slot for recursive assertions
    246238                                        ast::UniqueId crntResnSlot = 0;
     
    406398                        mergeOpenVars( open, i.match.open );
    407399
    408                         if ( ! env.combine( i.match.env, open ) ) return false;
     400                        if ( ! env.combine( i.match.env, open, symtab ) ) return false;
    409401
    410402                        crnt.emplace_back( i );
  • src/ResolvExpr/Unify.cc

    r24d6572 r34b4268  
    3333#include "AST/TypeEnvironment.hpp"
    3434#include "Common/PassVisitor.h"     // for PassVisitor
    35 #include "CommonType.hpp"           // for commonType
    3635#include "FindOpenVars.h"           // for findOpenVars
    37 #include "SpecCost.hpp"             // for SpecCost
    3836#include "SynTree/LinkageSpec.h"    // for C
    3937#include "SynTree/Constant.h"       // for Constant
     
    4543#include "Tuples/Tuples.h"          // for isTtype
    4644#include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
    47 #include "typeops.h"                // for flatten, occurs
     45#include "typeops.h"                // for flatten, occurs, commonType
    4846
    4947namespace ast {
     
    5250
    5351namespace SymTab {
    54         class Indexer;
     52class Indexer;
    5553}  // namespace SymTab
    5654
     
    5856
    5957namespace ResolvExpr {
    60 
    61 // Template Helpers:
    62 template< typename Iterator1, typename Iterator2 >
    63 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
    64         for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    65                 Type *commonType = 0;
    66                 if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    67                         return false;
    68                 } // if
    69                 commonTypes.push_back( commonType );
    70         } // for
    71         return ( list1Begin == list1End && list2Begin == list2End );
    72 }
    73 
    74 template< typename Iterator1, typename Iterator2 >
    75 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    76         std::list< Type* > commonTypes;
    77         if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions,  openVars, indexer, commonTypes ) ) {
    78                 deleteAll( commonTypes );
    79                 return true;
    80         } else {
    81                 return false;
    82         } // if
    83 }
    8458
    8559        struct Unify_old : public WithShortCircuiting {
     
    128102                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    129103                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    130                 WidenMode widen );
     104                WidenMode widen, const ast::SymbolTable & symtab );
    131105
    132106        bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     
    150124
    151125        bool typesCompatible(
    152                         const ast::Type * first, const ast::Type * second,
     126                        const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
    153127                        const ast::TypeEnvironment & env ) {
    154128                ast::TypeEnvironment newEnv;
     
    163137                findOpenVars( newSecond, open, closed, need, have, newEnv, FirstOpen );
    164138
    165                 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
     139                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    166140        }
    167141
     
    183157
    184158        bool typesCompatibleIgnoreQualifiers(
    185                         const ast::Type * first, const ast::Type * second,
     159                        const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
    186160                        const ast::TypeEnvironment & env ) {
    187161                ast::TypeEnvironment newEnv;
     
    216190                        subFirst,
    217191                        subSecond,
    218                         newEnv, need, have, open, noWiden() );
     192                        newEnv, need, have, open, noWiden(), symtab );
    219193        }
    220194
     
    786760                const ast::OpenVarSet & open;
    787761                WidenMode widen;
     762                const ast::SymbolTable & symtab;
    788763        public:
    789764                static size_t traceId;
     
    792767                Unify_new(
    793768                        const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
    794                         ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen )
     769                        ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,
     770                        const ast::SymbolTable & symtab )
    795771                : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),
    796                 result(false) {}
     772                  symtab(symtab), result(false) {}
    797773
    798774                void previsit( const ast::Node * ) { visit_children = false; }
     
    812788                                result = unifyExact(
    813789                                        pointer->base, pointer2->base, tenv, need, have, open,
    814                                         noWiden());
     790                                        noWiden(), symtab );
    815791                        }
    816792                }
     
    835811
    836812                        result = unifyExact(
    837                                 array->base, array2->base, tenv, need, have, open, noWiden());
     813                                array->base, array2->base, tenv, need, have, open, noWiden(),
     814                                symtab );
    838815                }
    839816
     
    841818                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    842819                                result = unifyExact(
    843                                         ref->base, ref2->base, tenv, need, have, open, noWiden());
     820                                        ref->base, ref2->base, tenv, need, have, open, noWiden(),
     821                                        symtab );
    844822                        }
    845823                }
     
    850828                static bool unifyTypeList(
    851829                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    852                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open
     830                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     831                        const ast::SymbolTable & symtab
    853832                ) {
    854833                        while ( crnt1 != end1 && crnt2 != end2 ) {
     
    863842                                        return unifyExact(
    864843                                                t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    865                                                 noWiden() );
     844                                                noWiden(), symtab );
    866845                                } else if ( ! isTuple1 && isTuple2 ) {
    867846                                        // combine remainder of list1, then unify
    868847                                        return unifyExact(
    869848                                                tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    870                                                 noWiden() );
     849                                                noWiden(), symtab );
    871850                                }
    872851
    873852                                if ( ! unifyExact(
    874                                         t1, t2, env, need, have, open, noWiden() )
     853                                        t1, t2, env, need, have, open, noWiden(), symtab )
    875854                                ) return false;
    876855
     
    886865                                return unifyExact(
    887866                                        t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    888                                         noWiden() );
     867                                        noWiden(), symtab );
    889868                        } else if ( crnt2 != end2 ) {
    890869                                // try unifying empty tuple with ttype
     
    893872                                return unifyExact(
    894873                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    895                                         noWiden() );
     874                                        noWiden(), symtab );
    896875                        }
    897876
     
    903882                        const std::vector< ast::ptr< ast::Type > > & list2,
    904883                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    905                         const ast::OpenVarSet & open
     884                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    906885                ) {
    907886                        return unifyTypeList(
    908                                 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open);
     887                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
     888                                symtab );
    909889                }
    910890
     
    947927                        ) return;
    948928
    949                         if ( ! unifyTypeList( params, params2, tenv, need, have, open ) ) return;
     929                        if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
    950930                        if ( ! unifyTypeList(
    951                                 func->returns, func2->returns, tenv, need, have, open ) ) return;
     931                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    952932
    953933                        markAssertions( have, need, func );
     
    964944                        // check that the other type is compatible and named the same
    965945                        auto otherInst = dynamic_cast< const XInstType * >( other );
    966                         if (otherInst && inst->name == otherInst->name)
    967                                 this->result = otherInst;
     946                        if (otherInst && inst->name == otherInst->name) this->result = otherInst;
    968947                        return otherInst;
    969948                }
     
    10211000
    10221001                                if ( ! unifyExact(
    1023                                                 pty, pty2, tenv, need, have, open, noWiden() ) ) {
     1002                                                pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
    10241003                                        result = false;
    10251004                                        return;
     
    10511030                void postvisit( const ast::TypeInstType * typeInst ) {
    10521031                        // assert( open.find( *typeInst ) == open.end() );
    1053                         auto otherInst = dynamic_cast< const ast::TypeInstType * >( type2 );
    1054                         if (otherInst && typeInst->name == otherInst->name)
    1055                                 this->result = otherInst;
    1056                         // return otherInst;
     1032                        handleRefType( typeInst, type2 );
    10571033                }
    10581034
     
    10631039                        const std::vector< ast::ptr< ast::Type > > & list1,
    10641040                        const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,
    1065                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open
     1041                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     1042                        const ast::SymbolTable & symtab
    10661043                ) {
    10671044                        auto crnt1 = list1.begin();
     
    10781055                                        return unifyExact(
    10791056                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1080                                                 noWiden() );
     1057                                                noWiden(), symtab );
    10811058                                } else if ( ! isTuple1 && isTuple2 ) {
    10821059                                        // combine entirety of list1, then unify
    10831060                                        return unifyExact(
    10841061                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1085                                                 noWiden() );
     1062                                                noWiden(), symtab );
    10861063                                }
    10871064
    10881065                                if ( ! unifyExact(
    1089                                         t1, t2, env, need, have, open, noWiden() )
     1066                                        t1, t2, env, need, have, open, noWiden(), symtab )
    10901067                                ) return false;
    10911068
     
    11011078                                return unifyExact(
    11021079                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1103                                                 noWiden() );
     1080                                                noWiden(), symtab );
    11041081                        } else if ( crnt2 != list2.end() ) {
    11051082                                // try unifying empty tuple with ttype
     
    11101087                                return unifyExact(
    11111088                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1112                                                 noWiden() );
     1089                                                noWiden(), symtab );
    11131090                        }
    11141091
     
    11291106                        auto types2 = flatten( flat2 );
    11301107
    1131                         result = unifyList( types, types2, tenv, need, have, open );
     1108                        result = unifyList( types, types2, tenv, need, have, open, symtab );
    11321109                }
    11331110
     
    11531130                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11541131                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1155                         ast::OpenVarSet & open
     1132                        ast::OpenVarSet & open, const ast::SymbolTable & symtab
    11561133        ) {
    11571134                ast::ptr<ast::Type> common;
    1158                 return unify( type1, type2, env, need, have, open, common );
     1135                return unify( type1, type2, env, need, have, open, symtab, common );
    11591136        }
    11601137
     
    11621139                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11631140                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1164                         ast::OpenVarSet & open, ast::ptr<ast::Type> & common
     1141                        ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
    11651142        ) {
    11661143                ast::OpenVarSet closed;
     
    11681145                findOpenVars( type2, open, closed, need, have, env, FirstOpen );
    11691146                return unifyInexact(
    1170                         type1, type2, env, need, have, open, WidenMode{ true, true }, common );
     1147                        type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common );
    11711148        }
    11721149
     
    11741151                        const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    11751152                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1176                         WidenMode widen
     1153                        WidenMode widen, const ast::SymbolTable & symtab
    11771154        ) {
    11781155                if ( type1->qualifiers != type2->qualifiers ) return false;
     
    11931170                        return env.bindVarToVar(
    11941171                                var1, var2, ast::TypeData{ entry1->second, entry2->second }, need, have,
    1195                                 open, widen );
     1172                                open, widen, symtab );
    11961173                } else if ( isopen1 ) {
    1197                         return env.bindVar( var1, type2, entry1->second, need, have, open, widen );
     1174                        return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab );
    11981175                } else if ( isopen2 ) {
    11991176                        return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );
     
    12031180                        return env.bindVarToVar(
    12041181                                var1, var2, ast::TypeData{ var1->base->kind, var1->base->sized||var2->base->sized }, need, have,
    1205                                 open, widen );
     1182                                open, widen, symtab );
    12061183                } else if ( isopen1 ) {
    1207                         return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen );
     1184                        return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen, symtab );
    12081185                } else if ( isopen2 ) {
    1209                         return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen );
     1186                        return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen, symtab );
    12101187                }else {
    12111188                        return ast::Pass<Unify_new>::read(
    1212                                 type1, type2, env, need, have, open, widen );
     1189                                type1, type2, env, need, have, open, widen, symtab );
    12131190                }
    12141191               
     
    12181195                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    12191196                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1220                         const ast::OpenVarSet & open, WidenMode widen,
     1197                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
    12211198                        ast::ptr<ast::Type> & common
    12221199        ) {
     
    12321209                ast::ptr< ast::Type > t2_(t2);
    12331210
    1234                 if ( unifyExact( t1, t2, env, need, have, open, widen ) ) {
     1211                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    12351212                        // if exact unification on unqualified types, try to merge qualifiers
    12361213                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
     
    12421219                        }
    12431220
    1244                 } else if (( common = commonType( t1, t2, env, need, have, open, widen ))) {
     1221                } else if (( common = commonType( t1, t2, env, need, have, open, widen, symtab ))) {
    12451222                        // no exact unification, but common type
    12461223                        auto c = shallowCopy(common.get());
  • src/ResolvExpr/Unify.h

    r24d6572 r34b4268  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jan 17 11:12:00 2023
    13 // Update Count     : 5
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    3737
    3838namespace ResolvExpr {
     39        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
     40        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
     41        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
     42        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    3943
    40 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    41 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    42 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    43 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
     44        template< typename Iterator1, typename Iterator2 >
     45        bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
     46                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     47                        Type *commonType = 0;
     48                        if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     49                                return false;
     50                        } // if
     51                        commonTypes.push_back( commonType );
     52                } // for
     53                if ( list1Begin != list1End || list2Begin != list2End ) {
     54                        return false;
     55                } else {
     56                        return true;
     57                } // if
     58        }
    4459
    45 bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    46 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
     60        template< typename Iterator1, typename Iterator2 >
     61        bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     62                std::list< Type* > commonTypes;
     63                if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
     64                        deleteAll( commonTypes );
     65                        return true;
     66                } else {
     67                        return false;
     68                } // if
     69        }
    4770
    48 inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    49         TypeEnvironment env;
    50         return typesCompatible( t1, t2, indexer, env );
    51 }
     71        bool unify(
     72                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     73                ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     74                ast::OpenVarSet & open, const ast::SymbolTable & symtab );
    5275
    53 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    54         TypeEnvironment env;
    55         return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
    56 }
     76        bool unify(
     77                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     78                ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     79                ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
    5780
    58 bool unify(
    59         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    60         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    61         ast::OpenVarSet & open );
     81        bool unifyExact(
     82                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     83                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     84                WidenMode widen, const ast::SymbolTable & symtab );
    6285
    63 bool unify(
    64         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    65         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    66         ast::OpenVarSet & open, ast::ptr<ast::Type> & common );
    67 
    68 bool unifyExact(
    69         const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    70         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    71         WidenMode widen );
    72 
    73 bool unifyInexact(
    74         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    75         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    76         const ast::OpenVarSet & open, WidenMode widen,
    77         ast::ptr<ast::Type> & common );
    78 
    79 bool typesCompatible(
    80         const ast::Type *, const ast::Type *,
    81         const ast::TypeEnvironment & env = {} );
    82 
    83 bool typesCompatibleIgnoreQualifiers(
    84         const ast::Type *, const ast::Type *,
    85         const ast::TypeEnvironment & env = {} );
    86 
    87 /// Creates the type represented by the list of returnVals in a FunctionType.
    88 /// The caller owns the return value.
    89 Type * extractResultType( FunctionType * functionType );
    90 /// Creates or extracts the type represented by returns in a `FunctionType`.
    91 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
    92 
    93 std::vector<ast::ptr<ast::Type>> flattenList(
    94         const std::vector<ast::ptr<ast::Type>> & src, ast::TypeEnvironment & env
    95 );
     86        bool unifyInexact(
     87                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     88                ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     89                const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
     90                ast::ptr<ast::Type> & common );
    9691
    9792} // namespace ResolvExpr
  • src/ResolvExpr/WidenMode.h

    r24d6572 r34b4268  
    1919        struct WidenMode {
    2020                WidenMode( bool first, bool second ): first( first ), second( second ) {}
    21 
     21               
    2222                WidenMode &operator|=( const WidenMode &other ) {
    2323                        first |= other.first; second |= other.second; return *this;
     
    3535                        WidenMode newWM( *this ); newWM &= other; return newWM;
    3636                }
    37 
     37               
    3838                operator bool() { return first && second; }
    3939
  • src/ResolvExpr/module.mk

    r24d6572 r34b4268  
    1717SRC_RESOLVEXPR = \
    1818      ResolvExpr/AdjustExprType.cc \
    19       ResolvExpr/AdjustExprType.hpp \
    2019      ResolvExpr/Alternative.cc \
    2120      ResolvExpr/AlternativeFinder.cc \
     
    2726      ResolvExpr/Candidate.hpp \
    2827      ResolvExpr/CastCost.cc \
    29       ResolvExpr/CastCost.hpp \
    3028      ResolvExpr/CommonType.cc \
    31       ResolvExpr/CommonType.hpp \
    3229      ResolvExpr/ConversionCost.cc \
    3330      ResolvExpr/ConversionCost.h \
     
    4340      ResolvExpr/Occurs.cc \
    4441      ResolvExpr/PolyCost.cc \
    45       ResolvExpr/PolyCost.hpp \
    4642      ResolvExpr/PtrsAssignable.cc \
    47       ResolvExpr/PtrsAssignable.hpp \
    4843      ResolvExpr/PtrsCastable.cc \
    49       ResolvExpr/PtrsCastable.hpp \
    5044      ResolvExpr/RenameVars.cc \
    5145      ResolvExpr/RenameVars.h \
     
    6054      ResolvExpr/SatisfyAssertions.hpp \
    6155      ResolvExpr/SpecCost.cc \
    62       ResolvExpr/SpecCost.hpp \
    6356      ResolvExpr/TypeEnvironment.cc \
    6457      ResolvExpr/TypeEnvironment.h \
  • src/ResolvExpr/typeops.h

    r24d6572 r34b4268  
    1010// Created On       : Sun May 17 07:28:22 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jan 18 11:54:00 2023
    13 // Update Count     : 7
     12// Last Modified On : Tue Oct  1 09:45:00 2019
     13// Update Count     : 6
    1414//
    1515
     
    1818#include <vector>
    1919
     20#include "Cost.h"
     21#include "TypeEnvironment.h"
     22#include "WidenMode.h"
     23#include "AST/Fwd.hpp"
     24#include "AST/Node.hpp"
     25#include "AST/SymbolTable.hpp"
    2026#include "AST/Type.hpp"
     27#include "AST/TypeEnvironment.hpp"
     28#include "SynTree/SynTree.h"
    2129#include "SynTree/Type.h"
    2230
     
    2634
    2735namespace ResolvExpr {
    28         class TypeEnvironment;
    29 
    3036        // combos: takes a list of sets and returns a set of lists representing every possible way of forming a list by
    3137        // picking one element out of each set
     
    5561        }
    5662
     63        // in AdjustExprType.cc
     64        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
     65        void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
     66
     67        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
     68        void adjustExprType( Type *& type );
     69
     70        template< typename ForwardIterator >
     71        void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
     72                while ( begin != end ) {
     73                        adjustExprType( *begin++, env, indexer );
     74                } // while
     75        }
     76
     77        /// Replaces array types with equivalent pointer, and function types with a pointer-to-function
     78        const ast::Type * adjustExprType(
     79                const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );
     80
     81        // in CastCost.cc
     82        Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
     83                const SymTab::Indexer & indexer, const TypeEnvironment & env );
     84        Cost castCost(
     85                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     86                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
     87
     88        // in ConversionCost.cc
     89        Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
     90                const SymTab::Indexer & indexer, const TypeEnvironment & env );
     91        Cost conversionCost(
     92                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     93                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
     94
     95        // in AlternativeFinder.cc
     96        Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
     97                const SymTab::Indexer & indexer, const TypeEnvironment & env );
     98
     99        // in PtrsAssignable.cc
     100        int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env );
     101        int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
     102                const ast::TypeEnvironment & env );
     103
     104        // in PtrsCastable.cc
     105        int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer & indexer );
     106        int ptrsCastable(
     107                const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     108                const ast::TypeEnvironment & env );
     109
     110        // in Unify.cc
     111        bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
     112        bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
     113
     114        inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
     115                TypeEnvironment env;
     116                return typesCompatible( t1, t2, indexer, env );
     117        }
     118
     119        inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
     120                TypeEnvironment env;
     121                return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
     122        }
     123
     124        bool typesCompatible(
     125                const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
     126                const ast::TypeEnvironment & env = {} );
     127
     128        bool typesCompatibleIgnoreQualifiers(
     129                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     130                const ast::TypeEnvironment & env = {} );
     131
     132        /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
     133        Type * extractResultType( FunctionType * functionType );
     134        /// Creates or extracts the type represented by the list of returns in a `FunctionType`.
     135        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
     136
     137        // in CommonType.cc
     138        Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars );
     139        ast::ptr< ast::Type > commonType(
     140                const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
     141                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     142                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
     143        );
     144        // in Unify.cc
     145        std::vector< ast::ptr< ast::Type > > flattenList(
     146                const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     147        );
     148
     149        // in PolyCost.cc
     150        int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
     151        int polyCost(
     152                const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
     153
     154        // in SpecCost.cc
     155        int specCost( Type * type );
     156        int specCost( const ast::Type * type );
     157
    57158        // in Occurs.cc
    58159        bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
     
    67168                return false;
    68169        }
     170
     171        // in AlternativeFinder.cc
     172        void referenceToRvalueConversion( Expression *& expr, Cost & cost );
     173        // in CandidateFinder.cpp
     174        const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );
    69175
    70176        /// flatten tuple type into list of types
     
    112218                }
    113219
     220
    114221                return new ast::TupleType{ std::move(types) };
    115222        }
     
    120227                return tupleFromTypes( tys.begin(), tys.end() );
    121228        }
     229
     230       
    122231
    123232        // in TypeEnvironment.cc
  • src/SymTab/Autogen.cc

    r24d6572 r34b4268  
    1010// Created On       : Thu Mar 03 15:45:56 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 14 15:03:00 2023
    13 // Update Count     : 64
     12// Last Modified On : Fri Apr 27 14:39:06 2018
     13// Update Count     : 63
    1414//
    1515
     
    211211        }
    212212
     213        bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
     214                return obj && obj->name.empty() && obj->bitfieldWidth;
     215        }
     216
    213217        /// inserts a forward declaration for functionDecl into declsToAdd
    214218        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
     
    230234        }
    231235
     236        // shallow copy the pointer list for return
     237        std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {
     238                if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {
     239                        return structInst->base->params;
     240                }
     241                if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {
     242                        return unionInst->base->params;
     243                }
     244                return {};
     245        }
     246
    232247        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    233248        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
     
    241256                ftype->parameters.push_back( dstParam );
    242257                return ftype;
     258        }
     259
     260        /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).
     261        ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {
     262                std::vector<ast::ptr<ast::TypeDecl>> typeParams;
     263                if (maybePolymorphic) typeParams = getGenericParams(paramType);
     264                auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);
     265                return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc), {}, ast::Linkage::Cforall);
    243266        }
    244267
  • src/SymTab/Autogen.h

    r24d6572 r34b4268  
    99// Author           : Rob Schluntz
    1010// Created On       : Sun May 17 21:53:34 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 14 15:06:00 2023
    13 // Update Count     : 17
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Dec 13 16:38:06 2019
     13// Update Count     : 16
    1414//
    1515
     
    2020#include <string>                 // for string
    2121
     22#include "AST/Decl.hpp"
     23#include "AST/Expr.hpp"
     24#include "AST/Init.hpp"
     25#include "AST/Node.hpp"
     26#include "AST/Stmt.hpp"
     27#include "AST/Type.hpp"
    2228#include "CodeGen/OperatorTable.h"
    2329#include "Common/UniqueName.h"    // for UniqueName
     
    3945        /// returns true if obj's name is the empty string and it has a bitfield width
    4046        bool isUnnamedBitfield( ObjectDecl * obj );
     47        bool isUnnamedBitfield( const ast::ObjectDecl * obj );
    4148
    4249        /// generate the type of an assignment function for paramType.
     
    4855        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
    4956
     57        ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);
     58
    5059        /// generate the type of a copy constructor for paramType.
    5160        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    5261        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    5362
     63        /// Enum for loop direction
     64        enum LoopDirection { LoopBackward, LoopForward };
     65
    5466        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    5567        template< typename OutputIterator >
    5668        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
     69
     70        template< typename OutIter >
     71        ast::ptr< ast::Stmt > genCall(
     72                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     73                const CodeLocation & loc, const std::string & fname, OutIter && out,
     74                const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
    5775
    5876        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     
    103121
    104122                *out++ = new ExprStmt( fExpr );
     123
     124                srcParam.clearArrayIndices();
     125
     126                return listInit;
     127        }
     128
     129        /// inserts into out a generated call expression to function fname with arguments dstParam and
     130        /// srcParam. Should only be called with non-array types.
     131        /// optionally returns a statement which must be inserted prior to the containing loop, if
     132        /// there is one
     133        template< typename OutIter >
     134        ast::ptr< ast::Stmt > genScalarCall(
     135                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     136                const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
     137                const ast::Type * addCast = nullptr
     138        ) {
     139                bool isReferenceCtorDtor = false;
     140                if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     141                        // reference constructors are essentially application of the rebind operator.
     142                        // apply & to both arguments, do not need a cast
     143                        fname = "?=?";
     144                        dstParam = new ast::AddressExpr{ dstParam };
     145                        addCast = nullptr;
     146                        isReferenceCtorDtor = true;
     147                }
     148
     149                // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
     150                // "?=?", "?{}", or "^?{}"
     151                ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };
     152
     153                if ( addCast ) {
     154                        // cast to T& with qualifiers removed, so that qualified objects can be constructed and
     155                        // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
     156                        // is considered a qualifier - for AddressExpr to resolve, its argument must have an
     157                        // lvalue-qualified type, so remove all qualifiers except lvalue.
     158                        // xxx -- old code actually removed lvalue too...
     159                        ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
     160                        ast::ptr< ast::Type > castType = addCast;
     161                        ast::remove_qualifiers(
     162                                castType,
     163                                ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
     164                        dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
     165                }
     166                fExpr->args.emplace_back( dstParam );
     167
     168                ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
     169
     170                // fetch next set of arguments
     171                ++srcParam;
     172
     173                // return if adding reference fails -- will happen on default ctor and dtor
     174                if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
     175
     176                std::vector< ast::ptr< ast::Expr > > args = *srcParam;
     177                splice( fExpr->args, args );
     178
     179                *out++ = new ast::ExprStmt{ loc, fExpr };
    105180
    106181                srcParam.clearArrayIndices();
     
    173248        }
    174249
     250        /// Store in out a loop which calls fname on each element of the array with srcParam and
     251        /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
     252        template< typename OutIter >
     253        void genArrayCall(
     254                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     255                const CodeLocation & loc, const std::string & fname, OutIter && out,
     256                const ast::ArrayType * array, const ast::Type * addCast = nullptr,
     257                LoopDirection forward = LoopForward
     258        ) {
     259                static UniqueName indexName( "_index" );
     260
     261                // for a flexible array member nothing is done -- user must define own assignment
     262                if ( ! array->dimension ) return;
     263
     264                if ( addCast ) {
     265                        // peel off array layer from cast
     266                        addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
     267                }
     268
     269                ast::ptr< ast::Expr > begin, end;
     270                std::string cmp, update;
     271
     272                if ( forward ) {
     273                        // generate: for ( int i = 0; i < N; ++i )
     274                        begin = ast::ConstantExpr::from_int( loc, 0 );
     275                        end = array->dimension;
     276                        cmp = "?<?";
     277                        update = "++?";
     278                } else {
     279                        // generate: for ( int i = N-1; i >= 0; --i )
     280                        begin = ast::UntypedExpr::createCall( loc, "?-?",
     281                                { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
     282                        end = ast::ConstantExpr::from_int( loc, 0 );
     283                        cmp = "?>=?";
     284                        update = "--?";
     285                }
     286
     287                ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
     288                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
     289                        new ast::SingleInit{ loc, begin } };
     290                ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
     291
     292                ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
     293                        loc, cmp, { indexVar, end } );
     294
     295                ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
     296                        loc, update, { indexVar } );
     297
     298                ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
     299                        loc, "?[?]", { dstParam, indexVar } );
     300
     301                // srcParam must keep track of the array indices to build the source parameter and/or
     302                // array list initializer
     303                srcParam.addArrayIndex( indexVar, array->dimension );
     304
     305                // for stmt's body, eventually containing call
     306                ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
     307                ast::ptr< ast::Stmt > listInit = genCall(
     308                        srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
     309                        forward );
     310
     311                // block containing the stmt and index variable
     312                ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
     313                block->push_back( new ast::DeclStmt{ loc, index } );
     314                if ( listInit ) { block->push_back( listInit ); }
     315                block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );
     316
     317                *out++ = block;
     318        }
     319
    175320        template< typename OutputIterator >
    176321        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     
    180325                } else {
    181326                        return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
     327                }
     328        }
     329
     330        template< typename OutIter >
     331        ast::ptr< ast::Stmt > genCall(
     332                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     333                const CodeLocation & loc, const std::string & fname, OutIter && out,
     334                const ast::Type * type, const ast::Type * addCast, LoopDirection forward
     335        ) {
     336                if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
     337                        genArrayCall(
     338                                srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
     339                                forward );
     340                        return {};
     341                } else {
     342                        return genScalarCall(
     343                                srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
    182344                }
    183345        }
     
    217379        }
    218380
     381        static inline ast::ptr< ast::Stmt > genImplicitCall(
     382                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     383                const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
     384                LoopDirection forward = LoopForward
     385        ) {
     386                // unnamed bit fields are not copied as they cannot be accessed
     387                if ( isUnnamedBitfield( obj ) ) return {};
     388
     389                ast::ptr< ast::Type > addCast;
     390                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
     391                        assert( dstParam->result );
     392                        addCast = dstParam->result;
     393                }
     394
     395                std::vector< ast::ptr< ast::Stmt > > stmts;
     396                genCall(
     397                        srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
     398
     399                if ( stmts.empty() ) {
     400                        return {};
     401                } else if ( stmts.size() == 1 ) {
     402                        const ast::Stmt * callStmt = stmts.front();
     403                        if ( addCast ) {
     404                                // implicitly generated ctor/dtor calls should be wrapped so that later passes are
     405                                // aware they were generated.
     406                                callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
     407                        }
     408                        return callStmt;
     409                } else {
     410                        assert( false );
     411                        return {};
     412                }
     413        }
    219414} // namespace SymTab
    220415
  • src/SymTab/FixFunction.cc

    r24d6572 r34b4268  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
    23 #include "Common/utility.h"       // for copy
     23#include "Common/utility.h"       // for maybeClone, copy
    2424#include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
    2525#include "SynTree/Expression.h"   // for Expression
  • src/SymTab/Indexer.cc

    r24d6572 r34b4268  
    3131#include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
    3232#include "Mangler.h"               // for Mangler
    33 #include "ResolvExpr/AlternativeFinder.h"  // for referenceToRvalueConversion
    34 #include "ResolvExpr/Unify.h"      // for typesCompatible
     33#include "ResolvExpr/typeops.h"    // for typesCompatible
    3534#include "SynTree/LinkageSpec.h"   // for isMangled, isOverridable, Spec
    3635#include "SynTree/Constant.h"      // for Constant
  • src/SymTab/Mangler.cc

    r24d6572 r34b4268  
    2424#include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
    2525#include "Common/PassVisitor.h"
    26 #include "Common/ToString.hpp"           // for toCString
    2726#include "Common/SemanticError.h"        // for SemanticError
     27#include "Common/utility.h"              // for toString
    2828#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    2929#include "SynTree/LinkageSpec.h"         // for Spec, isOverridable, AutoGen, Int...
     
    439439                  private:
    440440                        void mangleDecl( const ast::DeclWithType *declaration );
    441                         void mangleRef( const ast::BaseInstType *refType, const std::string & prefix );
     441                        void mangleRef( const ast::BaseInstType *refType, std::string prefix );
    442442
    443443                        void printQualifiers( const ast::Type *type );
     
    535535                }
    536536
     537                __attribute__((unused))
     538                inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) {
     539                        std::vector< ast::ptr< ast::Type > > ret;
     540                        std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
     541                                                        std::mem_fun( &ast::DeclWithType::get_type ) );
     542                        return ret;
     543                }
     544
    537545                void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
    538546                        printQualifiers( functionType );
     
    550558                }
    551559
    552                 void Mangler_new::mangleRef(
    553                                 const ast::BaseInstType * refType, const std::string & prefix ) {
     560                void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) {
    554561                        printQualifiers( refType );
    555562
    556563                        mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
    557564
    558                         if ( mangleGenericParams && ! refType->params.empty() ) {
    559                                 mangleName += "_";
    560                                 for ( const ast::Expr * param : refType->params ) {
    561                                         auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
    562                                         assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
    563                                         maybeAccept( paramType->type.get(), *visitor );
     565                        if ( mangleGenericParams ) {
     566                                if ( ! refType->params.empty() ) {
     567                                        mangleName += "_";
     568                                        for ( const ast::Expr * param : refType->params ) {
     569                                                auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
     570                                                assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
     571                                                maybeAccept( paramType->type.get(), *visitor );
     572                                        }
     573                                        mangleName += "_";
    564574                                }
    565                                 mangleName += "_";
    566575                        }
    567576                }
     
    647656                }
    648657
    649                 // For debugging:
    650658                __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
    651659                        for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
     
    657665                        // skip if not including qualifiers
    658666                        if ( typeMode ) return;
    659                         auto funcType = dynamic_cast<const ast::FunctionType *>( type );
    660                         if ( funcType && !funcType->forall.empty() ) {
    661                                 std::list< std::string > assertionNames;
    662                                 int dcount = 0, fcount = 0, vcount = 0, acount = 0;
    663                                 mangleName += Encoding::forall;
    664                                 for ( auto & decl : funcType->forall ) {
    665                                         switch ( decl->kind ) {
    666                                         case ast::TypeDecl::Dtype:
    667                                                 dcount++;
    668                                                 break;
    669                                         case ast::TypeDecl::Ftype:
    670                                                 fcount++;
    671                                                 break;
    672                                         case ast::TypeDecl::Ttype:
    673                                                 vcount++;
    674                                                 break;
    675                                         default:
    676                                                 assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() );
    677                                         } // switch
    678                                         varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
    679                                 } // for
    680                                 for ( auto & assert : funcType->assertions ) {
    681                                         assertionNames.push_back( ast::Pass<Mangler_new>::read(
    682                                                 assert->var.get(),
    683                                                 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
    684                                         acount++;
    685                                 } // for
    686                                 mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
    687                                 for ( const auto & a : assertionNames ) mangleName += a;
    688                                 mangleName += "_";
     667                        if ( auto ptype = dynamic_cast< const ast::FunctionType * >(type) ) {
     668                                if ( ! ptype->forall.empty() ) {
     669                                        std::list< std::string > assertionNames;
     670                                        int dcount = 0, fcount = 0, vcount = 0, acount = 0;
     671                                        mangleName += Encoding::forall;
     672                                        for ( auto & decl : ptype->forall ) {
     673                                                switch ( decl->kind ) {
     674                                                  case ast::TypeDecl::Kind::Dtype:
     675                                                        dcount++;
     676                                                        break;
     677                                                  case ast::TypeDecl::Kind::Ftype:
     678                                                        fcount++;
     679                                                        break;
     680                                                  case ast::TypeDecl::Kind::Ttype:
     681                                                        vcount++;
     682                                                        break;
     683                                                  default:
     684                                                        assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() );
     685                                                } // switch
     686                                                varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
     687                                        } // for
     688                                        for ( auto & assert : ptype->assertions ) {
     689                                                assertionNames.push_back( ast::Pass<Mangler_new>::read(
     690                                                        assert->var.get(),
     691                                                        mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
     692                                                acount++;
     693                                        } // for
     694                                        mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
     695                                        for(const auto & a : assertionNames) mangleName += a;
     696//                                      std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
     697                                        mangleName += "_";
     698                                } // if
    689699                        } // if
    690700                        if ( ! inFunctionType ) {
  • src/SymTab/Validate.cc

    r24d6572 r34b4268  
    5555#include "Common/ScopedMap.h"          // for ScopedMap
    5656#include "Common/SemanticError.h"      // for SemanticError
    57 #include "Common/ToString.hpp"         // for toCString
    5857#include "Common/UniqueName.h"         // for UniqueName
    59 #include "Common/utility.h"            // for cloneAll, deleteAll
     58#include "Common/utility.h"            // for operator+, cloneAll, deleteAll
    6059#include "CompilationState.h"          // skip some passes in new-ast build
    6160#include "Concurrency/Keywords.h"      // for applyKeywords
     
    6463#include "InitTweak/GenInit.h"         // for fixReturnStatements
    6564#include "InitTweak/InitTweak.h"       // for isCtorDtorAssign
    66 #include "ResolvExpr/typeops.h"        // for extractResultType
    67 #include "ResolvExpr/Unify.h"          // for typesCompatible
     65#include "ResolvExpr/typeops.h"        // for typesCompatible
    6866#include "ResolvExpr/Resolver.h"       // for findSingleExpression
    6967#include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
     
    864862
    865863        void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
    866                 typedefNames.erase( typeDecl->name );
     864                TypedefMap::iterator i = typedefNames.find( typeDecl->name );
     865                if ( i != typedefNames.end() ) {
     866                        typedefNames.erase( i ) ;
     867                } // if
     868
    867869                typedeclNames.insert( typeDecl->name, typeDecl );
    868870        }
  • src/SymTab/ValidateType.cc

    r24d6572 r34b4268  
    1818#include "CodeGen/OperatorTable.h"
    1919#include "Common/PassVisitor.h"
    20 #include "Common/ToString.hpp"
    2120#include "SymTab/FixFunction.h"
    2221#include "SynTree/Declaration.h"
  • src/SymTab/module.mk

    r24d6572 r34b4268  
    2020        SymTab/FixFunction.cc \
    2121        SymTab/FixFunction.h \
    22         SymTab/GenImplicitCall.cpp \
    23         SymTab/GenImplicitCall.hpp \
    2422        SymTab/Indexer.cc \
    2523        SymTab/Indexer.h \
  • src/SynTree/AggregateDecl.cc

    r24d6572 r34b4268  
    1919
    2020#include "Attribute.h"           // for Attribute
    21 #include "Common/Eval.h"         // for eval
    2221#include "Common/utility.h"      // for printAll, cloneAll, deleteAll
    2322#include "Declaration.h"         // for AggregateDecl, TypeDecl, Declaration
  • src/SynTree/ApplicationExpr.cc

    r24d6572 r34b4268  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ApplicationExpr.cc --
     7// ApplicationExpr.cc.cc --
    88//
    99// Author           : Richard C. Bilson
     
    2626#include "Expression.h"          // for ParamEntry, ApplicationExpr, Expression
    2727#include "InitTweak/InitTweak.h" // for getFunction
    28 #include "ResolvExpr/Unify.h"    // for extractResultType
     28#include "ResolvExpr/typeops.h"  // for extractResultType
    2929#include "Type.h"                // for Type, PointerType, FunctionType
    3030
  • src/SynTree/BasicType.cc

    r24d6572 r34b4268  
    2929}
    3030
     31bool BasicType::isWholeNumber() const {
     32        return kind == Bool ||
     33                kind ==Char ||
     34                kind == SignedChar ||
     35                kind == UnsignedChar ||
     36                kind == ShortSignedInt ||
     37                kind == ShortUnsignedInt ||
     38                kind == SignedInt ||
     39                kind == UnsignedInt ||
     40                kind == LongSignedInt ||
     41                kind == LongUnsignedInt ||
     42                kind == LongLongSignedInt ||
     43                kind ==LongLongUnsignedInt ||
     44                kind == SignedInt128 ||
     45                kind == UnsignedInt128;
     46}
     47
    3148bool BasicType::isInteger() const {
    3249        return kind <= UnsignedInt128;
  • src/SynTree/FunctionDecl.cc

    r24d6572 r34b4268  
    8787        } // if
    8888
    89         if ( !withExprs.empty() ) {
    90                 os << indent << "... with clause" << std::endl;
    91                 os << indent + 1;
    92                 printAll( withExprs, os, indent + 1 );
    93         }
    94 
    9589        if ( statements ) {
    9690                os << indent << "... with body" << endl << indent+1;
  • src/SynTree/Type.cc

    r24d6572 r34b4268  
    1616
    1717#include "Attribute.h"                // for Attribute
    18 #include "Common/ToString.hpp"        // for toCString
    1918#include "Common/utility.h"           // for cloneAll, deleteAll, printAll
    2019#include "InitTweak/InitTweak.h"      // for getPointerBase
     
    106105int Type::referenceDepth() const { return 0; }
    107106
    108 AggregateDecl * Type::getAggr() const {
    109         assertf( false, "Non-aggregate type: %s", toCString( this ) );
    110 }
    111 
    112107TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
    113108
  • src/SynTree/Type.h

    r24d6572 r34b4268  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Feb 19 22:37:10 2023
    13 // Update Count     : 176
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jul 14 15:40:00 2021
     13// Update Count     : 171
    1414//
    1515
     
    2323
    2424#include "BaseSyntaxNode.h"  // for BaseSyntaxNode
    25 #include "Common/Iterate.hpp"// for operator+
     25#include "Common/utility.h"  // for operator+
    2626#include "Mutator.h"         // for Mutator
    2727#include "SynTree.h"         // for AST nodes
     
    124124                bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); }
    125125                bool operator<=( Qualifiers other ) const {
    126                         return is_const    <= other.is_const        // Any non-const converts to const without cost
    127                                 && is_volatile <= other.is_volatile             // Any non-volatile converts to volatile without cost
    128                                 && is_mutex    >= other.is_mutex                // Any mutex converts to non-mutex without cost
    129                                 && is_atomic   == other.is_atomic;              // No conversion from atomic to non atomic is free
     126                        return is_const    <= other.is_const        //Any non-const converts to const without cost
     127                                        && is_volatile <= other.is_volatile     //Any non-volatile converts to volatile without cost
     128                                        && is_mutex    >= other.is_mutex        //Any mutex converts to non-mutex without cost
     129                                        && is_atomic   == other.is_atomic;      //No conversion from atomic to non atomic is free
    130130                }
    131131                bool operator<( Qualifiers other ) const { return *this != other && *this <= other; }
     
    185185        virtual bool isComplete() const { return true; }
    186186
    187         virtual AggregateDecl * getAggr() const;
     187        virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
    188188
    189189        virtual TypeSubstitution genericSubstitution() const;
    190190
    191         virtual Type * clone() const = 0;
     191        virtual Type *clone() const = 0;
    192192        virtual void accept( Visitor & v ) = 0;
    193193        virtual void accept( Visitor & v ) const = 0;
    194         virtual Type * acceptMutator( Mutator & m ) = 0;
     194        virtual Type *acceptMutator( Mutator & m ) = 0;
    195195        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    196196};
     
    207207        virtual bool isComplete() const override { return false; }
    208208
    209         virtual VoidType * clone() const override { return new VoidType( *this ); }
    210         virtual void accept( Visitor & v ) override { v.visit( this ); }
    211         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    212         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     209        virtual VoidType *clone() const override { return new VoidType( *this ); }
     210        virtual void accept( Visitor & v ) override { v.visit( this ); }
     211        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     212        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    213213        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    214214};
     
    259259        // GENERATED END
    260260
    261         static const char * typeNames[];                                        // string names for basic types, MUST MATCH with Kind
     261        static const char *typeNames[];                                         // string names for basic types, MUST MATCH with Kind
    262262
    263263        BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     
    266266        void set_kind( Kind newValue ) { kind = newValue; }
    267267
    268         virtual BasicType * clone() const override { return new BasicType( *this ); }
    269         virtual void accept( Visitor & v ) override { v.visit( this ); }
    270         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    271         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    272         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     268        virtual BasicType *clone() const override { return new BasicType( *this ); }
     269        virtual void accept( Visitor & v ) override { v.visit( this ); }
     270        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     271        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     272        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     273        bool isWholeNumber() const;
    273274        bool isInteger() const;
    274275};
     
    279280
    280281        // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] )
    281         Expression * dimension;
     282        Expression *dimension;
    282283        bool isVarLen;
    283284        bool isStatic;
    284285
    285         PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    286         PointerType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     286        PointerType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     287        PointerType( const Type::Qualifiers & tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    287288        PointerType( const PointerType& );
    288289        virtual ~PointerType();
    289290
    290         Type * get_base() { return base; }
    291         void set_base( Type * newValue ) { base = newValue; }
    292         Expression * get_dimension() { return dimension; }
    293         void set_dimension( Expression * newValue ) { dimension = newValue; }
     291        Type *get_base() { return base; }
     292        void set_base( Type *newValue ) { base = newValue; }
     293        Expression *get_dimension() { return dimension; }
     294        void set_dimension( Expression *newValue ) { dimension = newValue; }
    294295        bool get_isVarLen() { return isVarLen; }
    295296        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    301302        virtual bool isComplete() const override { return ! isVarLen; }
    302303
    303         virtual PointerType * clone() const override { return new PointerType( * this ); }
    304         virtual void accept( Visitor & v ) override { v.visit( this ); }
    305         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    306         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     304        virtual PointerType *clone() const override { return new PointerType( *this ); }
     305        virtual void accept( Visitor & v ) override { v.visit( this ); }
     306        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     307        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    307308        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    308309};
     
    310311class ArrayType : public Type {
    311312  public:
    312         Type * base;
    313         Expression * dimension;
     313        Type *base;
     314        Expression *dimension;
    314315        bool isVarLen;
    315316        bool isStatic;
    316317
    317         ArrayType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     318        ArrayType( const Type::Qualifiers & tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    318319        ArrayType( const ArrayType& );
    319320        virtual ~ArrayType();
    320321
    321         Type * get_base() { return base; }
    322         void set_base( Type * newValue ) { base = newValue; }
    323         Expression * get_dimension() { return dimension; }
    324         void set_dimension( Expression * newValue ) { dimension = newValue; }
     322        Type *get_base() { return base; }
     323        void set_base( Type *newValue ) { base = newValue; }
     324        Expression *get_dimension() { return dimension; }
     325        void set_dimension( Expression *newValue ) { dimension = newValue; }
    325326        bool get_isVarLen() { return isVarLen; }
    326327        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    333334        virtual bool isComplete() const override { return dimension || isVarLen; }
    334335
    335         virtual ArrayType * clone() const override { return new ArrayType( *this ); }
    336         virtual void accept( Visitor & v ) override { v.visit( this ); }
    337         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    338         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     336        virtual ArrayType *clone() const override { return new ArrayType( *this ); }
     337        virtual void accept( Visitor & v ) override { v.visit( this ); }
     338        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     339        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    339340        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    340341};
     
    348349        virtual ~QualifiedType();
    349350
    350         virtual QualifiedType * clone() const override { return new QualifiedType( *this ); }
    351         virtual void accept( Visitor & v ) override { v.visit( this ); }
    352         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    353         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     351        virtual QualifiedType *clone() const override { return new QualifiedType( *this ); }
     352        virtual void accept( Visitor & v ) override { v.visit( this ); }
     353        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     354        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    354355        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    355356};
     
    357358class ReferenceType : public Type {
    358359public:
    359         Type * base;
    360 
    361         ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     360        Type *base;
     361
     362        ReferenceType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    362363        ReferenceType( const ReferenceType & );
    363364        virtual ~ReferenceType();
    364365
    365         Type * get_base() { return base; }
    366         void set_base( Type * newValue ) { base = newValue; }
     366        Type *get_base() { return base; }
     367        void set_base( Type *newValue ) { base = newValue; }
    367368
    368369        virtual int referenceDepth() const override;
     
    375376        virtual TypeSubstitution genericSubstitution() const override;
    376377
    377         virtual ReferenceType * clone() const override { return new ReferenceType( *this ); }
    378         virtual void accept( Visitor & v ) override { v.visit( this ); }
    379         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    380         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     378        virtual ReferenceType *clone() const override { return new ReferenceType( *this ); }
     379        virtual void accept( Visitor & v ) override { v.visit( this ); }
     380        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     381        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    381382        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    382383};
     
    405406        bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
    406407
    407         virtual FunctionType * clone() const override { return new FunctionType( *this ); }
    408         virtual void accept( Visitor & v ) override { v.visit( this ); }
    409         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    410         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     408        virtual FunctionType *clone() const override { return new FunctionType( *this ); }
     409        virtual void accept( Visitor & v ) override { v.visit( this ); }
     410        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     411        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    411412        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    412413};
     
    414415class ReferenceToType : public Type {
    415416  public:
    416         std::list< Expression * > parameters;
     417        std::list< Expression* > parameters;
    417418        std::string name;
    418419        bool hoistType;
     
    428429        void set_hoistType( bool newValue ) { hoistType = newValue; }
    429430
    430         virtual ReferenceToType * clone() const override = 0;
     431        virtual ReferenceToType *clone() const override = 0;
    431432        virtual void accept( Visitor & v ) override = 0;
    432         virtual Type * acceptMutator( Mutator & m ) override = 0;
     433        virtual Type *acceptMutator( Mutator & m ) override = 0;
    433434        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    434435
     
    443444        // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree,
    444445        // where the structure used in this type is actually defined
    445         StructDecl * baseStruct;
     446        StructDecl *baseStruct;
    446447
    447448        StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseStruct( 0 ) {}
     
    449450        StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {}
    450451
    451         StructDecl * get_baseStruct() const { return baseStruct; }
    452         void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }
     452        StructDecl *get_baseStruct() const { return baseStruct; }
     453        void set_baseStruct( StructDecl *newValue ) { baseStruct = newValue; }
    453454
    454455        /// Accesses generic parameters of base struct (NULL if none such)
     
    466467        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    467468
    468         virtual StructInstType * clone() const override { return new StructInstType( *this ); }
    469         virtual void accept( Visitor & v ) override { v.visit( this ); }
    470         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    471         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     469        virtual StructInstType *clone() const override { return new StructInstType( *this ); }
     470        virtual void accept( Visitor & v ) override { v.visit( this ); }
     471        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     472        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    472473
    473474        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    481482        // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree,
    482483        // where the union used in this type is actually defined
    483         UnionDecl * baseUnion;
     484        UnionDecl *baseUnion;
    484485
    485486        UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseUnion( 0 ) {}
     
    487488        UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {}
    488489
    489         UnionDecl * get_baseUnion() const { return baseUnion; }
     490        UnionDecl *get_baseUnion() const { return baseUnion; }
    490491        void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; }
    491492
     
    504505        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    505506
    506         virtual UnionInstType * clone() const override { return new UnionInstType( *this ); }
    507         virtual void accept( Visitor & v ) override { v.visit( this ); }
    508         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    509         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     507        virtual UnionInstType *clone() const override { return new UnionInstType( *this ); }
     508        virtual void accept( Visitor & v ) override { v.visit( this ); }
     509        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     510        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    510511
    511512        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    519520        // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree,
    520521        // where the enum used in this type is actually defined
    521         EnumDecl * baseEnum = nullptr;
     522        EnumDecl *baseEnum = nullptr;
    522523
    523524        EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
     
    525526        EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {}
    526527
    527         EnumDecl * get_baseEnum() const { return baseEnum; }
    528         void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }
     528        EnumDecl *get_baseEnum() const { return baseEnum; }
     529        void set_baseEnum( EnumDecl *newValue ) { baseEnum = newValue; }
    529530
    530531        virtual bool isComplete() const override;
     
    532533        virtual AggregateDecl * getAggr() const override;
    533534
    534         virtual EnumInstType * clone() const override { return new EnumInstType( *this ); }
    535         virtual void accept( Visitor & v ) override { v.visit( this ); }
    536         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    537         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     535        virtual EnumInstType *clone() const override { return new EnumInstType( *this ); }
     536        virtual void accept( Visitor & v ) override { v.visit( this ); }
     537        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     538        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    538539
    539540        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    556557        virtual bool isComplete() const override;
    557558
    558         virtual TraitInstType * clone() const override { return new TraitInstType( *this ); }
    559         virtual void accept( Visitor & v ) override { v.visit( this ); }
    560         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    561         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     559        virtual TraitInstType *clone() const override { return new TraitInstType( *this ); }
     560        virtual void accept( Visitor & v ) override { v.visit( this ); }
     561        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     562        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    562563  private:
    563564        virtual std::string typeString() const override;
     
    569570        // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree,
    570571        // where the type used here is actually defined
    571         TypeDecl * baseType;
     572        TypeDecl *baseType;
    572573        bool isFtype;
    573574
    574         TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     575        TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl *baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    575576        TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    576577        TypeInstType( const TypeInstType & other );
    577578        ~TypeInstType();
    578579
    579         TypeDecl * get_baseType() const { return baseType; }
    580         void set_baseType( TypeDecl * newValue );
     580        TypeDecl *get_baseType() const { return baseType; }
     581        void set_baseType( TypeDecl *newValue );
    581582        bool get_isFtype() const { return isFtype; }
    582583        void set_isFtype( bool newValue ) { isFtype = newValue; }
     
    584585        virtual bool isComplete() const override;
    585586
    586         virtual TypeInstType * clone() const override { return new TypeInstType( *this ); }
    587         virtual void accept( Visitor & v ) override { v.visit( this ); }
    588         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    589         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     587        virtual TypeInstType *clone() const override { return new TypeInstType( *this ); }
     588        virtual void accept( Visitor & v ) override { v.visit( this ); }
     589        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     590        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    590591        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    591592  private:
     
    622623        // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness
    623624
    624         virtual TupleType * clone() const override { return new TupleType( *this ); }
    625         virtual void accept( Visitor & v ) override { v.visit( this ); }
    626         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    627         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     625        virtual TupleType *clone() const override { return new TupleType( *this ); }
     626        virtual void accept( Visitor & v ) override { v.visit( this ); }
     627        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     628        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    628629        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    629630};
     
    631632class TypeofType : public Type {
    632633  public:
    633         Expression * expr;              ///< expression to take the type of
    634         bool is_basetypeof;             ///< true iff is basetypeof type
    635 
    636         TypeofType( const Type::Qualifiers & tq, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    637         TypeofType( const Type::Qualifiers & tq, Expression * expr, bool is_basetypeof,
     634        Expression *expr;    ///< expression to take the type of
     635        bool is_basetypeof;  ///< true iff is basetypeof type
     636
     637        TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     638        TypeofType( const Type::Qualifiers & tq, Expression *expr, bool is_basetypeof,
    638639                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    639640        TypeofType( const TypeofType& );
    640641        virtual ~TypeofType();
    641642
    642         Expression * get_expr() const { return expr; }
    643         void set_expr( Expression * newValue ) { expr = newValue; }
     643        Expression *get_expr() const { return expr; }
     644        void set_expr( Expression *newValue ) { expr = newValue; }
    644645
    645646        virtual bool isComplete() const override { assert( false ); return false; }
    646647
    647         virtual TypeofType * clone() const override { return new TypeofType( *this ); }
    648         virtual void accept( Visitor & v ) override { v.visit( this ); }
    649         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    650         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     648        virtual TypeofType *clone() const override { return new TypeofType( *this ); }
     649        virtual void accept( Visitor & v ) override { v.visit( this ); }
     650        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     651        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    651652        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    652653};
     
    654655class VTableType : public Type {
    655656public:
    656         Type * base;
    657 
    658         VTableType( const Type::Qualifiers & tq, Type * base,
     657        Type *base;
     658
     659        VTableType( const Type::Qualifiers & tq, Type *base,
    659660                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    660661        VTableType( const VTableType & );
    661662        virtual ~VTableType();
    662663
    663         Type * get_base() { return base; }
    664         void set_base( Type * newValue ) { base = newValue; }
    665 
    666         virtual VTableType * clone() const override { return new VTableType( *this ); }
    667         virtual void accept( Visitor & v ) override { v.visit( this ); }
    668         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    669         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     664        Type *get_base() { return base; }
     665        void set_base( Type *newValue ) { base = newValue; }
     666
     667        virtual VTableType *clone() const override { return new VTableType( *this ); }
     668        virtual void accept( Visitor & v ) override { v.visit( this ); }
     669        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     670        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    670671        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    671672};
     
    674675  public:
    675676        std::string name;
    676         Expression * expr;
    677         Type * type;
     677        Expression *expr;
     678        Type *type;
    678679        bool isType;
    679680
    680         AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    681         AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     681        AttrType( const Type::Qualifiers & tq, const std::string & name, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     682        AttrType( const Type::Qualifiers & tq, const std::string & name, Type *type, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    682683        AttrType( const AttrType& );
    683684        virtual ~AttrType();
     
    685686        const std::string & get_name() const { return name; }
    686687        void set_name( const std::string & newValue ) { name = newValue; }
    687         Expression * get_expr() const { return expr; }
    688         void set_expr( Expression * newValue ) { expr = newValue; }
    689         Type * get_type() const { return type; }
    690         void set_type( Type * newValue ) { type = newValue; }
     688        Expression *get_expr() const { return expr; }
     689        void set_expr( Expression *newValue ) { expr = newValue; }
     690        Type *get_type() const { return type; }
     691        void set_type( Type *newValue ) { type = newValue; }
    691692        bool get_isType() const { return isType; }
    692693        void set_isType( bool newValue ) { isType = newValue; }
     
    694695        virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here
    695696
    696         virtual AttrType * clone() const override { return new AttrType( *this ); }
    697         virtual void accept( Visitor & v ) override { v.visit( this ); }
    698         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    699         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     697        virtual AttrType *clone() const override { return new AttrType( *this ); }
     698        virtual void accept( Visitor & v ) override { v.visit( this ); }
     699        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     700        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    700701        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    701702};
     
    709710        virtual bool isComplete() const override{ return true; } // xxx - is this right?
    710711
    711         virtual VarArgsType * clone() const override { return new VarArgsType( *this ); }
    712         virtual void accept( Visitor & v ) override { v.visit( this ); }
    713         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    714         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     712        virtual VarArgsType *clone() const override { return new VarArgsType( *this ); }
     713        virtual void accept( Visitor & v ) override { v.visit( this ); }
     714        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     715        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    715716        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    716717};
     
    722723        ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    723724
    724         virtual ZeroType * clone() const override { return new ZeroType( *this ); }
    725         virtual void accept( Visitor & v ) override { v.visit( this ); }
    726         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    727         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     725        virtual ZeroType *clone() const override { return new ZeroType( *this ); }
     726        virtual void accept( Visitor & v ) override { v.visit( this ); }
     727        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     728        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    728729        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    729730};
     
    735736        OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    736737
    737         virtual OneType * clone() const override { return new OneType( *this ); }
    738         virtual void accept( Visitor & v ) override { v.visit( this ); }
    739         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    740         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     738        virtual OneType *clone() const override { return new OneType( *this ); }
     739        virtual void accept( Visitor & v ) override { v.visit( this ); }
     740        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     741        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    741742        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    742743};
     
    746747        GlobalScopeType();
    747748
    748         virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); }
    749         virtual void accept( Visitor & v ) override { v.visit( this ); }
    750         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    751         virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     749        virtual GlobalScopeType *clone() const override { return new GlobalScopeType( *this ); }
     750        virtual void accept( Visitor & v ) override { v.visit( this ); }
     751        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     752        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    752753        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    753754};
  • src/Tuples/Explode.cc

    r24d6572 r34b4268  
    1717#include <list>                  // for list
    1818
    19 #include "AST/Pass.hpp"          // for Pass
    2019#include "SynTree/Mutator.h"     // for Mutator
    2120#include "Common/PassVisitor.h"  // for PassVisitor
  • src/Validate/Autogen.cpp

    r24d6572 r34b4268  
    2525
    2626#include "AST/Attribute.hpp"
    27 #include "AST/Copy.hpp"
    2827#include "AST/Create.hpp"
    2928#include "AST/Decl.hpp"
     
    4039#include "InitTweak/GenInit.h"     // for fixReturnStatements
    4140#include "InitTweak/InitTweak.h"   // for isAssignment, isCopyConstructor
    42 #include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    4341#include "SymTab/Mangler.h"        // for Mangler
    4442#include "CompilationState.h"
     43
     44// TODO: The other new ast function should be moved over to this file.
     45#include "SymTab/Autogen.h"
    4546
    4647namespace Validate {
     
    9394
    9495        const CodeLocation& getLocation() const { return getDecl()->location; }
    95         ast::FunctionDecl * genProto( std::string&& name,
     96        ast::FunctionDecl * genProto( const std::string& name,
    9697                std::vector<ast::ptr<ast::DeclWithType>>&& params,
    9798                std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const;
     
    321322void FuncGenerator::produceDecl( const ast::FunctionDecl * decl ) {
    322323        assert( nullptr != decl->stmts );
    323         const auto & oldParams = getGenericParams(type);
    324         assert( decl->type_params.size() == oldParams.size());
    325 
    326         /*
    327         ast::DeclReplacer::TypeMap typeMap;
    328         for (auto it = oldParams.begin(), jt = decl->type_params.begin(); it != oldParams.end(); ++it, ++jt) {
    329                 typeMap.emplace(*it, *jt);
    330         }
    331 
    332         const ast::FunctionDecl * mut = strict_dynamic_cast<const ast::FunctionDecl *>(ast::DeclReplacer::replace(decl, typeMap));
    333         assert (mut == decl);
    334         */
    335324
    336325        definitions.push_back( decl );
     
    346335}
    347336
    348 void replaceAll( std::vector<ast::ptr<ast::DeclWithType>> & dwts,
    349                 const ast::DeclReplacer::TypeMap & map ) {
    350         for ( auto & dwt : dwts ) {
    351                 dwt = strict_dynamic_cast<const ast::DeclWithType *>(
    352                                 ast::DeclReplacer::replace( dwt, map ) );
    353         }
    354 }
    355 
    356337/// Generates a basic prototype function declaration.
    357 ast::FunctionDecl * FuncGenerator::genProto( std::string&& name,
     338ast::FunctionDecl * FuncGenerator::genProto( const std::string& name,
    358339                std::vector<ast::ptr<ast::DeclWithType>>&& params,
    359340                std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const {
     
    361342        // Handle generic prameters and assertions, if any.
    362343        auto const & old_type_params = getGenericParams( type );
    363         ast::DeclReplacer::TypeMap oldToNew;
    364344        std::vector<ast::ptr<ast::TypeDecl>> type_params;
    365345        std::vector<ast::ptr<ast::DeclWithType>> assertions;
    366 
    367         ast::DeclReplacer::TypeMap typeMap;
    368346        for ( auto & old_param : old_type_params ) {
    369347                ast::TypeDecl * decl = ast::deepCopy( old_param );
    370                 decl->init = nullptr;
    371                 splice( assertions, decl->assertions );
    372                 oldToNew.emplace( std::make_pair( old_param, decl ) );
     348                for ( auto assertion : decl->assertions ) {
     349                        assertions.push_back( assertion );
     350                }
     351                decl->assertions.clear();
    373352                type_params.push_back( decl );
    374                 typeMap.emplace(old_param, decl);
    375         }
    376 
    377         for (auto & param : params) {
    378                 param = ast::DeclReplacer::replace(param, typeMap);
    379         }
    380         for (auto & param : returns) {
    381                 param = ast::DeclReplacer::replace(param, typeMap);
    382         }
    383         replaceAll( params, oldToNew );
    384         replaceAll( returns, oldToNew );
    385         replaceAll( assertions, oldToNew );
     353        }
     354        // TODO: The values in params and returns still may point at the old
     355        // generic params, that does not appear to be an issue but perhaps it
     356        // should be addressed.
    386357
    387358        ast::FunctionDecl * decl = new ast::FunctionDecl(
    388359                // Auto-generated routines use the type declaration's location.
    389360                getLocation(),
    390                 std::move( name ),
     361                name,
    391362                std::move( type_params ),
    392363                std::move( assertions ),
     
    452423        for ( unsigned int index = 0 ; index < fields ; ++index ) {
    453424                auto member = aggr->members[index].strict_as<ast::DeclWithType>();
    454                 if ( ast::isUnnamedBitfield(
     425                if ( SymTab::isUnnamedBitfield(
    455426                                dynamic_cast<const ast::ObjectDecl *>( member ) ) ) {
    456427                        if ( index == fields - 1 ) {
     
    544515        InitTweak::InitExpander_new srcParam( src );
    545516        // Assign to destination.
    546         ast::MemberExpr * dstSelect = new ast::MemberExpr(
     517        ast::Expr * dstSelect = new ast::MemberExpr(
    547518                location,
    548519                field,
     
    596567                }
    597568
    598                 ast::MemberExpr * srcSelect = (srcParam) ? new ast::MemberExpr(
     569                ast::Expr * srcSelect = (srcParam) ? new ast::MemberExpr(
    599570                        location, field, new ast::VariableExpr( location, srcParam )
    600571                ) : nullptr;
     
    628599                // Not sure why it could be null.
    629600                // Don't make a function for a parameter that is an unnamed bitfield.
    630                 if ( nullptr == field || ast::isUnnamedBitfield( field ) ) {
     601                if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) {
    631602                        continue;
    632603                // Matching Parameter: Initialize the field by copy.
  • src/Validate/FixQualifiedTypes.cpp

    r24d6572 r34b4268  
    1616#include "Validate/FixQualifiedTypes.hpp"
    1717
    18 #include "AST/Copy.hpp"
    19 #include "AST/LinkageSpec.hpp"             // for Linkage
    2018#include "AST/Pass.hpp"
    2119#include "AST/TranslationUnit.hpp"
    22 #include "Common/ToString.hpp"             // for toString
    23 #include "SymTab/Mangler.h"                // for Mangler
    2420#include "Validate/NoIdSymbolTable.hpp"
     21#include "SymTab/Mangler.h"            // for Mangler
     22#include "AST/LinkageSpec.hpp"                     // for Linkage
    2523
    2624namespace Validate {
  • src/Validate/FixReturnTypes.cpp

    r24d6572 r34b4268  
    2020#include "AST/Type.hpp"
    2121#include "CodeGen/CodeGenerator.h"
    22 #include "ResolvExpr/Unify.h"
     22#include "ResolvExpr/typeops.h"
    2323
    2424namespace ast {
  • src/Validate/ForallPointerDecay.cpp

    r24d6572 r34b4268  
    2222#include "CodeGen/OperatorTable.h"
    2323#include "Common/CodeLocation.h"
    24 #include "Common/ToString.hpp"
    2524#include "SymTab/FixFunction.h"
    2625
  • src/Validate/GenericParameter.cpp

    r24d6572 r34b4268  
    1616#include "GenericParameter.hpp"
    1717
    18 #include "AST/Copy.hpp"
    1918#include "AST/Decl.hpp"
    2019#include "AST/Expr.hpp"
  • src/Validate/HandleAttributes.cc

    r24d6572 r34b4268  
    1717
    1818#include "CompilationState.h"
    19 #include "Common/Eval.h"
    2019#include "Common/PassVisitor.h"
    21 #include "Common/ToString.hpp"
    2220#include "Common/SemanticError.h"
    2321#include "ResolvExpr/Resolver.h"
  • src/Validate/HoistStruct.cpp

    r24d6572 r34b4268  
    1616#include "Validate/HoistStruct.hpp"
    1717
    18 #include <sstream>
    19 
    2018#include "AST/Pass.hpp"
    2119#include "AST/TranslationUnit.hpp"
     20#include "Common/utility.h"
    2221
    2322namespace Validate {
  • src/Validate/ReplaceTypedef.cpp

    r24d6572 r34b4268  
    1616#include "ReplaceTypedef.hpp"
    1717
    18 #include "AST/Copy.hpp"
    1918#include "AST/Pass.hpp"
    2019#include "Common/ScopedMap.h"
    2120#include "Common/UniqueName.h"
    2221#include "Common/utility.h"
    23 #include "ResolvExpr/Unify.h"
     22#include "ResolvExpr/typeops.h"
    2423
    2524namespace Validate {
     
    150149                // constant/enumerator. The effort required to fix this corner case
    151150                // likely outweighs the utility of allowing it.
    152                 if ( !ResolvExpr::typesCompatible( t0, t1 )
     151                if ( !ResolvExpr::typesCompatible( t0, t1, ast::SymbolTable() )
    153152                                || ast::Pass<VarLenChecker>::read( t0 )
    154153                                || ast::Pass<VarLenChecker>::read( t1 ) ) {
     
    187186
    188187void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) {
    189         typedefNames.erase( decl->name );
     188        TypedefMap::iterator iter = typedefNames.find( decl->name );
     189        if ( iter != typedefNames.end() ) {
     190                typedefNames.erase( iter );
     191        }
    190192        typedeclNames.insert( decl->name, decl );
    191193}
  • src/Virtual/ExpandCasts.cc

    r24d6572 r34b4268  
    2020#include <string>                  // for string, allocator, operator==, ope...
    2121
    22 #include "AST/Copy.hpp"
    2322#include "AST/Decl.hpp"
    2423#include "AST/Expr.hpp"
  • src/Virtual/module.mk

    r24d6572 r34b4268  
    1919        Virtual/ExpandCasts.h \
    2020        Virtual/Tables.cc \
    21         Virtual/Tables.h \
    22         Virtual/VirtualDtor.cpp \
    23         Virtual/VirtualDtor.hpp
     21        Virtual/Tables.h
  • src/include/cassert

    r24d6572 r34b4268  
    2020#include_next <cassert>
    2121
    22 #include "Common/ToString.hpp"
     22#include <string>
     23
     24template < typename ... Params >
     25std::string toString( const Params & ... params );
    2326
    2427#ifdef NDEBUG
  • src/main.cc

    r24d6572 r34b4268  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 10 21:12:17 2023
    13 // Update Count     : 682
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Oct  5 12:06:00 2022
     13// Update Count     : 679
    1414//
    1515
     
    3232
    3333#include "AST/Convert.hpp"
    34 #include "AST/Pass.hpp"                     // for pass_visitor_stats
    35 #include "AST/TranslationUnit.hpp"          // for TranslationUnit
    36 #include "AST/Util.hpp"                     // for checkInvariants
    3734#include "CompilationState.h"
    3835#include "../config.h"                      // for CFA_LIBDIR
     
    4340#include "CodeTools/TrackLoc.h"             // for fillLocations
    4441#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
     42#include "Common/CompilerError.h"           // for CompilerError
    4543#include "Common/DeclStats.hpp"             // for printDeclStats
    4644#include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
    4745#include "Common/Stats.h"                   // for Stats
     46#include "Common/UnimplementedError.h"      // for UnimplementedError
    4847#include "Common/utility.h"                 // for deleteAll, filter, printAll
    49 #include "Concurrency/Actors.hpp"           // for implementActors
    5048#include "Concurrency/Keywords.h"           // for implementMutex, implement...
    5149#include "Concurrency/Waitfor.h"            // for generateWaitfor
    52 #include "Concurrency/Waituntil.hpp"        // for generateWaitUntil
    5350#include "ControlStruct/ExceptDecl.h"       // for translateExcept
    5451#include "ControlStruct/ExceptTranslate.h"  // for translateThrows, translat...
     
    6259#include "InitTweak/GenInit.h"              // for genInit
    6360#include "MakeLibCfa.h"                     // for makeLibCfa
    64 #include "Parser/RunParser.hpp"             // for buildList, dumpParseTree,...
     61#include "Parser/ParseNode.h"               // for DeclarationNode, buildList
     62#include "Parser/TypedefTable.h"            // for TypedefTable
    6563#include "ResolvExpr/CandidatePrinter.hpp"  // for printCandidates
    6664#include "ResolvExpr/Resolver.h"            // for resolve
     
    8684#include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign
    8785#include "Virtual/ExpandCasts.h"            // for expandCasts
    88 #include "Virtual/VirtualDtor.hpp"           // for implementVirtDtors
    8986
    9087static void NewPass( const char * const name ) {
     
    105102}
    106103
    107 // Helpers for checkInvariant:
    108 void checkInvariants( std::list< Declaration * > & ) {}
    109 using ast::checkInvariants;
    110 
    111 #define PASS( name, pass, unit, ... )       \
     104#define PASS( name, pass )                  \
    112105        if ( errorp ) { cerr << name << endl; } \
    113106        NewPass(name);                          \
    114107        Stats::Time::StartBlock(name);          \
    115         pass(unit,##__VA_ARGS__);               \
    116         Stats::Time::StopBlock();               \
    117         if ( invariant ) {                      \
    118                 checkInvariants(unit);              \
    119         }
    120 
    121 #define DUMP( cond, unit )                  \
    122         if ( cond ) {                           \
    123                 dump(unit);                         \
    124                 return EXIT_SUCCESS;                \
    125         }
     108        pass;                                   \
     109        Stats::Time::StopBlock();
     110
     111LinkageSpec::Spec linkage = LinkageSpec::Cforall;
     112TypedefTable typedefTable;
     113DeclarationNode * parseTree = nullptr;                                  // program parse tree
    126114
    127115static bool waiting_for_gdb = false;                                    // flag to set cfa-cpp to wait for gdb on start
     
    130118
    131119static void parse_cmdline( int argc, char * argv[] );
     120static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false );
    132121static void dump( list< Declaration * > & translationUnit, ostream & out = cout );
    133122static void dump( ast::TranslationUnit && transUnit, ostream & out = cout );
     
    245234        ostream * output = & cout;
    246235        list< Declaration * > translationUnit;
    247         ast::TranslationUnit transUnit;
    248236
    249237        Signal( SIGSEGV, sigSegvBusHandler, SA_SIGINFO );
     
    290278                        FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" );
    291279                        assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" );
    292                         parse( gcc_builtins, ast::Linkage::Compiler );
     280                        parse( gcc_builtins, LinkageSpec::Compiler );
    293281
    294282                        // read the extra prelude in, if not generating the cfa library
    295283                        FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" );
    296284                        assertf( extras, "cannot open extras.cf\n" );
    297                         parse( extras, ast::Linkage::BuiltinC );
     285                        parse( extras, LinkageSpec::BuiltinC );
    298286
    299287                        if ( ! libcfap ) {
     
    301289                                FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
    302290                                assertf( prelude, "cannot open prelude.cfa\n" );
    303                                 parse( prelude, ast::Linkage::Intrinsic );
     291                                parse( prelude, LinkageSpec::Intrinsic );
    304292
    305293                                // Read to cfa builtins, if not generating the cfa library
    306294                                FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" );
    307295                                assertf( builtins, "cannot open builtins.cf\n" );
    308                                 parse( builtins, ast::Linkage::BuiltinCFA );
    309                         } // if
    310                 } // if
    311 
    312                 parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug );
    313 
    314                 transUnit = buildUnit();
    315 
    316                 DUMP( astp, std::move( transUnit ) );
    317 
     296                                parse( builtins, LinkageSpec::BuiltinCFA );
     297                        } // if
     298                } // if
     299
     300                parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug );
     301
     302                if ( parsep ) {
     303                        parseTree->printList( cout );
     304                        delete parseTree;
     305                        return EXIT_SUCCESS;
     306                } // if
     307
     308                buildList( parseTree, translationUnit );
     309                delete parseTree;
     310                parseTree = nullptr;
     311
     312                if ( astp ) {
     313                        dump( translationUnit );
     314                        return EXIT_SUCCESS;
     315                } // if
     316
     317                // Temporary: fill locations after parsing so that every node has a location, for early error messages.
     318                // Eventually we should pass the locations from the parser to every node, but this quick and dirty solution
     319                // works okay for now.
     320                CodeTools::fillLocations( translationUnit );
    318321                Stats::Time::StopBlock();
    319322
     
    322325                        ast::pass_visitor_stats.max = Stats::Counters::build<Stats::Counters::MaxCounter<double>>("Max depth - New");
    323326                }
    324 
    325                 PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit );
    326 
    327                 PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit );
    328                 DUMP( exdeclp, std::move( transUnit ) );
    329                 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit );
    330                 PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit );
    331                 PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit );
    332                 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit );
    333 
    334                 PASS( "Link Reference To Types", Validate::linkReferenceToTypes, transUnit );
    335 
    336                 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit );
    337                 PASS( "Hoist Struct", Validate::hoistStruct, transUnit );
    338                 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit );
    339                 PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit );
    340                 PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit );
    341                 PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit );
    342                 PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit );
    343                 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit );
    344                 PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit );
    345         PASS( "Implement Waituntil", Concurrency::generateWaitUntil, transUnit  );
    346                 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit );
    347 
    348                 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit );
    349 
    350                 PASS( "Implement Actors", Concurrency::implementActors, transUnit );
    351                 PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit );
    352                 PASS( "Implement Mutex", Concurrency::implementMutex, transUnit );
    353                 PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit );
    354                 PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit );
    355                 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit );
    356                 PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit );
    357                 PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit );
     327                auto transUnit = convert( std::move( translationUnit ) );
     328
     329                forceFillCodeLocations( transUnit );
     330
     331                PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) );
     332                if ( exdeclp ) {
     333                        dump( std::move( transUnit ) );
     334                        return EXIT_SUCCESS;
     335                }
     336
     337                PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) );
     338                PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) );
     339                // Hoist Type Decls pulls some declarations out of contexts where
     340                // locations are not tracked. Perhaps they should be, but for now
     341                // the full fill solves it.
     342                forceFillCodeLocations( transUnit );
     343
     344                PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) );
     345                PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) );
     346                PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) );
     347
     348                PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) );
     349
     350                PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) );
     351                PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) );
     352                PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) );
     353                PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) );
     354                PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) );
     355                PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) );
     356                PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) );
     357                PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) );
     358                PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) );
     359                PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) );
     360
     361                PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
     362
     363                PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
     364                PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
     365                PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) );
     366                PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
     367                PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
     368                PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) );
    358369
    359370                if ( symtabp ) {
     
    366377                } // if
    367378
    368                 DUMP( validp, std::move( transUnit ) );
    369 
    370                 PASS( "Translate Throws", ControlStruct::translateThrows, transUnit );
    371                 PASS( "Fix Labels", ControlStruct::fixLabels, transUnit );
    372                 PASS( "Fix Names", CodeGen::fixNames, transUnit );
    373                 PASS( "Gen Init", InitTweak::genInit, transUnit );
    374                 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit );
     379                if ( validp ) {
     380                        dump( std::move( transUnit ) );
     381                        return EXIT_SUCCESS;
     382                } // if
     383
     384                PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) );
     385                PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) );
     386                PASS( "Fix Names", CodeGen::fixNames( transUnit ) );
     387                PASS( "Gen Init", InitTweak::genInit( transUnit ) );
     388                PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
    375389
    376390                if ( libcfap ) {
     
    384398                } // if
    385399
    386                 DUMP( bresolvep, std::move( transUnit ) );
     400                if ( bresolvep ) {
     401                        dump( std::move( transUnit ) );
     402                        return EXIT_SUCCESS;
     403                } // if
    387404
    388405                if ( resolvprotop ) {
     
    391408                } // if
    392409
    393                 PASS( "Resolve", ResolvExpr::resolve, transUnit );
    394                 DUMP( exprp, std::move( transUnit ) );
    395 
    396                 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() );
     410                PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
     411                if ( exprp ) {
     412                        dump( std::move( transUnit ) );
     413                        return EXIT_SUCCESS;
     414                } // if
     415
     416                forceFillCodeLocations( transUnit );
     417
     418                PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
    397419
    398420                // fix ObjectDecl - replaces ConstructorInit nodes
    399                 DUMP( ctorinitp, std::move( transUnit ) );
     421                if ( ctorinitp ) {
     422                        dump( std::move( transUnit ) );
     423                        return EXIT_SUCCESS;
     424                } // if
    400425
    401426                // Currently not working due to unresolved issues with UniqueExpr
    402                 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr, transUnit ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    403 
    404                 PASS( "Translate Tries", ControlStruct::translateTries, transUnit );
    405                 PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit );
     427                PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
     428
     429                PASS( "Translate Tries", ControlStruct::translateTries( transUnit ) );
     430                PASS( "Gen Waitfor", Concurrency::generateWaitFor( transUnit ) );
    406431
    407432                // Needs to happen before tuple types are expanded.
    408                 PASS( "Convert Specializations",  GenPoly::convertSpecializations, transUnit );
    409 
    410                 PASS( "Expand Tuples", Tuples::expandTuples, transUnit );
    411                 DUMP( tuplep, std::move( transUnit ) );
     433                PASS( "Convert Specializations",  GenPoly::convertSpecializations( transUnit ) );
     434
     435                PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) );
     436
     437                if ( tuplep ) {
     438                        dump( std::move( transUnit ) );
     439                        return EXIT_SUCCESS;
     440                } // if
    412441
    413442                // Must come after Translate Tries.
    414                 PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit );
    415 
    416                 PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit );
    417                 DUMP( genericsp, std::move( transUnit ) );
    418 
    419                 PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit );
     443                PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) );
     444
     445                PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) );
     446                if ( genericsp ) {
     447                        dump( std::move( transUnit ) );
     448                        return EXIT_SUCCESS;
     449                } // if
     450
     451                PASS( "Convert L-Value", GenPoly::convertLvalue( transUnit ) );
    420452
    421453                translationUnit = convert( std::move( transUnit ) );
    422454
    423                 DUMP( bboxp, translationUnit );
    424                 PASS( "Box", GenPoly::box, translationUnit );
    425 
    426                 PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit );
     455                if ( bboxp ) {
     456                        dump( translationUnit );
     457                        return EXIT_SUCCESS;
     458                } // if
     459                PASS( "Box", GenPoly::box( translationUnit ) );
     460
     461                PASS( "Link-Once", CodeGen::translateLinkOnce( translationUnit ) );
    427462
    428463                // Code has been lowered to C, now we can start generation.
    429464
    430                 DUMP( bcodegenp, translationUnit );
     465                if ( bcodegenp ) {
     466                        dump( translationUnit );
     467                        return EXIT_SUCCESS;
     468                } // if
    431469
    432470                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     
    435473
    436474                CodeTools::fillLocations( translationUnit );
    437                 PASS( "Code Gen", CodeGen::generate, translationUnit, *output, ! genproto, prettycodegenp, true, linemarks );
     475                PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );
    438476
    439477                CodeGen::FixMain::fix( translationUnit, *output,
     
    445483                if ( errorp ) {
    446484                        cerr << "---AST at error:---" << endl;
    447                         // We check which section the errors came from without looking at
    448                         // transUnit because std::move means it could look like anything.
    449                         if ( !translationUnit.empty() ) {
    450                                 dump( translationUnit, cerr );
    451                         } else {
    452                                 dump( std::move( transUnit ), cerr );
    453                         }
     485                        dump( translationUnit, cerr );
    454486                        cerr << endl << "---End of AST, begin error message:---\n" << endl;
    455487                } // if
    456488                e.print();
     489                if ( output != &cout ) {
     490                        delete output;
     491                } // if
     492                return EXIT_FAILURE;
     493        } catch ( UnimplementedError & e ) {
     494                cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
     495                if ( output != &cout ) {
     496                        delete output;
     497                } // if
     498                return EXIT_FAILURE;
     499        } catch ( CompilerError & e ) {
     500                cerr << "Compiler Error: " << e.get_what() << endl;
     501                cerr << "(please report bugs to [REDACTED])" << endl;
    457502                if ( output != &cout ) {
    458503                        delete output;
     
    483528
    484529
    485 static const char optstring[] = ":c:ghilLmNnpdP:S:twW:D:";
     530static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
    486531
    487532enum { PreludeDir = 128 };
     
    490535        { "gdb", no_argument, nullptr, 'g' },
    491536        { "help", no_argument, nullptr, 'h' },
    492         { "invariant", no_argument, nullptr, 'i' },
    493537        { "libcfa", no_argument, nullptr, 'l' },
    494538        { "linemarks", no_argument, nullptr, 'L' },
    495         { "no-main", no_argument, nullptr, 'm' },
     539        { "no-main", no_argument, 0, 'm' },
    496540        { "no-linemarks", no_argument, nullptr, 'N' },
    497541        { "no-prelude", no_argument, nullptr, 'n' },
     
    512556        "wait for gdb to attach",                                                       // -g
    513557        "print translator help message",                                        // -h
    514         "invariant checking during AST passes",                         // -i
    515558        "generate libcfa.c",                                                            // -l
    516559        "generate line marks",                                                          // -L
     
    544587        { "rproto", resolvprotop, true, "resolver-proto instance" },
    545588        { "rsteps", resolvep, true, "print resolver steps" },
     589        { "tree", parsep, true, "print parse tree" },
    546590        // code dumps
    547591        { "ast", astp, true, "print AST after parsing" },
     
    606650                        usage( argv );                                                          // no return
    607651                        break;
    608                   case 'i':                                                                             // invariant checking
    609                         invariant = true;
    610                         break;
    611652                  case 'l':                                                                             // generate libcfa.c
    612653                        libcfap = true;
     
    707748} // parse_cmdline
    708749
     750static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit ) {
     751        extern int yyparse( void );
     752        extern FILE * yyin;
     753        extern int yylineno;
     754
     755        ::linkage = linkage;                                                            // set globals
     756        yyin = input;
     757        yylineno = 1;
     758        int parseStatus = yyparse();
     759
     760        fclose( input );
     761        if ( shouldExit || parseStatus != 0 ) {
     762                exit( parseStatus );
     763        } // if
     764} // parse
     765
    709766static bool notPrelude( Declaration * decl ) {
    710767        return ! LinkageSpec::isBuiltin( decl->get_linkage() );
  • tests/.expect/PRNG.x64.txt

    r24d6572 r34b4268  
    11
    2 CFA xoshiro256pp
    3 
    4                     PRNG()     PRNG(5)   PRNG(0,5)
    5       13944458589275087071           3           2
    6         129977468648444256           0           4
    7        2357727400298891021           2           2
    8        8855179187835660146           3           3
    9        9957620185645882382           4           1
    10       13396406983727409795           0           5
    11        3342782395220265920           0           5
    12        1707651271867677937           1           0
    13       16402561450140881681           0           1
    14       17838519215740313729           4           2
    15        7425936020594490136           4           0
    16        4174865704721714670           3           5
    17       16055269689200152092           0           2
    18       15091270195803594018           1           5
    19       11807315541476180798           1           1
    20       10697186588988060306           4           1
    21       14665526411527044929           3           2
    22       11289342279096164771           2           5
    23       16126980828050300615           1           4
    24        7821578301767524260           4           1
     2       PRNG()   PRNG(5)    PRNG(0,5)
     3          861         3            0
     410137507171299805328         1            2
     512205946788447993741         4            0
     616222929371023265189         2            5
     711921944259646500358         1            1
     89511863719043198063         2            0
     918170109536749574203         0            1
     1015896208456307578543         0            3
     114171113079117645375         1            4
     125535309872453329531         1            1
     1313293369315461644140         2            2
     14855811942427900360         1            1
     159125507373316195824         1            5
     166942856496042419510         1            5
     1716774706561877323900         2            4
     1817765436951300330249         4            0
     193766082030894719812         1            2
     2015818141700523398820         3            5
     211244962761353699441         0            5
     224506898200126256218         1            2
    2523seed 1009
    2624
    2725Sequential
    28 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
     26trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
    2927
    3028Concurrent
    31 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
    32 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
    33 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
    34 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
     29trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     30trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     31trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     32trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
    3533
    36                     prng()     prng(5)   prng(0,5)
    37       13944458589275087071           3           2
    38         129977468648444256           0           4
    39        2357727400298891021           2           2
    40        8855179187835660146           3           3
    41        9957620185645882382           4           1
    42       13396406983727409795           0           5
    43        3342782395220265920           0           5
    44        1707651271867677937           1           0
    45       16402561450140881681           0           1
    46       17838519215740313729           4           2
    47        7425936020594490136           4           0
    48        4174865704721714670           3           5
    49       16055269689200152092           0           2
    50       15091270195803594018           1           5
    51       11807315541476180798           1           1
    52       10697186588988060306           4           1
    53       14665526411527044929           3           2
    54       11289342279096164771           2           5
    55       16126980828050300615           1           4
    56        7821578301767524260           4           1
     34       prng()   prng(5)    prng(0,5)
     35          861         3            0
     3610137507171299805328         1            2
     3712205946788447993741         4            0
     3816222929371023265189         2            5
     3911921944259646500358         1            1
     409511863719043198063         2            0
     4118170109536749574203         0            1
     4215896208456307578543         0            3
     434171113079117645375         1            4
     445535309872453329531         1            1
     4513293369315461644140         2            2
     46855811942427900360         1            1
     479125507373316195824         1            5
     486942856496042419510         1            5
     4916774706561877323900         2            4
     5017765436951300330249         4            0
     513766082030894719812         1            2
     5215818141700523398820         3            5
     531244962761353699441         0            5
     544506898200126256218         1            2
    5755seed 1009
    5856
    5957Sequential
    60 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0%
     58trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
    6159
    6260Concurrent
    63 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0%
    64 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0%
    65 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0%
    66 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0%
     61trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     62trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     63trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     64trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
    6765
    68                    prng(t)   prng(t,5) prng(t,0,5)
    69       13944458589275087071           3           2
    70         129977468648444256           0           4
    71        2357727400298891021           2           2
    72        8855179187835660146           3           3
    73        9957620185645882382           4           1
    74       13396406983727409795           0           5
    75        3342782395220265920           0           5
    76        1707651271867677937           1           0
    77       16402561450140881681           0           1
    78       17838519215740313729           4           2
    79        7425936020594490136           4           0
    80        4174865704721714670           3           5
    81       16055269689200152092           0           2
    82       15091270195803594018           1           5
    83       11807315541476180798           1           1
    84       10697186588988060306           4           1
    85       14665526411527044929           3           2
    86       11289342279096164771           2           5
    87       16126980828050300615           1           4
    88        7821578301767524260           4           1
     66      prng(t) prng(t,5) prng(t,0,5)
     67          861         3            0
     6810137507171299805328         1            2
     6912205946788447993741         4            0
     7016222929371023265189         2            5
     7111921944259646500358         1            1
     729511863719043198063         2            0
     7318170109536749574203         0            1
     7415896208456307578543         0            3
     754171113079117645375         1            4
     765535309872453329531         1            1
     7713293369315461644140         2            2
     78855811942427900360         1            1
     799125507373316195824         1            5
     806942856496042419510         1            5
     8116774706561877323900         2            4
     8217765436951300330249         4            0
     833766082030894719812         1            2
     8415818141700523398820         3            5
     851244962761353699441         0            5
     864506898200126256218         1            2
    8987seed 1009
    9088
    9189Sequential
    92 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
     90trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
    9391
    9492Concurrent
    95 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
    96 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
    97 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
    98 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%
     93trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     94trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     95trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
     96trials 100000000 buckets 100000 min 875 max 1138 avg 1000.0 std 31.8 rstd 3.2%
  • tests/.expect/PRNG.x86.txt

    r24d6572 r34b4268  
    11
    2 CFA xoshiro128pp
    3 
    4                     PRNG()     PRNG(5)   PRNG(0,5)
    5                 2884683541           0           0
    6                 3465286746           2           4
    7                 3268922916           0           1
    8                 2396374907           3           0
    9                 2135076892           4           1
    10                  944377718           3           1
    11                 2204845346           3           3
    12                 3736609533           0           4
    13                 4063231336           0           2
    14                 1075394776           0           2
    15                  712844808           4           0
    16                 4246343110           3           1
    17                 3793873837           2           1
    18                 3690340337           1           4
    19                  319207944           1           4
    20                 1815791072           3           5
    21                 2581617261           1           5
    22                 3873329448           1           3
    23                  832631329           4           0
    24                  651551615           3           5
     2       PRNG()   PRNG(5)    PRNG(0,5)
     3      8333105         1            2
     4   1989339636         4            5
     5    266970699         3            2
     6   1928130121         3            4
     7   1351003938         4            5
     8   1624164922         4            3
     9    363429604         1            2
     10   3355083174         1            1
     11    214422584         1            1
     12   2266729947         1            2
     13   3649702519         2            4
     14   2250875012         2            4
     15   4184653025         1            3
     16   2640851227         2            5
     17    206468178         2            3
     18   2600873108         1            3
     19   3007574582         3            3
     20    394476790         0            2
     21   1312145388         1            5
     22   2989081290         2            4
    2523seed 1009
    2624
    2725Sequential
    28 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
     26trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
    2927
    3028Concurrent
    31 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
    32 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
    33 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
    34 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
     29trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     30trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     31trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     32trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
    3533
    36                     prng()     prng(5)   prng(0,5)
    37                 2884683541           0           0
    38                 3465286746           2           4
    39                 3268922916           0           1
    40                 2396374907           3           0
    41                 2135076892           4           1
    42                  944377718           3           1
    43                 2204845346           3           3
    44                 3736609533           0           4
    45                 4063231336           0           2
    46                 1075394776           0           2
    47                  712844808           4           0
    48                 4246343110           3           1
    49                 3793873837           2           1
    50                 3690340337           1           4
    51                  319207944           1           4
    52                 1815791072           3           5
    53                 2581617261           1           5
    54                 3873329448           1           3
    55                  832631329           4           0
    56                  651551615           3           5
     34       prng()   prng(5)    prng(0,5)
     35      8333105         1            2
     36   1989339636         4            5
     37    266970699         3            2
     38   1928130121         3            4
     39   1351003938         4            5
     40   1624164922         4            3
     41    363429604         1            2
     42   3355083174         1            1
     43    214422584         1            1
     44   2266729947         1            2
     45   3649702519         2            4
     46   2250875012         2            4
     47   4184653025         1            3
     48   2640851227         2            5
     49    206468178         2            3
     50   2600873108         1            3
     51   3007574582         3            3
     52    394476790         0            2
     53   1312145388         1            5
     54   2989081290         2            4
    5755seed 1009
    5856
    5957Sequential
    60 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1%
     58trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
    6159
    6260Concurrent
    63 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1%
    64 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1%
    65 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1%
    66 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1%
     61trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     62trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     63trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     64trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
    6765
    68                    prng(t)   prng(t,5) prng(t,0,5)
    69                 2884683541           0           0
    70                 3465286746           2           4
    71                 3268922916           0           1
    72                 2396374907           3           0
    73                 2135076892           4           1
    74                  944377718           3           1
    75                 2204845346           3           3
    76                 3736609533           0           4
    77                 4063231336           0           2
    78                 1075394776           0           2
    79                  712844808           4           0
    80                 4246343110           3           1
    81                 3793873837           2           1
    82                 3690340337           1           4
    83                  319207944           1           4
    84                 1815791072           3           5
    85                 2581617261           1           5
    86                 3873329448           1           3
    87                  832631329           4           0
    88                  651551615           3           5
     66      prng(t) prng(t,5) prng(t,0,5)
     67      8333105         1            2
     68   1989339636         4            5
     69    266970699         3            2
     70   1928130121         3            4
     71   1351003938         4            5
     72   1624164922         4            3
     73    363429604         1            2
     74   3355083174         1            1
     75    214422584         1            1
     76   2266729947         1            2
     77   3649702519         2            4
     78   2250875012         2            4
     79   4184653025         1            3
     80   2640851227         2            5
     81    206468178         2            3
     82   2600873108         1            3
     83   3007574582         3            3
     84    394476790         0            2
     85   1312145388         1            5
     86   2989081290         2            4
    8987seed 1009
    9088
    9189Sequential
    92 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
     90trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
    9391
    9492Concurrent
    95 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
    96 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
    97 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
    98 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%
     93trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     94trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     95trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
     96trials 100000000 buckets 100000 min 873 max 1140 avg 1000.0 std 31.3 rstd 3.1%
  • tests/.expect/array.txt

    r24d6572 r34b4268  
    1 array.cfa:119:25: warning: Preprocessor started
     1array.cfa:52:25: warning: Compiled
  • tests/.expect/attributes.arm64.txt

    r24d6572 r34b4268  
    2626    return _X4_retS12__anonymous0_1;
    2727}
    28 __attribute__ ((unused)) static struct __anonymous0 _X5DummyS12__anonymous0_1;
     28__attribute__ ((unused)) struct __anonymous0 _X5DummyS12__anonymous0_1;
    2929struct __attribute__ ((unused)) Agn1;
    3030struct __attribute__ ((unused)) Agn2 {
     
    13511351signed int _X4apd5Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object12)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object13)(signed int __param_0));
    13521352signed int _X4apd6Fi_Fi__Fi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object14)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object15)());
    1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(__attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused)) signed int __param_0));
     1353signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(signed int __param_0));
    13541354struct Vad {
    13551355    __attribute__ ((unused)) signed int :4;
  • tests/.expect/attributes.x64.txt

    r24d6572 r34b4268  
    2626    return _X4_retS12__anonymous0_1;
    2727}
    28 __attribute__ ((unused)) static struct __anonymous0 _X5DummyS12__anonymous0_1;
     28__attribute__ ((unused)) struct __anonymous0 _X5DummyS12__anonymous0_1;
    2929struct __attribute__ ((unused)) Agn1;
    3030struct __attribute__ ((unused)) Agn2 {
     
    13511351signed int _X4apd5Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object12)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object13)(signed int __param_0));
    13521352signed int _X4apd6Fi_Fi__Fi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object14)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object15)());
    1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(__attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused)) signed int __param_0));
     1353signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(signed int __param_0));
    13541354struct Vad {
    13551355    __attribute__ ((unused)) signed int :4;
  • tests/.expect/attributes.x86.txt

    r24d6572 r34b4268  
    2626    return _X4_retS12__anonymous0_1;
    2727}
    28 __attribute__ ((unused)) static struct __anonymous0 _X5DummyS12__anonymous0_1;
     28__attribute__ ((unused)) struct __anonymous0 _X5DummyS12__anonymous0_1;
    2929struct __attribute__ ((unused)) Agn1;
    3030struct __attribute__ ((unused)) Agn2 {
     
    13511351signed int _X4apd5Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object12)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object13)(signed int __param_0));
    13521352signed int _X4apd6Fi_Fi__Fi____1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object14)(), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object15)());
    1353 signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(__attribute__ ((unused)) signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(__attribute__ ((unused)) signed int __param_0));
     1353signed int _X4apd7Fi_Fi_i_Fi_i___1(__attribute__ ((unused,unused,unused)) signed int (*__anonymous_object16)(signed int __param_0), __attribute__ ((unused,unused,unused)) signed int (*__anonymous_object17)(signed int __param_0));
    13541354struct Vad {
    13551355    __attribute__ ((unused)) signed int :4;
  • tests/.expect/declarationSpecifier.arm64.txt

    r24d6572 r34b4268  
    5151
    5252}
    53 static volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;
     53volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;
    5454struct __anonymous1 {
    5555    signed int _X1ii_1;
     
    9696
    9797}
    98 static volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;
     98volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;
    9999struct __anonymous2 {
    100100    signed int _X1ii_1;
     
    141141
    142142}
    143 static volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;
     143volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;
    144144struct __anonymous3 {
    145145    signed int _X1ii_1;
     
    322322}
    323323static volatile const struct __anonymous6 _X3x16KVS12__anonymous6_1;
     324struct __anonymous7 {
     325    signed int _X1ii_1;
     326};
     327static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
     328static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
     329static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
     330static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
     331static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1);
     332static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
     333    {
     334        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ?{} */);
     335    }
     336
     337}
     338static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
     339    {
     340        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1) /* ?{} */);
     341    }
     342
     343}
     344static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
     345    {
     346        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ^?{} */);
     347    }
     348
     349}
     350static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
     351    struct __anonymous7 _X4_retS12__anonymous7_1;
     352    {
     353        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1));
     354    }
     355
     356    {
     357        ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));
     358    }
     359
     360    return _X4_retS12__anonymous7_1;
     361}
     362static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1){
     363    {
     364        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X1ii_1) /* ?{} */);
     365    }
     366
     367}
     368static volatile const struct __anonymous7 _X3x17KVS12__anonymous7_1;
    324369volatile const signed short int _X3x20KVs_1;
    325370static volatile const signed short int _X3x21KVs_1;
     
    330375static volatile const signed short int _X3x26KVs_1;
    331376static volatile const signed short int _X3x27KVs_1;
    332 struct __anonymous7 {
    333     signed short int _X1is_1;
    334 };
    335 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
    336 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
    337 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
    338 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
    339 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1);
    340 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
    341     {
    342         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ?{} */);
    343     }
    344 
    345 }
    346 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
    347     {
    348         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1) /* ?{} */);
    349     }
    350 
    351 }
    352 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
    353     {
    354         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ^?{} */);
    355     }
    356 
    357 }
    358 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
    359     struct __anonymous7 _X4_retS12__anonymous7_1;
    360     {
    361         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1));
    362     }
    363 
    364     {
    365         ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));
    366     }
    367 
    368     return _X4_retS12__anonymous7_1;
    369 }
    370 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1){
    371     {
    372         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X1is_1) /* ?{} */);
    373     }
    374 
    375 }
    376 static volatile const struct __anonymous7 _X3x29KVS12__anonymous7_1;
    377377struct __anonymous8 {
    378378    signed short int _X1is_1;
     
    419419
    420420}
    421 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1;
     421volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1;
    422422struct __anonymous9 {
    423423    signed short int _X1is_1;
     
    464464
    465465}
    466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1;
     466volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1;
    467467struct __anonymous10 {
    468468    signed short int _X1is_1;
     
    509509
    510510}
    511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1;
     511volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1;
    512512struct __anonymous11 {
    513513    signed short int _X1is_1;
     
    554554
    555555}
    556 static volatile const struct __anonymous11 _X3x33KVS13__anonymous11_1;
     556static volatile const struct __anonymous11 _X3x32KVS13__anonymous11_1;
    557557struct __anonymous12 {
    558558    signed short int _X1is_1;
     
    599599
    600600}
    601 static volatile const struct __anonymous12 _X3x34KVS13__anonymous12_1;
     601static volatile const struct __anonymous12 _X3x33KVS13__anonymous12_1;
    602602struct __anonymous13 {
    603603    signed short int _X1is_1;
     
    644644
    645645}
    646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1;
     646static volatile const struct __anonymous13 _X3x34KVS13__anonymous13_1;
     647struct __anonymous14 {
     648    signed short int _X1is_1;
     649};
     650static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
     651static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
     652static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
     653static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
     654static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1);
     655static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
     656    {
     657        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ?{} */);
     658    }
     659
     660}
     661static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
     662    {
     663        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1) /* ?{} */);
     664    }
     665
     666}
     667static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
     668    {
     669        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ^?{} */);
     670    }
     671
     672}
     673static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
     674    struct __anonymous14 _X4_retS13__anonymous14_1;
     675    {
     676        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1));
     677    }
     678
     679    {
     680        ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1)));
     681    }
     682
     683    return _X4_retS13__anonymous14_1;
     684}
     685static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1){
     686    {
     687        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X1is_1) /* ?{} */);
     688    }
     689
     690}
     691static volatile const struct __anonymous14 _X3x35KVS13__anonymous14_1;
     692struct __anonymous15 {
     693    signed short int _X1is_1;
     694};
     695static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
     696static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
     697static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
     698static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
     699static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1);
     700static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
     701    {
     702        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ?{} */);
     703    }
     704
     705}
     706static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
     707    {
     708        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1) /* ?{} */);
     709    }
     710
     711}
     712static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
     713    {
     714        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ^?{} */);
     715    }
     716
     717}
     718static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
     719    struct __anonymous15 _X4_retS13__anonymous15_1;
     720    {
     721        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1));
     722    }
     723
     724    {
     725        ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1)));
     726    }
     727
     728    return _X4_retS13__anonymous15_1;
     729}
     730static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1){
     731    {
     732        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X1is_1) /* ?{} */);
     733    }
     734
     735}
     736static volatile const struct __anonymous15 _X3x36KVS13__anonymous15_1;
    647737_Thread_local signed int _X3x37i_1;
    648738__thread signed int _X3x38i_1;
     
    663753static inline volatile const signed short int _X3f27Fs___1();
    664754static inline volatile const signed short int _X3f28Fs___1();
    665 struct __anonymous14 {
    666     signed int _X1ii_1;
    667 };
    668 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
    669 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
    670 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
    671 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
    672 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1);
    673 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
    674     {
    675         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ?{} */);
    676     }
    677 
    678 }
    679 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
    680     {
    681         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1) /* ?{} */);
    682     }
    683 
    684 }
    685 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
    686     {
    687         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ^?{} */);
    688     }
    689 
    690 }
    691 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
    692     struct __anonymous14 _X4_retS13__anonymous14_1;
    693     {
    694         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1));
    695     }
    696 
    697     {
    698         ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1)));
    699     }
    700 
    701     return _X4_retS13__anonymous14_1;
    702 }
    703 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1){
    704     {
    705         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X1ii_1) /* ?{} */);
    706     }
    707 
    708 }
    709 static inline volatile const struct __anonymous14 _X3f31FS13__anonymous14___1();
    710 struct __anonymous15 {
    711     signed int _X1ii_1;
    712 };
    713 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
    714 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
    715 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
    716 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
    717 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1);
    718 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
    719     {
    720         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ?{} */);
    721     }
    722 
    723 }
    724 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
    725     {
    726         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1) /* ?{} */);
    727     }
    728 
    729 }
    730 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
    731     {
    732         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ^?{} */);
    733     }
    734 
    735 }
    736 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
    737     struct __anonymous15 _X4_retS13__anonymous15_1;
    738     {
    739         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1));
    740     }
    741 
    742     {
    743         ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1)));
    744     }
    745 
    746     return _X4_retS13__anonymous15_1;
    747 }
    748 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1){
    749     {
    750         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X1ii_1) /* ?{} */);
    751     }
    752 
    753 }
    754 static inline volatile const struct __anonymous15 _X3f32FS13__anonymous15___1();
    755755struct __anonymous16 {
    756756    signed int _X1ii_1;
     
    797797
    798798}
    799 static inline volatile const struct __anonymous16 _X3f33FS13__anonymous16___1();
     799static inline volatile const struct __anonymous16 _X3f31FS13__anonymous16___1();
    800800struct __anonymous17 {
    801801    signed int _X1ii_1;
     
    842842
    843843}
    844 static inline volatile const struct __anonymous17 _X3f34FS13__anonymous17___1();
     844static inline volatile const struct __anonymous17 _X3f32FS13__anonymous17___1();
    845845struct __anonymous18 {
    846846    signed int _X1ii_1;
     
    887887
    888888}
    889 static inline volatile const struct __anonymous18 _X3f35FS13__anonymous18___1();
     889static inline volatile const struct __anonymous18 _X3f33FS13__anonymous18___1();
    890890struct __anonymous19 {
    891891    signed int _X1ii_1;
     
    932932
    933933}
    934 static inline volatile const struct __anonymous19 _X3f36FS13__anonymous19___1();
     934static inline volatile const struct __anonymous19 _X3f34FS13__anonymous19___1();
    935935struct __anonymous20 {
    936936    signed int _X1ii_1;
     
    977977
    978978}
    979 static inline volatile const struct __anonymous20 _X3f37FS13__anonymous20___1();
     979static inline volatile const struct __anonymous20 _X3f35FS13__anonymous20___1();
    980980struct __anonymous21 {
    981981    signed int _X1ii_1;
     
    10221022
    10231023}
    1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1();
     1024static inline volatile const struct __anonymous21 _X3f36FS13__anonymous21___1();
     1025struct __anonymous22 {
     1026    signed int _X1ii_1;
     1027};
     1028static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1);
     1029static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1);
     1030static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1);
     1031static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1);
     1032static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1);
     1033static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){
     1034    {
     1035        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ?{} */);
     1036    }
     1037
     1038}
     1039static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){
     1040    {
     1041        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1) /* ?{} */);
     1042    }
     1043
     1044}
     1045static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){
     1046    {
     1047        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ^?{} */);
     1048    }
     1049
     1050}
     1051static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){
     1052    struct __anonymous22 _X4_retS13__anonymous22_1;
     1053    {
     1054        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1));
     1055    }
     1056
     1057    {
     1058        ((void)_X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1((&_X4_retS13__anonymous22_1), (*_X4_dstS13__anonymous22_1)));
     1059    }
     1060
     1061    return _X4_retS13__anonymous22_1;
     1062}
     1063static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1){
     1064    {
     1065        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X1ii_1) /* ?{} */);
     1066    }
     1067
     1068}
     1069static inline volatile const struct __anonymous22 _X3f37FS13__anonymous22___1();
     1070struct __anonymous23 {
     1071    signed int _X1ii_1;
     1072};
     1073static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1);
     1074static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1);
     1075static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1);
     1076static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1);
     1077static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1);
     1078static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){
     1079    {
     1080        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ?{} */);
     1081    }
     1082
     1083}
     1084static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){
     1085    {
     1086        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1) /* ?{} */);
     1087    }
     1088
     1089}
     1090static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){
     1091    {
     1092        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ^?{} */);
     1093    }
     1094
     1095}
     1096static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){
     1097    struct __anonymous23 _X4_retS13__anonymous23_1;
     1098    {
     1099        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1));
     1100    }
     1101
     1102    {
     1103        ((void)_X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1((&_X4_retS13__anonymous23_1), (*_X4_dstS13__anonymous23_1)));
     1104    }
     1105
     1106    return _X4_retS13__anonymous23_1;
     1107}
     1108static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1){
     1109    {
     1110        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X1ii_1) /* ?{} */);
     1111    }
     1112
     1113}
     1114static inline volatile const struct __anonymous23 _X3f38FS13__anonymous23___1();
    10251115static inline volatile const signed short int _X3f41Fs___1();
    10261116static inline volatile const signed short int _X3f42Fs___1();
  • tests/.expect/declarationSpecifier.x64.txt

    r24d6572 r34b4268  
    5151
    5252}
    53 static volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;
     53volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;
    5454struct __anonymous1 {
    5555    signed int _X1ii_1;
     
    9696
    9797}
    98 static volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;
     98volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;
    9999struct __anonymous2 {
    100100    signed int _X1ii_1;
     
    141141
    142142}
    143 static volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;
     143volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;
    144144struct __anonymous3 {
    145145    signed int _X1ii_1;
     
    322322}
    323323static volatile const struct __anonymous6 _X3x16KVS12__anonymous6_1;
     324struct __anonymous7 {
     325    signed int _X1ii_1;
     326};
     327static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
     328static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
     329static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
     330static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
     331static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1);
     332static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
     333    {
     334        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ?{} */);
     335    }
     336
     337}
     338static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
     339    {
     340        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1) /* ?{} */);
     341    }
     342
     343}
     344static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
     345    {
     346        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ^?{} */);
     347    }
     348
     349}
     350static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
     351    struct __anonymous7 _X4_retS12__anonymous7_1;
     352    {
     353        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1));
     354    }
     355
     356    {
     357        ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));
     358    }
     359
     360    return _X4_retS12__anonymous7_1;
     361}
     362static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1){
     363    {
     364        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X1ii_1) /* ?{} */);
     365    }
     366
     367}
     368static volatile const struct __anonymous7 _X3x17KVS12__anonymous7_1;
    324369volatile const signed short int _X3x20KVs_1;
    325370static volatile const signed short int _X3x21KVs_1;
     
    330375static volatile const signed short int _X3x26KVs_1;
    331376static volatile const signed short int _X3x27KVs_1;
    332 struct __anonymous7 {
    333     signed short int _X1is_1;
    334 };
    335 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
    336 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
    337 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
    338 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
    339 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1);
    340 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
    341     {
    342         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ?{} */);
    343     }
    344 
    345 }
    346 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
    347     {
    348         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1) /* ?{} */);
    349     }
    350 
    351 }
    352 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
    353     {
    354         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ^?{} */);
    355     }
    356 
    357 }
    358 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
    359     struct __anonymous7 _X4_retS12__anonymous7_1;
    360     {
    361         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1));
    362     }
    363 
    364     {
    365         ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));
    366     }
    367 
    368     return _X4_retS12__anonymous7_1;
    369 }
    370 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1){
    371     {
    372         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X1is_1) /* ?{} */);
    373     }
    374 
    375 }
    376 static volatile const struct __anonymous7 _X3x29KVS12__anonymous7_1;
    377377struct __anonymous8 {
    378378    signed short int _X1is_1;
     
    419419
    420420}
    421 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1;
     421volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1;
    422422struct __anonymous9 {
    423423    signed short int _X1is_1;
     
    464464
    465465}
    466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1;
     466volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1;
    467467struct __anonymous10 {
    468468    signed short int _X1is_1;
     
    509509
    510510}
    511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1;
     511volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1;
    512512struct __anonymous11 {
    513513    signed short int _X1is_1;
     
    554554
    555555}
    556 static volatile const struct __anonymous11 _X3x33KVS13__anonymous11_1;
     556static volatile const struct __anonymous11 _X3x32KVS13__anonymous11_1;
    557557struct __anonymous12 {
    558558    signed short int _X1is_1;
     
    599599
    600600}
    601 static volatile const struct __anonymous12 _X3x34KVS13__anonymous12_1;
     601static volatile const struct __anonymous12 _X3x33KVS13__anonymous12_1;
    602602struct __anonymous13 {
    603603    signed short int _X1is_1;
     
    644644
    645645}
    646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1;
     646static volatile const struct __anonymous13 _X3x34KVS13__anonymous13_1;
     647struct __anonymous14 {
     648    signed short int _X1is_1;
     649};
     650static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
     651static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
     652static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
     653static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
     654static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1);
     655static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
     656    {
     657        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ?{} */);
     658    }
     659
     660}
     661static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
     662    {
     663        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1) /* ?{} */);
     664    }
     665
     666}
     667static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
     668    {
     669        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ^?{} */);
     670    }
     671
     672}
     673static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
     674    struct __anonymous14 _X4_retS13__anonymous14_1;
     675    {
     676        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1));
     677    }
     678
     679    {
     680        ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1)));
     681    }
     682
     683    return _X4_retS13__anonymous14_1;
     684}
     685static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1){
     686    {
     687        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X1is_1) /* ?{} */);
     688    }
     689
     690}
     691static volatile const struct __anonymous14 _X3x35KVS13__anonymous14_1;
     692struct __anonymous15 {
     693    signed short int _X1is_1;
     694};
     695static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
     696static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
     697static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
     698static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
     699static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1);
     700static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
     701    {
     702        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ?{} */);
     703    }
     704
     705}
     706static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
     707    {
     708        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1) /* ?{} */);
     709    }
     710
     711}
     712static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
     713    {
     714        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ^?{} */);
     715    }
     716
     717}
     718static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
     719    struct __anonymous15 _X4_retS13__anonymous15_1;
     720    {
     721        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1));
     722    }
     723
     724    {
     725        ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1)));
     726    }
     727
     728    return _X4_retS13__anonymous15_1;
     729}
     730static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1){
     731    {
     732        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X1is_1) /* ?{} */);
     733    }
     734
     735}
     736static volatile const struct __anonymous15 _X3x36KVS13__anonymous15_1;
    647737_Thread_local signed int _X3x37i_1;
    648738__thread signed int _X3x38i_1;
     
    663753static inline volatile const signed short int _X3f27Fs___1();
    664754static inline volatile const signed short int _X3f28Fs___1();
    665 struct __anonymous14 {
    666     signed int _X1ii_1;
    667 };
    668 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
    669 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
    670 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
    671 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
    672 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1);
    673 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
    674     {
    675         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ?{} */);
    676     }
    677 
    678 }
    679 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
    680     {
    681         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1) /* ?{} */);
    682     }
    683 
    684 }
    685 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
    686     {
    687         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ^?{} */);
    688     }
    689 
    690 }
    691 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
    692     struct __anonymous14 _X4_retS13__anonymous14_1;
    693     {
    694         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1));
    695     }
    696 
    697     {
    698         ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1)));
    699     }
    700 
    701     return _X4_retS13__anonymous14_1;
    702 }
    703 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1){
    704     {
    705         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X1ii_1) /* ?{} */);
    706     }
    707 
    708 }
    709 static inline volatile const struct __anonymous14 _X3f31FS13__anonymous14___1();
    710 struct __anonymous15 {
    711     signed int _X1ii_1;
    712 };
    713 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
    714 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
    715 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
    716 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
    717 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1);
    718 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
    719     {
    720         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ?{} */);
    721     }
    722 
    723 }
    724 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
    725     {
    726         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1) /* ?{} */);
    727     }
    728 
    729 }
    730 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
    731     {
    732         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ^?{} */);
    733     }
    734 
    735 }
    736 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
    737     struct __anonymous15 _X4_retS13__anonymous15_1;
    738     {
    739         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1));
    740     }
    741 
    742     {
    743         ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1)));
    744     }
    745 
    746     return _X4_retS13__anonymous15_1;
    747 }
    748 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1){
    749     {
    750         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X1ii_1) /* ?{} */);
    751     }
    752 
    753 }
    754 static inline volatile const struct __anonymous15 _X3f32FS13__anonymous15___1();
    755755struct __anonymous16 {
    756756    signed int _X1ii_1;
     
    797797
    798798}
    799 static inline volatile const struct __anonymous16 _X3f33FS13__anonymous16___1();
     799static inline volatile const struct __anonymous16 _X3f31FS13__anonymous16___1();
    800800struct __anonymous17 {
    801801    signed int _X1ii_1;
     
    842842
    843843}
    844 static inline volatile const struct __anonymous17 _X3f34FS13__anonymous17___1();
     844static inline volatile const struct __anonymous17 _X3f32FS13__anonymous17___1();
    845845struct __anonymous18 {
    846846    signed int _X1ii_1;
     
    887887
    888888}
    889 static inline volatile const struct __anonymous18 _X3f35FS13__anonymous18___1();
     889static inline volatile const struct __anonymous18 _X3f33FS13__anonymous18___1();
    890890struct __anonymous19 {
    891891    signed int _X1ii_1;
     
    932932
    933933}
    934 static inline volatile const struct __anonymous19 _X3f36FS13__anonymous19___1();
     934static inline volatile const struct __anonymous19 _X3f34FS13__anonymous19___1();
    935935struct __anonymous20 {
    936936    signed int _X1ii_1;
     
    977977
    978978}
    979 static inline volatile const struct __anonymous20 _X3f37FS13__anonymous20___1();
     979static inline volatile const struct __anonymous20 _X3f35FS13__anonymous20___1();
    980980struct __anonymous21 {
    981981    signed int _X1ii_1;
     
    10221022
    10231023}
    1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1();
     1024static inline volatile const struct __anonymous21 _X3f36FS13__anonymous21___1();
     1025struct __anonymous22 {
     1026    signed int _X1ii_1;
     1027};
     1028static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1);
     1029static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1);
     1030static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1);
     1031static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1);
     1032static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1);
     1033static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){
     1034    {
     1035        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ?{} */);
     1036    }
     1037
     1038}
     1039static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){
     1040    {
     1041        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1) /* ?{} */);
     1042    }
     1043
     1044}
     1045static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){
     1046    {
     1047        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ^?{} */);
     1048    }
     1049
     1050}
     1051static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){
     1052    struct __anonymous22 _X4_retS13__anonymous22_1;
     1053    {
     1054        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1));
     1055    }
     1056
     1057    {
     1058        ((void)_X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1((&_X4_retS13__anonymous22_1), (*_X4_dstS13__anonymous22_1)));
     1059    }
     1060
     1061    return _X4_retS13__anonymous22_1;
     1062}
     1063static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1){
     1064    {
     1065        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X1ii_1) /* ?{} */);
     1066    }
     1067
     1068}
     1069static inline volatile const struct __anonymous22 _X3f37FS13__anonymous22___1();
     1070struct __anonymous23 {
     1071    signed int _X1ii_1;
     1072};
     1073static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1);
     1074static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1);
     1075static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1);
     1076static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1);
     1077static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1);
     1078static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){
     1079    {
     1080        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ?{} */);
     1081    }
     1082
     1083}
     1084static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){
     1085    {
     1086        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1) /* ?{} */);
     1087    }
     1088
     1089}
     1090static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){
     1091    {
     1092        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ^?{} */);
     1093    }
     1094
     1095}
     1096static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){
     1097    struct __anonymous23 _X4_retS13__anonymous23_1;
     1098    {
     1099        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1));
     1100    }
     1101
     1102    {
     1103        ((void)_X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1((&_X4_retS13__anonymous23_1), (*_X4_dstS13__anonymous23_1)));
     1104    }
     1105
     1106    return _X4_retS13__anonymous23_1;
     1107}
     1108static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1){
     1109    {
     1110        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X1ii_1) /* ?{} */);
     1111    }
     1112
     1113}
     1114static inline volatile const struct __anonymous23 _X3f38FS13__anonymous23___1();
    10251115static inline volatile const signed short int _X3f41Fs___1();
    10261116static inline volatile const signed short int _X3f42Fs___1();
  • tests/.expect/declarationSpecifier.x86.txt

    r24d6572 r34b4268  
    5151
    5252}
    53 static volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;
     53volatile const struct __anonymous0 _X3x10KVS12__anonymous0_1;
    5454struct __anonymous1 {
    5555    signed int _X1ii_1;
     
    9696
    9797}
    98 static volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;
     98volatile const struct __anonymous1 _X3x11KVS12__anonymous1_1;
    9999struct __anonymous2 {
    100100    signed int _X1ii_1;
     
    141141
    142142}
    143 static volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;
     143volatile const struct __anonymous2 _X3x12KVS12__anonymous2_1;
    144144struct __anonymous3 {
    145145    signed int _X1ii_1;
     
    322322}
    323323static volatile const struct __anonymous6 _X3x16KVS12__anonymous6_1;
     324struct __anonymous7 {
     325    signed int _X1ii_1;
     326};
     327static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
     328static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
     329static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
     330static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
     331static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1);
     332static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
     333    {
     334        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ?{} */);
     335    }
     336
     337}
     338static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
     339    {
     340        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1) /* ?{} */);
     341    }
     342
     343}
     344static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
     345    {
     346        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1) /* ^?{} */);
     347    }
     348
     349}
     350static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
     351    struct __anonymous7 _X4_retS12__anonymous7_1;
     352    {
     353        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X4_srcS12__anonymous7_1._X1ii_1));
     354    }
     355
     356    {
     357        ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));
     358    }
     359
     360    return _X4_retS12__anonymous7_1;
     361}
     362static inline void _X12_constructorFv_S12__anonymous7i_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed int _X1ii_1){
     363    {
     364        ((void)((*_X4_dstS12__anonymous7_1)._X1ii_1=_X1ii_1) /* ?{} */);
     365    }
     366
     367}
     368static volatile const struct __anonymous7 _X3x17KVS12__anonymous7_1;
    324369volatile const signed short int _X3x20KVs_1;
    325370static volatile const signed short int _X3x21KVs_1;
     
    330375static volatile const signed short int _X3x26KVs_1;
    331376static volatile const signed short int _X3x27KVs_1;
    332 struct __anonymous7 {
    333     signed short int _X1is_1;
    334 };
    335 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
    336 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
    337 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1);
    338 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1);
    339 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1);
    340 static inline void _X12_constructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
    341     {
    342         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ?{} */);
    343     }
    344 
    345 }
    346 static inline void _X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
    347     {
    348         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1) /* ?{} */);
    349     }
    350 
    351 }
    352 static inline void _X11_destructorFv_S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1){
    353     {
    354         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1) /* ^?{} */);
    355     }
    356 
    357 }
    358 static inline struct __anonymous7 _X16_operator_assignFS12__anonymous7_S12__anonymous7S12__anonymous7_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, struct __anonymous7 _X4_srcS12__anonymous7_1){
    359     struct __anonymous7 _X4_retS12__anonymous7_1;
    360     {
    361         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X4_srcS12__anonymous7_1._X1is_1));
    362     }
    363 
    364     {
    365         ((void)_X12_constructorFv_S12__anonymous7S12__anonymous7_autogen___1((&_X4_retS12__anonymous7_1), (*_X4_dstS12__anonymous7_1)));
    366     }
    367 
    368     return _X4_retS12__anonymous7_1;
    369 }
    370 static inline void _X12_constructorFv_S12__anonymous7s_autogen___1(struct __anonymous7 *_X4_dstS12__anonymous7_1, signed short int _X1is_1){
    371     {
    372         ((void)((*_X4_dstS12__anonymous7_1)._X1is_1=_X1is_1) /* ?{} */);
    373     }
    374 
    375 }
    376 static volatile const struct __anonymous7 _X3x29KVS12__anonymous7_1;
    377377struct __anonymous8 {
    378378    signed short int _X1is_1;
     
    419419
    420420}
    421 static volatile const struct __anonymous8 _X3x30KVS12__anonymous8_1;
     421volatile const struct __anonymous8 _X3x29KVS12__anonymous8_1;
    422422struct __anonymous9 {
    423423    signed short int _X1is_1;
     
    464464
    465465}
    466 static volatile const struct __anonymous9 _X3x31KVS12__anonymous9_1;
     466volatile const struct __anonymous9 _X3x30KVS12__anonymous9_1;
    467467struct __anonymous10 {
    468468    signed short int _X1is_1;
     
    509509
    510510}
    511 static volatile const struct __anonymous10 _X3x32KVS13__anonymous10_1;
     511volatile const struct __anonymous10 _X3x31KVS13__anonymous10_1;
    512512struct __anonymous11 {
    513513    signed short int _X1is_1;
     
    554554
    555555}
    556 static volatile const struct __anonymous11 _X3x33KVS13__anonymous11_1;
     556static volatile const struct __anonymous11 _X3x32KVS13__anonymous11_1;
    557557struct __anonymous12 {
    558558    signed short int _X1is_1;
     
    599599
    600600}
    601 static volatile const struct __anonymous12 _X3x34KVS13__anonymous12_1;
     601static volatile const struct __anonymous12 _X3x33KVS13__anonymous12_1;
    602602struct __anonymous13 {
    603603    signed short int _X1is_1;
     
    644644
    645645}
    646 static volatile const struct __anonymous13 _X3x35KVS13__anonymous13_1;
     646static volatile const struct __anonymous13 _X3x34KVS13__anonymous13_1;
     647struct __anonymous14 {
     648    signed short int _X1is_1;
     649};
     650static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
     651static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
     652static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
     653static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
     654static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1);
     655static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
     656    {
     657        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ?{} */);
     658    }
     659
     660}
     661static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
     662    {
     663        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1) /* ?{} */);
     664    }
     665
     666}
     667static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
     668    {
     669        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1) /* ^?{} */);
     670    }
     671
     672}
     673static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
     674    struct __anonymous14 _X4_retS13__anonymous14_1;
     675    {
     676        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X4_srcS13__anonymous14_1._X1is_1));
     677    }
     678
     679    {
     680        ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1)));
     681    }
     682
     683    return _X4_retS13__anonymous14_1;
     684}
     685static inline void _X12_constructorFv_S13__anonymous14s_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed short int _X1is_1){
     686    {
     687        ((void)((*_X4_dstS13__anonymous14_1)._X1is_1=_X1is_1) /* ?{} */);
     688    }
     689
     690}
     691static volatile const struct __anonymous14 _X3x35KVS13__anonymous14_1;
     692struct __anonymous15 {
     693    signed short int _X1is_1;
     694};
     695static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
     696static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
     697static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
     698static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
     699static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1);
     700static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
     701    {
     702        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ?{} */);
     703    }
     704
     705}
     706static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
     707    {
     708        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1) /* ?{} */);
     709    }
     710
     711}
     712static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
     713    {
     714        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1) /* ^?{} */);
     715    }
     716
     717}
     718static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
     719    struct __anonymous15 _X4_retS13__anonymous15_1;
     720    {
     721        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X4_srcS13__anonymous15_1._X1is_1));
     722    }
     723
     724    {
     725        ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1)));
     726    }
     727
     728    return _X4_retS13__anonymous15_1;
     729}
     730static inline void _X12_constructorFv_S13__anonymous15s_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed short int _X1is_1){
     731    {
     732        ((void)((*_X4_dstS13__anonymous15_1)._X1is_1=_X1is_1) /* ?{} */);
     733    }
     734
     735}
     736static volatile const struct __anonymous15 _X3x36KVS13__anonymous15_1;
    647737_Thread_local signed int _X3x37i_1;
    648738__thread signed int _X3x38i_1;
     
    663753static inline volatile const signed short int _X3f27Fs___1();
    664754static inline volatile const signed short int _X3f28Fs___1();
    665 struct __anonymous14 {
    666     signed int _X1ii_1;
    667 };
    668 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
    669 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
    670 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1);
    671 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1);
    672 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1);
    673 static inline void _X12_constructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
    674     {
    675         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ?{} */);
    676     }
    677 
    678 }
    679 static inline void _X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
    680     {
    681         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1) /* ?{} */);
    682     }
    683 
    684 }
    685 static inline void _X11_destructorFv_S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1){
    686     {
    687         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1) /* ^?{} */);
    688     }
    689 
    690 }
    691 static inline struct __anonymous14 _X16_operator_assignFS13__anonymous14_S13__anonymous14S13__anonymous14_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, struct __anonymous14 _X4_srcS13__anonymous14_1){
    692     struct __anonymous14 _X4_retS13__anonymous14_1;
    693     {
    694         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X4_srcS13__anonymous14_1._X1ii_1));
    695     }
    696 
    697     {
    698         ((void)_X12_constructorFv_S13__anonymous14S13__anonymous14_autogen___1((&_X4_retS13__anonymous14_1), (*_X4_dstS13__anonymous14_1)));
    699     }
    700 
    701     return _X4_retS13__anonymous14_1;
    702 }
    703 static inline void _X12_constructorFv_S13__anonymous14i_autogen___1(struct __anonymous14 *_X4_dstS13__anonymous14_1, signed int _X1ii_1){
    704     {
    705         ((void)((*_X4_dstS13__anonymous14_1)._X1ii_1=_X1ii_1) /* ?{} */);
    706     }
    707 
    708 }
    709 static inline volatile const struct __anonymous14 _X3f31FS13__anonymous14___1();
    710 struct __anonymous15 {
    711     signed int _X1ii_1;
    712 };
    713 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
    714 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
    715 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1);
    716 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1);
    717 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1);
    718 static inline void _X12_constructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
    719     {
    720         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ?{} */);
    721     }
    722 
    723 }
    724 static inline void _X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
    725     {
    726         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1) /* ?{} */);
    727     }
    728 
    729 }
    730 static inline void _X11_destructorFv_S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1){
    731     {
    732         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1) /* ^?{} */);
    733     }
    734 
    735 }
    736 static inline struct __anonymous15 _X16_operator_assignFS13__anonymous15_S13__anonymous15S13__anonymous15_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, struct __anonymous15 _X4_srcS13__anonymous15_1){
    737     struct __anonymous15 _X4_retS13__anonymous15_1;
    738     {
    739         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X4_srcS13__anonymous15_1._X1ii_1));
    740     }
    741 
    742     {
    743         ((void)_X12_constructorFv_S13__anonymous15S13__anonymous15_autogen___1((&_X4_retS13__anonymous15_1), (*_X4_dstS13__anonymous15_1)));
    744     }
    745 
    746     return _X4_retS13__anonymous15_1;
    747 }
    748 static inline void _X12_constructorFv_S13__anonymous15i_autogen___1(struct __anonymous15 *_X4_dstS13__anonymous15_1, signed int _X1ii_1){
    749     {
    750         ((void)((*_X4_dstS13__anonymous15_1)._X1ii_1=_X1ii_1) /* ?{} */);
    751     }
    752 
    753 }
    754 static inline volatile const struct __anonymous15 _X3f32FS13__anonymous15___1();
    755755struct __anonymous16 {
    756756    signed int _X1ii_1;
     
    797797
    798798}
    799 static inline volatile const struct __anonymous16 _X3f33FS13__anonymous16___1();
     799static inline volatile const struct __anonymous16 _X3f31FS13__anonymous16___1();
    800800struct __anonymous17 {
    801801    signed int _X1ii_1;
     
    842842
    843843}
    844 static inline volatile const struct __anonymous17 _X3f34FS13__anonymous17___1();
     844static inline volatile const struct __anonymous17 _X3f32FS13__anonymous17___1();
    845845struct __anonymous18 {
    846846    signed int _X1ii_1;
     
    887887
    888888}
    889 static inline volatile const struct __anonymous18 _X3f35FS13__anonymous18___1();
     889static inline volatile const struct __anonymous18 _X3f33FS13__anonymous18___1();
    890890struct __anonymous19 {
    891891    signed int _X1ii_1;
     
    932932
    933933}
    934 static inline volatile const struct __anonymous19 _X3f36FS13__anonymous19___1();
     934static inline volatile const struct __anonymous19 _X3f34FS13__anonymous19___1();
    935935struct __anonymous20 {
    936936    signed int _X1ii_1;
     
    977977
    978978}
    979 static inline volatile const struct __anonymous20 _X3f37FS13__anonymous20___1();
     979static inline volatile const struct __anonymous20 _X3f35FS13__anonymous20___1();
    980980struct __anonymous21 {
    981981    signed int _X1ii_1;
     
    10221022
    10231023}
    1024 static inline volatile const struct __anonymous21 _X3f38FS13__anonymous21___1();
     1024static inline volatile const struct __anonymous21 _X3f36FS13__anonymous21___1();
     1025struct __anonymous22 {
     1026    signed int _X1ii_1;
     1027};
     1028static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1);
     1029static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1);
     1030static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1);
     1031static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1);
     1032static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1);
     1033static inline void _X12_constructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){
     1034    {
     1035        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ?{} */);
     1036    }
     1037
     1038}
     1039static inline void _X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){
     1040    {
     1041        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1) /* ?{} */);
     1042    }
     1043
     1044}
     1045static inline void _X11_destructorFv_S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1){
     1046    {
     1047        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1) /* ^?{} */);
     1048    }
     1049
     1050}
     1051static inline struct __anonymous22 _X16_operator_assignFS13__anonymous22_S13__anonymous22S13__anonymous22_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, struct __anonymous22 _X4_srcS13__anonymous22_1){
     1052    struct __anonymous22 _X4_retS13__anonymous22_1;
     1053    {
     1054        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X4_srcS13__anonymous22_1._X1ii_1));
     1055    }
     1056
     1057    {
     1058        ((void)_X12_constructorFv_S13__anonymous22S13__anonymous22_autogen___1((&_X4_retS13__anonymous22_1), (*_X4_dstS13__anonymous22_1)));
     1059    }
     1060
     1061    return _X4_retS13__anonymous22_1;
     1062}
     1063static inline void _X12_constructorFv_S13__anonymous22i_autogen___1(struct __anonymous22 *_X4_dstS13__anonymous22_1, signed int _X1ii_1){
     1064    {
     1065        ((void)((*_X4_dstS13__anonymous22_1)._X1ii_1=_X1ii_1) /* ?{} */);
     1066    }
     1067
     1068}
     1069static inline volatile const struct __anonymous22 _X3f37FS13__anonymous22___1();
     1070struct __anonymous23 {
     1071    signed int _X1ii_1;
     1072};
     1073static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1);
     1074static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1);
     1075static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1);
     1076static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1);
     1077static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1);
     1078static inline void _X12_constructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){
     1079    {
     1080        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ?{} */);
     1081    }
     1082
     1083}
     1084static inline void _X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){
     1085    {
     1086        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1) /* ?{} */);
     1087    }
     1088
     1089}
     1090static inline void _X11_destructorFv_S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1){
     1091    {
     1092        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1) /* ^?{} */);
     1093    }
     1094
     1095}
     1096static inline struct __anonymous23 _X16_operator_assignFS13__anonymous23_S13__anonymous23S13__anonymous23_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, struct __anonymous23 _X4_srcS13__anonymous23_1){
     1097    struct __anonymous23 _X4_retS13__anonymous23_1;
     1098    {
     1099        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X4_srcS13__anonymous23_1._X1ii_1));
     1100    }
     1101
     1102    {
     1103        ((void)_X12_constructorFv_S13__anonymous23S13__anonymous23_autogen___1((&_X4_retS13__anonymous23_1), (*_X4_dstS13__anonymous23_1)));
     1104    }
     1105
     1106    return _X4_retS13__anonymous23_1;
     1107}
     1108static inline void _X12_constructorFv_S13__anonymous23i_autogen___1(struct __anonymous23 *_X4_dstS13__anonymous23_1, signed int _X1ii_1){
     1109    {
     1110        ((void)((*_X4_dstS13__anonymous23_1)._X1ii_1=_X1ii_1) /* ?{} */);
     1111    }
     1112
     1113}
     1114static inline volatile const struct __anonymous23 _X3f38FS13__anonymous23___1();
    10251115static inline volatile const signed short int _X3f41Fs___1();
    10261116static inline volatile const signed short int _X3f42Fs___1();
  • tests/.expect/forall.txt

    r24d6572 r34b4268  
    1 1
    2 f
    3 97
    4 f
    5 g
    6 f
    7 f
    8 g
    9 fT
    10 fT
    11 fT
    12 fTU
    13 fTU
    14 fTU
    15 1 2
    16 2 1
    17 1, 2
    18 @ 0 2 0 4 6.4 6.4 6.4 6.4+3.i 4
    19 3. 3.
    20 45
    21 12 3
     1forall.cfa:244:25: warning: Compiled
  • tests/.expect/nested_function.x64.txt

    r24d6572 r34b4268  
    1 total 145
     1total 80
  • tests/.expect/nested_function.x86.txt

    r24d6572 r34b4268  
    1 total 245
     1total 55
  • tests/Makefile.am

    r24d6572 r34b4268  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Sun May 28 08:15:43 2023
    14 ## Update Count     : 196
     13## Last Modified On : Sat Jun  5 14:49:25 2021
     14## Update Count     : 92
    1515###############################################################################
    1616
     
    2222DEFAULT_INCLUDES = -I${abs_srcdir}
    2323
    24 debug ?= yes
    25 installed ?= no
    26 ARCH = ${if ${arch},"--arch=${arch}"}
    27 arch_support = "x86/x64/arm"
    28 TIMEOUT = ${if ${timeout},"--timeout=${timeout}"}
    29 GLOBAL_TIMEOUT = ${if ${global-timeout},"--global-timeout=${global-timeout}"}
    30 ARCHIVE_ERRORS = ${if ${archive-errors},"--archive-errors=${archive-errors}"}
    31 
    32 DEBUG_FLAGS = -debug -g -O0
    33 
    34 quick_test = avl_test operators numericConstants expression enum array typeof cast raii/dtor-early-exit raii/init_once attributes meta/dumpable
     24debug=yes
     25installed=no
     26archiveerrors=
     27
     28DEBUG_FLAGS=-debug -g -O0
     29
     30quick_test=avl_test operators numericConstants expression enum array typeof cast raii/dtor-early-exit raii/init_once attributes meta/dumpable
     31
     32concurrent=
     33timeouts=
    3534
    3635TEST_PY = python3 ${builddir}/test.py
     
    3837# applies to both programs
    3938# since automake doesn't have support for CFA we have to
    40 AM_CFLAGS = ${if ${test}, 2> ${test}, } \
    41         -fdebug-prefix-map=${abspath ${abs_srcdir}}= \
     39AM_CFLAGS = $(if $(test), 2> $(test), ) \
     40        -fdebug-prefix-map=$(abspath ${abs_srcdir})= \
    4241        -fdebug-prefix-map=/tmp= \
    4342        -fno-diagnostics-show-caret \
     
    5251
    5352# get the desired cfa to test
    54 TARGET_CFA = ${if ${filter ${installed},yes}, @CFACC_INSTALL@, @CFACC@}
     53TARGET_CFA = $(if $(filter $(installed),yes), @CFACC_INSTALL@, @CFACC@)
    5554
    5655# adjust CC to current flags
    57 CC = LC_ALL=C ${if ${DISTCC_CFA_PATH},distcc ${DISTCC_CFA_PATH} ${ARCH_FLAGS} ,${TARGET_CFA} ${DEBUG_FLAGS} ${ARCH_FLAGS}}
    58 CFACC = ${CC}
     56CC = LC_ALL=C $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS} ,$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
     57CFACC = $(CC)
    5958
    6059# get local binary for depedencies
     
    6261
    6362# adjusted CC but without the actual distcc call
    64 CFACCLOCAL = ${if ${DISTCC_CFA_PATH},${DISTCC_CFA_PATH} ${ARCH_FLAGS} ,${TARGET_CFA} ${DEBUG_FLAGS} ${ARCH_FLAGS}}
    65 CFACCLINK = ${CFACCLOCAL} -quiet ${if ${test}, 2> ${test}, } ${${shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'}}
    66 
    67 PRETTY_PATH = mkdir -p ${dir ${abspath ${@}}} && cd ${srcdir} &&
    68 
    69 .PHONY : concurrency list .validate .test_makeflags
    70 .INTERMEDIATE : .validate .validate.cfa .test_makeflags
     63CFACCLOCAL = $(if $(DISTCC_CFA_PATH),$(DISTCC_CFA_PATH) ${ARCH_FLAGS} ,$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
     64CFACCLINK = $(CFACCLOCAL) -quiet $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'))
     65
     66PRETTY_PATH=mkdir -p $(dir $(abspath ${@})) && cd ${srcdir} &&
     67
     68.PHONY: list .validate .test_makeflags
     69.INTERMEDIATE: .validate .validate.cfa .test_makeflags
    7170EXTRA_PROGRAMS = avl_test linkonce linking/mangling/anon .dummy_hack # build but do not install
    7271EXTRA_DIST = test.py \
     
    7978        avltree/avl-private.h \
    8079        avltree/avl.h \
     80        concurrent/clib_tls.c \
     81        concurrent/clib.c \
    8182        configs/.in/parseconfig-all.txt \
    8283        configs/.in/parseconfig-errors.txt \
     
    8788        io/.in/many_read.data \
    8889        meta/fork+exec.hfa \
    89         concurrency/clib_tls.c \
    90         concurrency/clib.c \
    91         concurrency/unified_locking/mutex_test.hfa \
    92         concurrency/channels/parallel_harness.hfa
     90        unified_locking/mutex_test.hfa
    9391
    9492dist-hook:
     
    9694        for file in `${TEST_PY} --list-dist`; do \
    9795                if test -f ${srcdir}/$${file}; then \
    98                         ${MKDIR_P} $$(dirname ${distdir}/$${file}); \
     96                        $(MKDIR_P) $$(dirname ${distdir}/$${file}); \
    9997                        cp -df ${srcdir}/$${file} ${distdir}/$${file}; \
    10098                fi; \
     
    108106
    109107#----------------------------------------------------------------------------------------------------------------
    110 
    111 # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program
    112 all-local : # This name is important to automake and implies the default build target.
    113         @+${TEST_PY} --debug=${debug} --install=${installed} --invariant ${ARCHIVE_ERRORS} ${TIMEOUT} ${GLOBAL_TIMEOUT} ${ARCH} --all
    114 
    115 tests : all-local # synonym
    116 
    117 install : all-local  # synonym, PAB only
    118 
    119 quick :
    120         @+${TEST_PY} --debug=${debug} --install=${installed} ${ARCHIVE_ERRORS} ${ARCH} ${quick_test}
    121 
    122 concurrency :
    123         @+${TEST_PY} --debug=${debug} --install=${installed} ${ARCHIVE_ERRORS} ${TIMEOUT} ${GLOBAL_TIMEOUT} ${ARCH} -Iconcurrency
    124 
    125 list :
    126         @+${TEST_PY} --list
    127 
    128 help :
    129         @echo "user targets:"
    130         @echo "    Run the complete test suite."
    131         @echo "    $$ make (null) / tests [debug=yes/no] [installed=yes/no] [archive-errors=dump-dir] [timeout=seconds] [global-timeout=seconds] [arch=${arch_support}]"
    132         @echo ""
    133         @echo "    Run the short (quick) test suite."
    134         @echo "    $$ make quick [debug=yes/no] [installed=yes/no] [archive-errors=dump-dir] [arch=${arch_support}]"
    135         @echo ""
    136         @echo "    Run the concurrency test suite."
    137         @echo "    $$ make concurrency [debug=yes/no] [installed=yes/no] [archive-errors=dump-dir] [timeout=seconds] [global-timeout=seconds] [arch=${arch_support}]"
    138         @echo ""
    139         @echo "    List all tests in the test suite."
    140         @echo "    $$ make list"
     108all-local :
     109        @+${TEST_PY} --debug=${debug} --install=${installed} --archive-errors=${archiveerrors} ${concurrent} ${timeouts} ${quick_test}
     110
     111all-tests :
     112        @+${TEST_PY} --debug=${debug} --install=${installed} --archive-errors=${archiveerrors} ${concurrent} ${timeouts} --all # '@' => do not echo command (SILENT), '+' => allows recursive make from within python program
    141113
    142114mostlyclean-local :
     
    150122        find ${builddir} -path '*.Po' -delete
    151123
     124list :
     125        @+${TEST_PY} --list ${concurrent}
     126
    152127.test_makeflags:
    153128        @echo "${MAKEFLAGS}"
    154129
    155130.validate: .validate.cfa
    156         ${CFACOMPILE} .validate.cfa -fsyntax-only -Wall -Wextra -Werror
     131        $(CFACOMPILE) .validate.cfa -fsyntax-only -Wall -Wextra -Werror
    157132
    158133.validate.cfa:
     
    166141        @echo "int bar() { return 0; }" > ${@}
    167142
     143concurrency :
     144        @+${TEST_PY} --debug=${debug}  --install=${installed} -Iconcurrent
     145
    168146#----------------------------------------------------------------------------------------------------------------
    169147
    170148# Use for all tests, make sure the path are correct and all flags are added
    171 CFACOMPILETEST=${PRETTY_PATH} ${CFACOMPILE} ${shell realpath --relative-to=${srcdir} ${<}} ${${shell echo "${@}_FLAGSCFA" | sed 's/-\|\//_/g'}}
     149CFACOMPILETEST=$(PRETTY_PATH) $(CFACOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) $($(shell echo "${@}_FLAGSCFA" | sed 's/-\|\//_/g'))
    172150
    173151#----------------------------------------------------------------------------------------------------------------
     
    176154# split into two steps to support compiling remotely using distcc
    177155# don't use distcc to do the linking because distcc doesn't do linking
    178 % : %.cfa ${CFACCBIN}
    179         ${CFACOMPILETEST} -c -o ${abspath ${@}}.o -DIN_DIR="${abspath ${dir ${<}}}/.in/"
    180         ${CFACCLINK} ${@}.o -o ${abspath ${@}}
    181         rm ${abspath ${@}}.o
     156% : %.cfa $(CFACCBIN)
     157        $(CFACOMPILETEST) -c -o $(abspath ${@}).o -DIN_DIR="$(abspath $(dir ${<}))/.in/"
     158        $(CFACCLINK) ${@}.o -o $(abspath ${@})
     159        rm $(abspath ${@}).o
    182160
    183161# implicit rule for c++ test
    184162# convient for testing the testsuite itself but not actuall used
    185163% : %.cpp
    186         ${PRETTY_PATH} ${CXXCOMPILE} ${shell realpath --relative-to=${srcdir} ${<}} -o ${abspath ${@}}
     164        $(PRETTY_PATH) $(CXXCOMPILE) $(shell realpath --relative-to=${srcdir} ${<}) -o $(abspath ${@})
    187165
    188166#------------------------------------------------------------------------------
     
    195173# Generated code
    196174GENERATED_CODE = declarationSpecifier gccExtensions extension attributes functions KRfunctions
    197 ${GENERATED_CODE} : % : %.cfa ${CFACCBIN}
    198         ${CFACOMPILETEST} -CFA -XCFA -p -c -fsyntax-only -o ${abspath ${@}}
     175$(GENERATED_CODE): % : %.cfa $(CFACCBIN)
     176        $(CFACOMPILETEST) -CFA -XCFA -p -c -fsyntax-only -o $(abspath ${@})
    199177
    200178#------------------------------------------------------------------------------
     
    202180#------------------------------------------------------------------------------
    203181# tests that just validate syntax and compiler output should be compared to stderr
    204 CFACOMPILE_SYNTAX = ${CFACOMPILETEST} -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o ${abspath ${@}}
    205 
    206 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator \
    207         init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment concurrency/waitfor/parse
    208 ${SYNTAX_ONLY_CODE} : % : %.cfa ${CFACCBIN}
    209         ${CFACOMPILE_SYNTAX}
    210         ${if ${test}, cp ${test} ${abspath ${@}}, }
     182CFACOMPILE_SYNTAX = $(CFACOMPILETEST) -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o $(abspath ${@})
     183
     184SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator forall \
     185        init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment
     186$(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN)
     187        $(CFACOMPILE_SYNTAX)
     188        $(if $(test), cp $(test) $(abspath ${@}), )
    211189
    212190# expected failures
    213191# use custom target since they require a custom define *and* have a name that doesn't match the file
    214 
    215 array-ERR1 : array.cfa ${CFACCBIN}
    216         ${CFACOMPILE_SYNTAX} -DERR1
    217         -cp ${test} ${abspath ${@}}
    218 
    219 array-ERR2 : array.cfa ${CFACCBIN}
    220         ${CFACOMPILE_SYNTAX} -DERR2
    221         -cp ${test} ${abspath ${@}}
    222 
    223 array-ERR3 : array.cfa ${CFACCBIN}
    224         ${CFACOMPILE_SYNTAX} -DERR3
    225         -cp ${test} ${abspath ${@}}
    226 
    227 alloc-ERROR : alloc.cfa ${CFACCBIN}
    228         ${CFACOMPILE_SYNTAX} -DERR1
    229         -cp ${test} ${abspath ${@}}
    230 
    231 init1-ERROR : init1.cfa ${CFACCBIN}
    232         ${CFACOMPILE_SYNTAX} -DERR1
    233         -cp ${test} ${abspath ${@}}
    234 
    235 typedefRedef-ERR1 : typedefRedef.cfa ${CFACCBIN}
    236         ${CFACOMPILE_SYNTAX} -DERR1
    237         -cp ${test} ${abspath ${@}}
    238 
    239 nested-types-ERR1 : nested-types.cfa ${CFACCBIN}
    240         ${CFACOMPILE_SYNTAX} -DERR1
    241         -cp ${test} ${abspath ${@}}
    242 
    243 nested-types-ERR2 : nested-types.cfa ${CFACCBIN}
    244         ${CFACOMPILE_SYNTAX} -DERR2
    245         -cp ${test} ${abspath ${@}}
    246 
    247 raii/memberCtors-ERR1 : raii/memberCtors.cfa ${CFACCBIN}
    248         ${CFACOMPILE_SYNTAX} -DERR1
    249         -cp ${test} ${abspath ${@}}
    250 
    251 raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa ${CFACCBIN}
    252         ${CFACOMPILE_SYNTAX} -DERR1
    253         -cp ${test} ${abspath ${@}}
    254 
    255 raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa ${CFACCBIN}
    256         ${CFACOMPILE_SYNTAX} -DERR1
    257         -cp ${test} ${abspath ${@}}
    258 
    259 raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa ${CFACCBIN}
    260         ${CFACOMPILE_SYNTAX} -DERR2
    261         -cp ${test} ${abspath ${@}}
     192alloc-ERROR : alloc.cfa $(CFACCBIN)
     193        $(CFACOMPILE_SYNTAX) -DERR1
     194        -cp $(test) $(abspath ${@})
     195
     196init1-ERROR : init1.cfa $(CFACCBIN)
     197        $(CFACOMPILE_SYNTAX) -DERR1
     198        -cp $(test) $(abspath ${@})
     199
     200typedefRedef-ERR1 : typedefRedef.cfa $(CFACCBIN)
     201        $(CFACOMPILE_SYNTAX) -DERR1
     202        -cp $(test) $(abspath ${@})
     203
     204nested-types-ERR1 : nested-types.cfa $(CFACCBIN)
     205        $(CFACOMPILE_SYNTAX) -DERR1
     206        -cp $(test) $(abspath ${@})
     207
     208nested-types-ERR2 : nested-types.cfa $(CFACCBIN)
     209        $(CFACOMPILE_SYNTAX) -DERR2
     210        -cp $(test) $(abspath ${@})
     211
     212raii/memberCtors-ERR1 : raii/memberCtors.cfa $(CFACCBIN)
     213        $(CFACOMPILE_SYNTAX) -DERR1
     214        -cp $(test) $(abspath ${@})
     215
     216raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa $(CFACCBIN)
     217        $(CFACOMPILE_SYNTAX) -DERR1
     218        -cp $(test) $(abspath ${@})
     219
     220raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa $(CFACCBIN)
     221        $(CFACOMPILE_SYNTAX) -DERR1
     222        -cp $(test) $(abspath ${@})
     223
     224raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa $(CFACCBIN)
     225        $(CFACOMPILE_SYNTAX) -DERR2
     226        -cp $(test) $(abspath ${@})
    262227
    263228# Exception Tests
    264229# Test with libcfathread; it changes how storage works.
    265230
    266 exceptions/%-threads : exceptions/%.cfa ${CFACCBIN}
    267         ${CFACOMPILETEST} -include exceptions/with-threads.hfa -c -o ${abspath ${@}}.o
    268         ${CFACCLOCAL} ${${shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g'}} ${abspath ${@}}.o -o ${abspath ${@}}
     231exceptions/%-threads : exceptions/%.cfa $(CFACCBIN)
     232        $(CFACOMPILETEST) -include exceptions/with-threads.hfa -c -o $(abspath ${@}).o
     233        $(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})
    269234
    270235# Linking tests
    271236# Meta tests to make sure we see linking errors (can't compile with -O2 since it may multiply number of calls)
    272 linking/linkerror : linking/linkerror.cfa ${CFACCBIN}
    273         ${CFACOMPILETEST} -O0 -c -o ${abspath ${@}}.o
    274         ${CFACCLINK}  -O0 ${@}.o -o ${abspath ${@}}
    275         rm ${abspath ${@}}.o
     237linking/linkerror : linking/linkerror.cfa $(CFACCBIN)
     238        $(CFACOMPILETEST) -O0 -c -o $(abspath ${@}).o
     239        $(CFACCLINK)  -O0 ${@}.o -o $(abspath ${@})
     240        rm $(abspath ${@}).o
    276241
    277242#------------------------------------------------------------------------------
  • tests/PRNG.cfa

    r24d6572 r34b4268  
    1 //
     1//                               -*- Mode: C -*-
     2//
    23// Cforall Version 1.0.0 Copyright (C) 2021 University of Waterloo
    3 //
    4 // PRNG.c -- high-perforamnce pseudo-random numbers
    5 //
    6 // The contents of this file are covered under the licence agreement in the
    7 // file "LICENCE" distributed with Cforall.
    8 //
     4//
     5// PRNG.c --
     6//
    97// Author           : Peter A. Buhr
    108// Created On       : Wed Dec 29 09:38:12 2021
    119// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May 25 15:39:52 2023
    13 // Update Count     : 422
     10// Last Modified On : Tue Nov 22 22:51:12 2022
     11// Update Count     : 381
    1412//
    1513
     
    1715#include <stdlib.hfa>                                                                   // PRNG
    1816#include <clock.hfa>
     17#include <thread.hfa>
    1918#include <limits.hfa>                                                                   // MAX
    2019#include <math.hfa>                                                                             // sqrt
    2120#include <malloc.h>                                                                             // malloc_stats
    2221#include <locale.h>                                                                             // setlocale
    23 #include <thread.hfa>
    2422#include <mutex_stmt.hfa>
    2523
    26 #define xstr(s) str(s)
    27 #define str(s) #s
    28 
    29 #if defined( __x86_64__ ) || defined( __aarch64__ )             // 64-bit architecture
     24#ifdef __x86_64__                                                                               // 64-bit architecture
    3025#define PRNG PRNG64
    3126#else                                                                                                   // 32-bit architecture
    3227#define PRNG PRNG32
    3328#endif // __x86_64__
    34 
    35 //#define TIME
    3629
    3730#ifdef TIME                                                                                             // use -O2 -nodebug
     
    4538#endif // TIME
    4639
    47 static void avgstd( size_t trials, size_t buckets[] ) {
    48         size_t min = MAX, max = 0;
     40void avgstd( unsigned int buckets[] ) {
     41        unsigned int min = MAX, max = 0;
    4942        double sum = 0.0, diff;
    5043        for ( i; BUCKETS ) {
     
    6154        } // for
    6255        double std = sqrt( sum / BUCKETS );
    63         mutex( sout ) sout | "trials"  | trials | "buckets" | BUCKETS
     56        mutex( sout ) sout | "trials"  | TRIALS | "buckets" | BUCKETS
    6457                | "min" | min | "max" | max
    6558                | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%";
     
    6760
    6861
    69 size_t seed = 1009;
     62unsigned int seed = 1009;
    7063
    7164thread T1 {};
    7265void main( T1 & ) {
    73         size_t * buckets = calloc( BUCKETS );                           // too big for task stack
    74         for ( TRIALS / 50 ) {
     66        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
     67        for ( TRIALS / 100 ) {
    7568                buckets[rand() % BUCKETS] += 1;                                 // concurrent
    7669        } // for
    77         avgstd( TRIALS / 50, buckets );
     70        avgstd( buckets );
    7871        free( buckets );
    7972} // main
     
    8376        PRNG prng;
    8477        if ( seed != 0 ) set_seed( prng, seed );
    85         size_t * buckets = calloc( BUCKETS );                           // too big for task stack
     78        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
    8679        for ( TRIALS ) {
    8780                buckets[prng( prng ) % BUCKETS] += 1;                   // concurrent
    8881        } // for
    89         avgstd( TRIALS, buckets );
     82        avgstd( buckets );
    9083        free( buckets );
    9184} // main
     
    9386thread T3 {};
    9487void main( T3 & th ) {
    95         size_t * buckets = calloc( BUCKETS );                           // too big for task stack
    96         for ( TRIALS / 5 ) {
     88        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
     89        for ( TRIALS ) {
    9790                buckets[prng() % BUCKETS] += 1;                                 // concurrent
    9891        } // for
    99         avgstd( TRIALS / 5, buckets );
     92        avgstd( buckets );
    10093        free( buckets );
    10194} // main
     
    10396thread T4 {};
    10497void main( T4 & th ) {
    105         size_t * buckets = calloc( BUCKETS );                           // too big for task stack
     98        unsigned int * buckets = calloc( BUCKETS );                     // too big for task stack
    10699        for ( TRIALS ) {
    107                 buckets[prng( th ) % BUCKETS] += 1;                             // concurrent
    108         } // for
    109         avgstd( TRIALS, buckets );
     100                buckets[prng( th ) % BUCKETS] += 1;     // concurrent
     101        } // for
     102        avgstd( buckets );
    110103        free( buckets );
    111104} // main
     
    115108static void dummy( thread$ & th ) __attribute__(( noinline ));
    116109static void dummy( thread$ & th ) {
    117         size_t * buckets = (size_t *)calloc( BUCKETS, sizeof(size_t) ); // too big for task stack
    118         for ( size_t i = 0; i < TRIALS; i += 1 ) {
     110        unsigned int * buckets = (unsigned int *)calloc( BUCKETS, sizeof(unsigned int) ); // too big for task stack
     111        for ( unsigned int i = 0; i < TRIALS; i += 1 ) {
    119112                buckets[prng( th ) % BUCKETS] += 1;                             // sequential
    120113        } // for
    121         avgstd( TRIALS, buckets );
     114        avgstd( buckets );
    122115        free( buckets );
    123116} // dummy
    124117
    125 
    126118int main() {
    127         // setlocale( LC_NUMERIC, getenv( "LANG" ) );           // causes leaked storage message
    128 
    129         // only works on the current pthread thread
    130         // locale_t loc = newlocale( LC_NUMERIC_MASK, getenv( "LANG" ), (locale_t)0p );
    131         // if ( loc == (locale_t)0p ) abort( "newlocale" );
    132         // uselocale( loc );
     119        // causes leaked storage message
     120//      setlocale( LC_NUMERIC, getenv( "LANG" ) );                      // print digit separator
    133121
    134122        enum { TASKS = 4 };
    135123        Time start;
    136 
    137124#ifdef TIME                                                                                             // too slow for test and generates non-repeatable results
    138125#if 1
    139         sout | "glib rand" | nl | nl;
    140 
    141         size_t rseed;
     126        unsigned int rseed;
    142127        if ( seed != 0 ) rseed = seed;
    143128        else rseed = rdtscl();
     
    145130
    146131        sout | sepDisable;
    147         sout | nl | wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" );
    148         for ( 20 ) {
    149                 sout | wd(26, rand()) | nonl;
    150                 sout | wd(12, rand() % 5) | nonl;
    151                 sout | wd(12, rand() % (5 - 0 + 1) + 0);
     132        sout | wd(13, "rand()" ) | wd(10, "rand(5)") | wd(13, "rand(0,5)" );
     133        for ( 20 ) {
     134                sout | wd(13, rand()) | nonl;
     135                sout | wd(10, rand() % 5) | nonl;
     136                sout | wd(13, rand() % (5 - 0 + 1) + 0);
    152137        } // for
    153138        sout | sepEnable;
     
    157142        STARTTIME;
    158143        {
    159                 size_t * buckets = calloc( BUCKETS );                   // too big for task stack
    160                 for ( i; TRIALS / 5 ) {
     144                unsigned int * buckets = calloc( BUCKETS );             // too big for task stack
     145                for ( i; TRIALS / 10 ) {
    161146                        buckets[rand() % BUCKETS] += 1;                         // sequential
    162147                } // for
    163                 avgstd( TRIALS / 5, buckets );
     148                avgstd( buckets );
    164149                free( buckets );
    165150        }
    166         ENDTIME( " x 5 " );
     151        ENDTIME( " x 10 " );
    167152
    168153        sout | nl | "Concurrent";
     
    174159                } // wait for threads to complete
    175160        }
    176         ENDTIME( " x 50 " );
     161        ENDTIME( " x 100 " );
    177162#endif // 0
    178163#endif // TIME
    179 
    180         sout | nl | "CFA " xstr(PRNG_NAME);
    181 
    182164#if 1
    183165        PRNG prng;
     
    186168
    187169        sout | sepDisable;
    188         sout | nl | wd(26, "PRNG()" ) | wd(12, "PRNG(5)") | wd(12, "PRNG(0,5)" );
    189         for ( 20 ) {
    190                 sout | wd(26, prng( prng )) | nonl;                             // cascading => side-effect functions called in arbitary order
    191                 sout | wd(12, prng( prng, 5 )) | nonl;
    192                 sout | wd(12, prng( prng, 0, 5 ));
     170        sout | nl | wd(13, "PRNG()" ) | wd(10, "PRNG(5)") | wd(13, "PRNG(0,5)" );
     171        for ( 20 ) {
     172                sout | wd(13, prng( prng )) | nonl;                             // cascading => side-effect functions called in arbitary order
     173                sout | wd(10, prng( prng, 5 )) | nonl;
     174                sout | wd(13, prng( prng, 0, 5 ));
    193175        } // for
    194176        sout | sepEnable;
     
    198180        STARTTIME;
    199181        {
    200                 size_t * buckets = calloc( BUCKETS );                   // too big for task stack
     182                unsigned int * buckets = calloc( BUCKETS );             // too big for task stack
    201183                for ( TRIALS ) {
    202184                        buckets[prng( prng ) % BUCKETS] += 1;           // sequential
    203185                } // for
    204                 avgstd( TRIALS, buckets );
     186                avgstd( buckets );
    205187                free( buckets );
    206188        }
     
    221203
    222204        sout | sepDisable;
    223         sout | nl | wd(26, "prng()" ) | wd(12, "prng(5)") | wd(12, "prng(0,5)" );
    224         for ( 20 ) {
    225                 sout | wd(26, prng()) | nonl;                                   // cascading => side-effect functions called in arbitary order
    226                 sout | wd(12, prng( 5 )) | nonl;
    227                 sout | wd(12, prng( 0, 5 ));
     205        sout | nl | wd(13, "prng()" ) | wd(10, "prng(5)") | wd(13, "prng(0,5)" );
     206        for ( 20 ) {
     207                sout | wd(13, prng()) | nonl;                                   // cascading => side-effect functions called in arbitary order
     208                sout | wd(10, prng( 5 )) | nonl;
     209                sout | wd(13, prng( 0, 5 ));
    228210        } // for
    229211        sout | sepEnable;
     
    233215        STARTTIME;
    234216        {
    235                 size_t * buckets = calloc( BUCKETS );                   // too big for task stack
    236                 for ( TRIALS / 5 ) {
     217                unsigned int * buckets = calloc( BUCKETS );             // too big for task stack
     218                for ( TRIALS ) {
    237219                        buckets[prng() % BUCKETS] += 1;
    238220                } // for
    239                 avgstd( TRIALS / 5, buckets );
     221                avgstd( buckets );
    240222                free( buckets );
    241223        }
    242         ENDTIME( " x 5 " );
     224        ENDTIME();
    243225
    244226        sout | nl | "Concurrent";
     
    250232                } // wait for threads to complete
    251233        }
    252         ENDTIME( " x 5 " );
     234        ENDTIME();
    253235#endif // 0
    254236#if 1
     
    257239
    258240        sout | sepDisable;
    259         sout | nl | wd(26, "prng(t)" ) | wd(12, "prng(t,5)") | wd(12, "prng(t,0,5)" );
    260         for ( 20 ) {
    261                 sout | wd(26, prng( th )) | nonl;                               // cascading => side-effect functions called in arbitary order
    262                 sout | wd(12, prng( th, 5 )) | nonl;
    263                 sout | wd(12, prng( th, 0, 5 ));
     241        sout | nl | wd(13, "prng(t)" ) | wd(10, "prng(t,5)") | wd(13, "prng(t,0,5)" );
     242        for ( 20 ) {
     243                sout | wd(13, prng( th )) | nonl;                               // cascading => side-effect functions called in arbitary order
     244                sout | wd(10, prng( th, 5 )) | nonl;
     245                sout | wd(13, prng( th, 0, 5 ));
    264246        } // for
    265247        sout | sepEnable;
     
    284266#endif // 0
    285267//      malloc_stats();
    286         // freelocale( loc );
    287268} // main
    288269
  • tests/array.cfa

    r24d6572 r34b4268  
    1515//
    1616
    17 // Tests syntax.  Comments explain semantics.  Test does not show semantics.
    18 // Mostly illustrates facts about C (with which CFA is being tested to agree).
    19 // Is a test oracle under `gcc -x c`.
     17int a1[0];
     18//int a2[*];
     19//double a4[3.0];
    2020
    21 #ifdef ERR1
    22 #define E1(...) __VA_ARGS__
    23 #else
    24 #define E1(...)
    25 #endif
     21int m1[0][3];
     22//int m2[*][*];
     23int m4[3][3];
    2624
    27 #ifdef ERR2
    28 #define E2(...) __VA_ARGS__
    29 #else
    30 #define E2(...)
    31 #endif
     25typedef int T;
    3226
    33 #ifdef ERR3
    34 #define E3(...) __VA_ARGS__
    35 #else
    36 #define E3(...)
    37 #endif
     27int fred() {
     28//      int a1[];
     29//      int a2[*];
     30        int a4[3];
     31        int T[3];
     32}
    3833
    39     int a1[0];
    40 E1( int a2[*];       )
    41                                                         #ifndef __cforall
    42 E1( double a4[3.0];  )                                  // BUG 275: CFA accepts but should reject
    43                                                         #endif
     34int mary( int T[3],
     35                  int p1[const 3],
     36                  int p2[static 3],
     37                  int p3[static const 3]
     38        ) {
     39}
    4440
    45     int m1[0][3];
    46 E1( int m2[*][*];    )
    47     int m4[3][3];
     41int (*tom())[3] {
     42}
    4843
    49     typedef int T;
    50 
    51     int fred(int n) {
    52 E1(     int a1[];    )
    53 E1(     int a2[*];   )
    54         int a4[3];
    55         int T[3];
    56         int a5[n];
    57     }
    58 
    59     int mary( int T[3],                                 // same as: int *T
    60               int p1[const 3],                          // same as: int const *p1
    61               int p2[static 3],                         // same as T, but length >=3 checked
    62               int p3[static const 3]                    // both above: 3 is static, p3 is const
    63         ) {
    64     }
    65 
    66     // function taking (), returning pointer to array of ints
    67     int (*tom())[3] {
    68     }
    69 
    70     // function taking (), returning pointer to function of same type as mary
    71     int (*(jane)())( int T[3],
    72                      int p1[const 3],
    73                      int p2[static 3],
    74                      int p3[static const 3]
    75         ) {
    76     }
    77 
    78     // functions returning same exotic pointers, in CFA's non-onion syntax
    79     #ifdef __cforall
    80     [ * [3] int ] toms_twin(...) {
    81     }
    82     [ * [int]( [3] int T,
    83                [const 3] int p1,
    84                [static 3] int p2,
    85                [static const 3] int p3
    86              )
    87     ] janes_twin(...) {
    88     }
    89     #endif
    90 
    91     // GCC 11+ gives a false warning (-Wvla-parameter) on the valid (C11 ARM p134-135) combination:
    92     // declare with type int[*], define with type int[n].
    93     // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=100420 suggests the internal representation of
    94     // of a[*] is the same as a[0].
    95     // https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wno-vla-parameter explains
    96     // the purpose of -Wvla-parameter is to report conflicts between int[] and int[n], which would
    97     // understandably also include those between int[42] and int[n].
    98     // https://stackoverflow.com/questions/17371645/why-use-an-asterisk-instead-of-an-integer-for-a-vla-array-parameter-of-a-f
    99     // explains the declare-*, define-n pattern.
    100 
    101     // To work around the false warning, and keep to this test's purpose of exercising CFA's
    102     // handling of exotic C array syntax, what would ideally be demonstrated as a declaration of
    103     // fm1, followed by its definition, is instead split into fm1x and fm1y.  And similarly for
    104     // fm5.
    105 
    106     int fm1x( int, int, int[][*] );
    107     int fm1y( int r, int c, int m[][c] ) {}
    108     int fm2( int r, int c, int (*m)[c] ) {}             // same as fm1
    109 E2( int fm3( int r, int c, int m[][static c] ) {}  )    // that's not static
    110 E3( int fm4( int r, int c, int m[][] );            )    // m's immediate element type is incomplete
    111     int fm5x( int, int, int[*][*] );                    // same as fm1 decl
    112                                                         #ifndef __cforall
    113     int fm5y( int r, int c, int m[r][c] ) {}            // BUG 276: CFA chokes but should accept
    114                                                         // C: same as fm1 defn
    115                                                         #endif
    116 
     44int (*(jane)())( int T[3],
     45                                 int p1[const 3],
     46                                 int p2[static 3],
     47                                 int p3[static const 3]
     48        ) {
     49}
    11750
    11851int main() {
    119     #pragma GCC warning "Preprocessor started"          // force non-empty .expect file, NO TABS!!!
     52    #pragma GCC warning "Compiled"                      // force non-empty .expect file, NO TABS!!!
    12053}
    12154
  • tests/attributes.cfa

    r24d6572 r34b4268  
    1010// Created On       : Mon Feb  6 16:07:02 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 23 20:33:07 2023
    13 // Update Count     : 39
     12// Last Modified On : Mon Mar 15 13:53:31 2021
     13// Update Count     : 38
    1414//
    1515
     
    2222
    2323// aggregate_name
    24 static struct __attribute__(( unused )) {} Dummy;
     24struct __attribute__(( unused )) {} Dummy;
    2525struct __attribute__(( unused )) Agn1;
    2626struct __attribute__(( unused )) Agn2 {};
  • tests/avltree/avl.h

    r24d6572 r34b4268  
    99// #include <lib.h>
    1010
    11 forall(T)
    12 trait Comparable {
     11trait Comparable(T) {
    1312  int ?<?(T, T);
    1413};
  • tests/collections/vector-demo.cfa

    r24d6572 r34b4268  
    143143    assert( v`capacity >  5 && v`length == 5 );
    144144
    145     v[2] = -0.1f;  // v is [0.0, 98.6, -0.1, 0.2, 0.3]; iter at -0.1, where only the new memory had that change
     145    v[2] = -0.1;  // v is [0.0, 98.6, -0.1, 0.2, 0.3]; iter at -0.1, where only the new memory had that change
    146146
    147147    float val3 = iter`val;
  • tests/declarationSpecifier.cfa

    r24d6572 r34b4268  
    1010// Created On       : Wed Aug 17 08:21:04 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 23 20:53:31 2023
    13 // Update Count     : 8
     12// Last Modified On : Tue Apr 30 18:20:36 2019
     13// Update Count     : 4
    1414//
    1515
     
    2525short int volatile static const x8;
    2626
    27 static const volatile struct { int i; } x10;
    28 static const struct { int i; } volatile x11;
    29 static struct { int i; } const volatile x12;
    30 const static struct { int i; } volatile x13;
    31 struct { int i; } static const volatile x14;
    32 struct { int i; } const static volatile x15;
    33 struct { int i; } const volatile static x16;
     27const volatile struct { int i; } x10;
     28const struct { int i; } volatile x11;
     29struct { int i; } const volatile x12;
     30static const volatile struct { int i; } x13;
     31const static struct { int i; } volatile x14;
     32struct { int i; } static const volatile x15;
     33struct { int i; } const static volatile x16;
     34struct { int i; } const volatile static x17;
    3435
    3536const Int volatile x20;
     
    4243Int volatile static const x27;
    4344
    44 static const volatile struct { Int i; } x29;
    45 static const struct { Int i; } volatile x30;
    46 static struct { Int i; } const volatile x31;
    47 const static struct { Int i; } volatile x32;
    48 struct { Int i; } static const volatile x33;
    49 struct { Int i; } const static volatile x34;
    50 struct { Int i; } const volatile static x35;
     45const volatile struct { Int i; } x29;
     46const struct { Int i; } volatile x30;
     47struct { Int i; } const volatile x31;
     48static const volatile struct { Int i; } x32;
     49const static struct { Int i; } volatile x33;
     50struct { Int i; } static const volatile x34;
     51struct { Int i; } const static volatile x35;
     52struct { Int i; } const volatile static x36;
    5153
    5254_Thread_local int x37;
  • tests/enum_tests/.expect/typedIntEnum.txt

    r24d6572 r34b4268  
    1 0=0
    2 1=1
    3 1000=1000
    4 1001=1001
    5 2000=2000
    6 2001=2001
    7 2002=2002
     10
     21
     31000
     41001
     52000
     62001
     72002
  • tests/enum_tests/pointerEnum.cfa

    r24d6572 r34b4268  
    1111int main() {
    1212    E * v = First;
    13     // sout | "v: " | e.x;
     13    sout | "v: " | e.x;
    1414}
  • tests/enum_tests/typedIntEnum.cfa

    r24d6572 r34b4268  
    1212
    1313int main() {
    14     printf("0=%d\n", zero);
    15     printf("1=%d\n", one);
    16     printf("1000=%d\n", thousand);
    17     printf("1001=%d\n", thousand_one);
    18     printf("2000=%d\n", two_thousand);
    19     printf("2001=%d\n", two_thousand_one);
    20     printf("2002=%d\n", two_thousand_two);
     14    printf("%d\n", zero);
     15    printf("%d\n", one);
     16    printf("%d\n", thousand);
     17    printf("%d\n", thousand_one);
     18    printf("%d\n", two_thousand);
     19    printf("%d\n", two_thousand_one);
     20    printf("%d\n", two_thousand_two);
    2121    return 0;
    2222}
  • tests/errors/.expect/declaration.txt

    r24d6572 r34b4268  
    1 errors/declaration.cfa:16:1 error: duplicate static storage class(es) in declaration of x1: static const volatile short int
     1errors/declaration.cfa:16:1 error: duplicate static in declaration of x1: static const volatile short int
    22
    3 errors/declaration.cfa:17:1 error: conflicting extern & static storage classes in declaration of x2: extern const volatile short int
     3errors/declaration.cfa:17:1 error: conflicting extern & static in declaration of x2: extern const volatile short int
    44
    5 errors/declaration.cfa:18:1 error: conflicting extern & auto storage classes, conflicting extern & static storage classes, conflicting extern & static storage classes, duplicate extern storage class(es) in declaration of x3: extern const volatile short int
     5errors/declaration.cfa:18:1 error: conflicting extern & auto, conflicting extern & static, conflicting extern & static, duplicate extern in declaration of x3: extern const volatile short int
    66
    7 errors/declaration.cfa:19:1 error: duplicate static storage class(es) in declaration of x4: static const volatile instance of const volatile struct __anonymous0
     7errors/declaration.cfa:19:1 error: duplicate static in declaration of x4: static const volatile instance of const volatile struct __anonymous0
    88  with members
    99    i: int
     
    1111
    1212
    13 errors/declaration.cfa:20:1 error: duplicate const qualifier(s), duplicate static storage class(es), duplicate volatile qualifier(s) in declaration of x5: static const volatile instance of const volatile struct __anonymous1
     13errors/declaration.cfa:20:1 error: duplicate const, duplicate static, duplicate volatile in declaration of x5: static const volatile instance of const volatile struct __anonymous1
    1414  with members
    1515    i: int
     
    1717
    1818
    19 errors/declaration.cfa:22:1 error: duplicate static storage class(es) in declaration of x6: static const volatile Int
     19errors/declaration.cfa:22:1 error: duplicate static in declaration of x6: static const volatile Int
    2020
    21 errors/declaration.cfa:24:1 error: duplicate const qualifier(s) in declaration of f01: static inline function
     21errors/declaration.cfa:24:1 error: duplicate const in declaration of f01: static inline function
    2222  with no parameters
    2323  returning const volatile int
    2424
    2525
    26 errors/declaration.cfa:25:1 error: duplicate volatile qualifier(s) in declaration of f02: static inline function
     26errors/declaration.cfa:25:1 error: duplicate volatile in declaration of f02: static inline function
    2727  with no parameters
    2828  returning const volatile int
    2929
    3030
    31 errors/declaration.cfa:26:1 error: duplicate const qualifier(s) in declaration of f03: static inline function
     31errors/declaration.cfa:26:1 error: duplicate const in declaration of f03: static inline function
    3232  with no parameters
    3333  returning const volatile int
    3434
    3535
    36 errors/declaration.cfa:27:1 error: duplicate volatile qualifier(s) in declaration of f04: static inline function
     36errors/declaration.cfa:27:1 error: duplicate volatile in declaration of f04: static inline function
    3737  with no parameters
    3838  returning const volatile int
    3939
    4040
    41 errors/declaration.cfa:28:1 error: duplicate const qualifier(s) in declaration of f05: static inline function
     41errors/declaration.cfa:28:1 error: duplicate const in declaration of f05: static inline function
    4242  with no parameters
    4343  returning const volatile int
    4444
    4545
    46 errors/declaration.cfa:29:1 error: duplicate volatile qualifier(s) in declaration of f06: static inline function
     46errors/declaration.cfa:29:1 error: duplicate volatile in declaration of f06: static inline function
    4747  with no parameters
    4848  returning const volatile int
    4949
    5050
    51 errors/declaration.cfa:30:1 error: duplicate const qualifier(s) in declaration of f07: static inline function
     51errors/declaration.cfa:30:1 error: duplicate const in declaration of f07: static inline function
    5252  with no parameters
    5353  returning const volatile int
    5454
    5555
    56 errors/declaration.cfa:31:1 error: duplicate const volatile qualifier(s) in declaration of f08: static inline function
     56errors/declaration.cfa:31:1 error: duplicate const, duplicate volatile in declaration of f08: static inline function
    5757  with no parameters
    5858  returning const volatile int
    5959
    6060
    61 errors/declaration.cfa:33:1 error: duplicate const volatile qualifier(s) in declaration of f09: static inline function
     61errors/declaration.cfa:33:1 error: duplicate const, duplicate volatile in declaration of f09: static inline function
    6262  with no parameters
    6363  returning const volatile int
    6464
    6565
    66 errors/declaration.cfa:34:1 error: duplicate const qualifier(s), duplicate _Atomic qualifier(s), duplicate _Atomic qualifier(s), duplicate const restrict volatile qualifier(s) in declaration of f09: static inline function
     66errors/declaration.cfa:34:1 error: duplicate const, duplicate _Atomic, duplicate _Atomic, duplicate const, duplicate restrict, duplicate volatile in declaration of f09: static inline function
    6767  with no parameters
    6868  returning const restrict volatile _Atomic int
  • tests/forall.cfa

    r24d6572 r34b4268  
    1010// Created On       : Wed May  9 08:48:15 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 23 20:29:59 2023
    13 // Update Count     : 91
    14 //
    15 
    16 #include <fstream.hfa>
     12// Last Modified On : Sat Jun  5 10:06:08 2021
     13// Update Count     : 36
     14//
    1715
    1816void g1() {
    19         forall( T ) T f( T p ) { sout | 'f'; return p;  };
    20         void f( int p ) { sout | p; };
    21         void g( void ) { sout | 'g'; };
    22         void h( void (*p)(void) ) { p(); };
    23 
    24         int x = 1;
    25         void (*y)(void) = g;
    26         char z = 'a';
    27         float w = 3.5;
     17        forall( T ) T f( T ) {};
     18        void f( int ) {};
     19        void h( void (*p)(void) ) {};
     20
     21        int x;
     22        void (*y)(void);
     23        char z;
     24        float w;
    2825
    2926        f( x );
     
    3128        f( z );
    3229        f( w );
    33         h( y );
    34         f( y );
    3530        h( f( y ) );
    3631}
    3732
    3833void g2() {
    39         forall( T ) void f( T, T ) { sout | "fT"; }
    40         forall( T, U ) void f( T, U ) { sout | "fTU"; }
     34        forall( T ) void f( T, T ) {}
     35        forall( T, U ) void f( T, U ) {}
    4136
    4237        int x;
    4338        float y;
    44         int * z;
    45         float * w;
    46 
    47         f( x, x );
    48         f( y, y );
    49         f( w, w );
     39        int *z;
     40        float *w;
     41
    5042        f( x, y );
    5143        f( z, w );
     
    5850
    5951forall( T )
    60 void swap( T & left, T & right ) {                                              // by reference
    61     T temp = left;
    62     left = right;
    63     right = temp;
    64 }
    65 
    66 forall( T )
    67 [ T, T ] swap( T i, T j ) {                                                             // by value
    68     return [ j, i ];
    69 }
    70 
    71 forall( T ) trait sumable {
     52void swap( T left, T right ) {
     53        T temp = left;
     54        left = right;
     55        right = temp;
     56}
     57
     58trait sumable( T ) {
    7259        void ?{}( T &, zero_t );                                                        // 0 literal constructor
    7360        T ?+?( T, T );                                                                          // assortment of additions
     
    7764}; // sumable
    7865
    79 forall( T | sumable( T ) )                                                              // use trait
     66forall( T | sumable( T ) )                                              // use trait
    8067T sum( size_t size, T a[] ) {
    8168        T total = 0;                                                                            // initialize by 0 constructor
     
    8572} // sum
    8673
    87 forall( T | { T ?+?( T, T ); T ?++( T & ); [T] ?+=?( T &, T ); } )
     74forall( T | { T ?+?( T, T ); T ?++( T & ); [T] ?+=?( T &,T ); } )
    8875T twice( T t ) {
    8976        return t + t;
     
    9582}
    9683
    97 void fred() {
    98         int x = 1, y = 2, a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
     84int fred() {
     85        int x = 1, y = 2, a[10];
    9986        float f;
    10087
    101         sout | x | y;
    10288        swap( x, y );
    103         sout | x | y | nl | swap( x, y );
    104         // [ x, y ] = swap( y, x );
    105         sout | twice( ' ' ) | ' ' | twice( 0hh ) | twice( 1h ) | twice( 0n ) | twice( 2 )
    106                  | twice( 3.2f ) | twice( 3.2 ) | twice( 3.2d ) | twice( 3.2+1.5i ) | twice( x );
     89        twice( x );
    10790        f = min( 4.0, 3.0 );
    108         sout | f | min( 4.0, 3.0 );
    109         sout | sum( 10, a );
     91        sum( 10, a );
    11092}
    11193
     
    195177
    196178forall( T ) struct S { T t; } (int) x, y, z;
    197 static forall( T ) struct { T t; } (int) a, b, c;
     179forall( T ) struct { T t; } (int) a, b, c;
    198180
    199181forall( T ) static forall( S ) {
     
    204186
    205187forall( T ) {
    206 //      extern "C" {
     188        extern "C" {
    207189                struct SS { T t; };
    208                 T foo( T p ) { return p; }
    209 //      }
     190                T foo( T ) {}
     191        }
    210192}
    211193
     
    213195W(int,int) w;
    214196
    215 void jane() {
     197int jane() {
    216198//      int j = bar( 3, 4 );
    217199        int k = baz( 3, 4, 5 );
    218200        int i = foo( 3 );
    219         sout | k | i;
    220201}
    221202
     
    230211        T t;
    231212        T t2 = t;
    232         sout | &tr | tp;
    233213}
    234214
     
    262242
    263243int main( void ) {
    264         g1();
    265         g2();
    266         fred();
    267         jane();
     244    #pragma GCC warning "Compiled"                      // force non-empty .expect file, NO TABS!!!
    268245}
    269246
  • tests/function-operator.cfa

    r24d6572 r34b4268  
    1010// Created On       : Fri Aug 25 15:21:11 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 25 07:26:10 2023
    13 // Update Count     : 12
     12// Last Modified On : Thu Apr 11 18:27:45 2019
     13// Update Count     : 10
    1414//
    1515
     
    2222
    2323// STL-like Algorithms
    24 forall(T &, U &)
    25 trait Assignable { T ?=?(T &, U); };
    26 forall(T &)
    27 trait Copyable { void ?{}(T &, T); };
    28 forall(T &)
    29 trait Destructable { void ^?{}(T &); };
     24trait Assignable(T &, U &) { T ?=?(T &, U); };
     25trait Copyable(T &) { void ?{}(T &, T); };
     26trait Destructable(T &) { void ^?{}(T &); };
    3027
    3128trait Iterator(iter & | sized(iter) | Copyable(iter) | Destructable(iter), T) {
  • tests/include/includes.cfa

    r24d6572 r34b4268  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 22 10:16:58 2023
    13 // Update Count     : 811
     12// Last Modified On : Sun May 22 08:27:20 2022
     13// Update Count     : 779
    1414//
    1515
     
    7272#include <gshadow.h>
    7373#include <iconv.h>
    74 //#include <ifaddrs.h>                                                                  // causes warning messages that break the build
     74#include <ifaddrs.h>
    7575#include <inttypes.h>
    7676#include <langinfo.h>
     
    9797#include <ncurses_dll.h>                                                                // may not be installed, comes with ncurses
    9898#endif
    99 //#include <netdb.h>
     99#include <netdb.h>
    100100#include <nl_types.h>
    101101#include <nss.h>
     
    111111#include <pwd.h>
    112112#include <regex.h>
    113 //#include <resolv.h>
     113#include <resolv.h>
    114114#include <re_comp.h>
    115115#include <sched.h>
     
    170170#endif // __CFA__
    171171
    172 int main() {
     172int main( int argc, char const * argv[] ) {
    173173    #pragma GCC warning "Compiled"                                                      // force non-empty .expect file, NO TABS!!!
    174174}
  • tests/io/comp_basic.cfa

    r24d6572 r34b4268  
    2626#include <unistd.h>
    2727
    28 static struct {
     28struct {
    2929        barrier & bar;
    3030        int pipe[2];
     31
    3132} globals;
    3233
  • tests/io/comp_fair.cfa

    r24d6572 r34b4268  
    2626#include <unistd.h>
    2727
    28 static struct {
     28struct {
    2929        barrier & bar;
    3030        int pipe[2];
     31
    3132} globals;
    3233
  • tests/linking/mangling/header.hfa

    r24d6572 r34b4268  
    88extern name_but_a_typedefed_t a_typedefed_global;
    99
    10 // Must be extern C to prevent name mangling.
    11 extern "C" {
    12         extern struct /* anonymous */ {
    13                 int some_int;
    14                 int some_other_int;
    15         } a_global_with_no_type;
    16 }
     10extern struct /* anonymous */ {
     11        int some_int;
     12        int some_other_int;
     13} a_global_with_no_type;
  • tests/linking/mangling/lib.cfa

    r24d6572 r34b4268  
    33name_but_a_typedefed_t a_typedefed_global;
    44
    5 // Must be extern C to prevent name mangling.
    6 extern "C" {
    7         // This declaration is necessary to create an instance of a_global_with_no_type.
    8         // typeof is a trick to get a_global_with_no_type's type because its type is anonymous.
    9         // Otherwise C generates conflicting types for a_global_with_no_type in .h and .c
    10         // because C uses name equivalence and the two anonymous types cannot have the same name.
    11         typeof(a_global_with_no_type) a_global_with_no_type;
    12 }
     5struct {
     6        int some_int;
     7        int some_other_int;
     8} a_global_with_no_type;
  • tests/linking/mangling/main.cfa

    r24d6572 r34b4268  
    11#include <fstream.hfa>
    22
    3 static struct { int a; } test; // purposefully before the include to force anonymous name numbering
     3struct { int a; } test; //purposefully before the include
    44
    55#include "header.hfa"
     
    1313
    1414        sout | "Done!";
     15
     16        return 0;
    1517}
  • tests/pybin/settings.py

    r24d6572 r34b4268  
    126126        global archive
    127127        global install
    128         global invariant
    129128
    130129        global continue_
     
    141140        all_install  = [Install(o)      for o in list(dict.fromkeys(options.install))]
    142141        archive      = os.path.abspath(os.path.join(original_path, options.archive_errors)) if options.archive_errors else None
    143         invariant    = options.invariant
    144142        continue_    = options.continue_
    145143        dry_run      = options.dry_run # must be called before tools.config_hash()
  • tests/quotedKeyword.cfa

    r24d6572 r34b4268  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 23 20:31:05 2023
    13 // Update Count     : 26
     12// Last Modified On : Fri Feb  7 19:07:07 2020
     13// Update Count     : 25
    1414//
    1515
    1616#include <fstream.hfa>
    1717
    18 static struct {
     18struct {
    1919        int ``otype;
    2020        int ``struct;
  • tests/sum.cfa

    r24d6572 r34b4268  
    1111// Created On       : Wed May 27 17:56:53 2015
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Fri Feb 24 22:52:12 2023
    14 // Update Count     : 347
     13// Last Modified On : Thu Aug  5 21:27:25 2021
     14// Update Count     : 346
    1515//
    1616
     
    1818#include <stdlib.hfa>
    1919
    20 forall( T )
    21 trait sumable {
     20trait sumable( T ) {
    2221        void ?{}( T &, zero_t );                                                        // 0 literal constructor
    2322        void ?{}( T &, one_t );                                                         // 1 literal constructor
  • tests/test.py

    r24d6572 r34b4268  
    114114        parser.add_argument('--install', help='Run all tests based on installed binaries or tree binaries', type=comma_separated(yes_no), default='no')
    115115        parser.add_argument('--continue', help='When multiple specifications are passed (debug/install/arch), sets whether or not to continue if the last specification failed', type=yes_no, default='yes', dest='continue_')
    116         parser.add_argument('--invariant', help='Tell the compiler to check invariants while running.', action='store_true')
    117116        parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=180)
    118117        parser.add_argument('--global-timeout', help='Maximum cumulative duration in seconds after the ALL tests are considered to have timed out', type=int, default=7200)
     
    173172        test.prepare()
    174173
    175         # extra flags for cfa to pass through make.
    176         cfa_flags = 'CFAFLAGS=--invariant' if settings.invariant else None
    177 
    178174        # ----------
    179175        # MAKE
     
    181177        # build, skipping to next test on error
    182178        with Timed() as comp_dur:
    183                 make_ret, _, _ = make(test.target(), flags=cfa_flags, output_file=subprocess.DEVNULL, error=out_file, error_file=err_file)
     179                make_ret, _, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file )
    184180
    185181        # ----------
Note: See TracChangeset for help on using the changeset viewer.