Changes in / [b067d9b:7951100]


Ignore:
Files:
640 added
968 deleted
194 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    rb067d9b r7951100  
    88config.status
    99config.log
    10 config.py
    1110stamp-h1
    12 libtool
    1311/Makefile
    14 **/Makefile
     12src/**/Makefile
     13tools/**/Makefile
    1514/version
    1615
     
    2120.deps
    2221.dirstamp
    23 /bin
    24 /lib
    25 /include
    26 /share
    27 /build
     22bin
     23lib
     24include
     25share
    2826*.class
    2927
    3028# src executables, for lib and bin
    31 driver/as
    32 driver/cfa
    33 driver/cfa-cpp
    34 driver/cc1
     29src/driver/cc1
     30src/driver/cfa
     31src/driver/cfa-cpp
    3532
    36 libcfa/prelude/bootloader.c
    37 libcfa/prelude/builtins.cf
    38 libcfa/prelude/extras.cf
    39 libcfa/prelude/gcc-builtins.cf
    40 libcfa/prelude/gcc-builtins.c
    41 libcfa/prelude/prelude.cfa
    42 libcfa/x64-debug/
    43 libcfa/x64-nodebug/
    44 libcfa/x64-nolib/
    45 libcfa/x86-debug/
    46 libcfa/x86-nodebug/
    47 libcfa/x86-nolib/
    48 libcfa/arm-debug/
    49 libcfa/arm-nodebug/
    50 libcfa/arm-nolib/
     33src/prelude/builtins.cf
     34src/prelude/gcc-builtins.cf
     35src/prelude/gcc-builtins.c
     36src/prelude/extras.cf
     37src/prelude/bootloader.c
     38src/libcfa/libcfa-prelude.c
    5139
    5240# generated by bison and lex from parser.yy and lex.ll
     
    5644src/Parser/parser.h
    5745src/Parser/parser.hh
    58 src/demangler
    5946
    6047tools/prettyprinter/parser.output
  • INSTALL

    rb067d9b r7951100  
    2222  it is important not to put quotes around the directory path; Cforall may
    2323  appear to build, but the installed version may not work properly.
     24
     25--with-backend-compiler=PROGRAM specifies the installed path of gcc.  It
     26  defaults to the first command named 'gcc' in the current PATH.
     27
     28cfa-cc itself is built with the version of g++ specified by the environment
     29variable CXX.  If CXX is unset, cfa-cc is built using the first command named
     30'g++' in the current PATH.
  • Jenkins/FullBuild

    rb067d9b r7951100  
    1717
    1818                                parallel (
    19                                         gcc_6_x64: { trigger_build( 'gcc-6',   'x64' ) },
    20                                         gcc_6_x86: { trigger_build( 'gcc-6',   'x86' ) },
    21                                         gcc_5_x64: { trigger_build( 'gcc-5',   'x64' ) },
    22                                         gcc_5_x86: { trigger_build( 'gcc-5',   'x86' ) },
    23                                         clang_x64: { trigger_build( 'clang',   'x64' ) },
    24                                         clang_x86: { trigger_build( 'clang',   'x86' ) },
     19                                        gcc_6_x64: { trigger_build( 'gcc-6',   'x64', true  ) },
     20                                        gcc_6_x86: { trigger_build( 'gcc-6',   'x86', true  ) },
     21                                        gcc_5_x64: { trigger_build( 'gcc-5',   'x64', false ) },
     22                                        gcc_5_x86: { trigger_build( 'gcc-5',   'x86', false ) },
     23                                        gcc_4_x64: { trigger_build( 'gcc-4.9', 'x64', false ) },
     24                                        gcc_4_x86: { trigger_build( 'gcc-4.9', 'x86', false ) },
     25                                        clang_x64: { trigger_build( 'clang',   'x64', false ) },
     26                                        clang_x86: { trigger_build( 'clang',   'x86', false ) },
    2527                                )
    2628                        }
     29
     30                        //Push latest changes to do-lang repo
     31                        push_build()
    2732                }
    28 
    29                 promote_email(true)
    3033        }
    3134
     
    4245
    4346                //Send email to notify the failure
    44                 promote_email(false)
     47                promote_failure_email()
    4548        }
    4649
     
    5659//===========================================================================================================
    5760
    58 def trigger_build(String cc, String arch) {
     61def trigger_build(String cc, String arch, Boolean publish) {
    5962        def result = build job: 'Cforall/master',               \
    6063                parameters: [                                           \
    6164                        [$class: 'StringParameterValue',                \
    62                           name: 'Compiler',                             \
     65                          name: 'pCompiler',                            \
    6366                          value: cc],                                   \
    6467                        [$class: 'StringParameterValue',                \
    65                           name: 'Architecture',                         \
     68                          name: 'pArchitecture',                        \
    6669                          value: arch],                                 \
    6770                        [$class: 'BooleanParameterValue',               \
    68                           name: 'RunAllTests',                          \
     71                          name: 'pRunAllTests',                         \
    6972                          value: true],                                         \
    7073                        [$class: 'BooleanParameterValue',               \
    71                           name: 'RunBenchmark',                         \
     74                          name: 'pRunBenchmark',                        \
    7275                          value: true],                                         \
    7376                        [$class: 'BooleanParameterValue',               \
    74                           name: 'BuildDocumentation',           \
     77                          name: 'pBuildDocumentation',          \
    7578                          value: true],                                         \
    7679                        [$class: 'BooleanParameterValue',               \
    77                           name: 'Publish',                              \
    78                           value: true],                                 \
     80                          name: 'pPublish',                             \
     81                          value: publish],                                      \
    7982                        [$class: 'BooleanParameterValue',               \
    80                           name: 'Silent',                               \
     83                          name: 'pSilent',                              \
    8184                          value: true],                                         \
    8285                ],                                                              \
     
    8689
    8790        if(result.result != 'SUCCESS') {
    88                 sh("wget -q -O - http://localhost:8084/jenkins/job/Cforall/job/master/${result.number}/consoleText")
     91                sh("wget -q -O - ${result.absoluteUrl}/consoleText")
    8992                error(result.result)
     93        }
     94}
     95
     96def push_build() {
     97        //Don't use the build_stage function which outputs the compiler
     98        stage('Push') {
     99
     100                status_prefix = 'Push'
     101
     102                def out_dir = pwd tmp: true
     103                sh "mkdir -p ${out_dir}"
     104
     105                //checkout the code to make sure this is a valid git repo
     106                checkout scm
     107
     108                collect_git_info()
     109
     110                //parse git logs to find what changed
     111                sh "git remote > ${out_dir}/GIT_REMOTE"
     112                git_remote = readFile("${out_dir}/GIT_REMOTE")
     113                remoteDoLangExists = git_remote.contains("DoLang")
     114
     115                if( !remoteDoLangExists ) {
     116                        sh 'git remote add DoLang git@gitlab.do-lang.org:internal/cfa-cc.git'
     117                }
     118
     119                //sh "GIT_SSH_COMMAND=\"ssh -v\" git push DoLang ${gitRefNewValue}:master"
     120                echo('BUILD NOT PUSH SINCE DO-LANG SERVER WAS DOWN')
    90121        }
    91122}
     
    112143
    113144//Email notification on a full build failure
    114 def promote_email(boolean success) {
     145def promote_failure_email() {
    115146        echo('notifying users')
    116 
    117         def result = success ? "PROMOTE - SUCCESS" : "PROMOTE - FAILURE"
    118147
    119148        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
    120149        //Configurations for email format
    121         def email_subject = "[cforall git][${result}]"
    122         def email_body = """<p>This is an automated email from the Jenkins build machine. It was
    123 generated following the result of the C\u2200 nightly build.</p>
     150        def email_subject = "[cforall git][PROMOTE - FAILURE]"
     151        def email_body = """This is an automated email from the Jenkins build machine. It was
     152generated because of a git hooks/post-receive script following
     153a ref change was pushed to the repository containing
     154the project "UNNAMED PROJECT".
    124155
    125 <p>Check console output at ${env.BUILD_URL} to view the results.</p>
     156Check console output at ${env.BUILD_URL} to view the results.
    126157
    127 <p>- Status --------------------------------------------------------------</p>
     158- Status --------------------------------------------------------------
    128159
    129 <p>${result}</p>
    130 
    131 <p>- Performance ---------------------------------------------------------</p>
    132 
    133 <img src="https://cforall.uwaterloo.ca/jenkins/job/Cforall/job/master/plot/Compilation/getPlot?index=0" >
    134 <img src="https://cforall.uwaterloo.ca/jenkins/job/Cforall/job/master/plot/Compilation/getPlot?index=1" >
    135 
    136 <p>- Logs ----------------------------------------------------------------</p>
     160PROMOTE FAILURE
    137161"""
    138162
     
    140164
    141165        //send email notification
    142         emailext body: email_body, subject: email_subject, to: email_to, attachLog: !success
     166        emailext body: email_body, subject: email_subject, to: email_to, attachLog: true
    143167}
  • Jenkins/TestRegen

    rb067d9b r7951100  
    7070        //escapes the sandbox
    7171        //Also specify the compiler by hand
    72         sh "./configure CXX=clang++ CC=gcc-6 --host=${arch} --enable-silent-rules --quiet"
     72        sh "./configure CXX=clang++ --host=${arch} --with-backend-compiler=gcc-6 --prefix=${install_dir} --enable-silent-rules --quiet"
    7373
    7474        //Compile the project
    75         sh 'make -j 8 --no-print-directory'
     75        sh 'make -j 8 --no-print-directory install'
    7676
    7777        //Regenerate the desired tests
  • Jenkinsfile

    rb067d9b r7951100  
    11#!groovy
    22
    3 import groovy.transform.Field
    4 
    5 // For skipping stages
    6 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
    7 
    83//===========================================================================================================
    94// Main loop of the compilation
    105//===========================================================================================================
    11 
    12 node('master') {
    13         // Globals
    14         BuildDir  = pwd tmp: true
    15         SrcDir    = pwd tmp: false
    16         Settings  = null
    17         StageName = ''
    18 
    19         // Local variables
     6node ('master'){
     7
     8        boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox"
    209        def err = null
    2110        def log_needed = false
     11
     12        stage_name              = ''
     13
     14        compiler                = null
     15        arch_name               = ''
     16        architecture    = ''
     17
     18        do_alltests             = false
     19        do_benchmark    = false
     20        do_doc          = false
     21        do_publish              = false
     22        do_sendemail    = true
    2223
    2324        currentBuild.result = "SUCCESS"
     
    2728                wrap([$class: 'TimestamperBuildWrapper']) {
    2829
    29                         Settings = prepare_build()
    30 
    31                         node(Settings.Architecture.node) {
    32                                 BuildDir  = pwd tmp: true
    33                                 SrcDir    = pwd tmp: false
    34 
    35                                 clean()
    36 
    37                                 checkout()
    38 
    39                                 build()
    40 
    41                                 test()
    42 
    43                                 benchmark()
    44 
    45                                 build_doc()
    46 
    47                                 publish()
    48                         }
    49 
    50                         // Update the build directories when exiting the node
    51                         BuildDir  = pwd tmp: true
    52                         SrcDir    = pwd tmp: false
     30                        notify_server(0)
     31
     32                        prepare_build()
     33
     34                        checkout()
     35
     36                        notify_server(0)
     37
     38                        build()
     39
     40                        test()
     41
     42                        benchmark()
     43
     44                        clean()
     45
     46                        build_doc()
     47
     48                        publish()
     49
     50                        notify_server(45)
    5351                }
    5452        }
     
    6058                err = caughtError
    6159
    62                 echo err.toString()
    63 
    6460                //An error has occured, the build log is relevent
    6561                log_needed = true
    6662
    6763                //Store the result of the build log
    68                 currentBuild.result = "${StageName} FAILURE".trim()
     64                currentBuild.result = "${stage_name} FAILURE".trim()
    6965        }
    7066
    7167        finally {
    7268                //Send email with final results if this is not a full build
    73                 email(log_needed)
     69                if( do_sendemail && !bIsSandbox ) {
     70                        echo 'Notifying users of result'
     71                        email(currentBuild.result, log_needed)
     72                }
    7473
    7574                echo 'Build Completed'
     
    8180        }
    8281}
    83 //===========================================================================================================
    84 // Main compilation routines
    85 //===========================================================================================================
    86 def clean() {
    87         build_stage('Cleanup', true) {
    88                 // clean the build by wipping the build directory
    89                 dir(BuildDir) {
    90                         deleteDir()
    91                 }
    92         }
    93 }
    94 
    95 //Compilation script is done here but environnement set-up and error handling is done in main loop
    96 def checkout() {
    97         build_stage('Checkout', true) {
    98                 //checkout the source code and clean the repo
    99                 final scmVars = checkout scm
    100                 Settings.GitNewRef = scmVars.GIT_COMMIT
    101                 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
    102 
    103                 echo GitLogMessage()
    104         }
    105 }
    106 
    107 def build() {
    108         debug = true
    109         release = Settings.RunAllTests || Settings.RunBenchmark
    110         build_stage('Build : configure', true) {
    111                 // Build outside of the src tree to ease cleaning
    112                 dir (BuildDir) {
    113                         //Configure the conpilation (Output is not relevant)
    114                         //Use the current directory as the installation target so nothing escapes the sandbox
    115                         //Also specify the compiler by hand
    116                         targets=""
    117                         if( Settings.RunAllTests || Settings.RunBenchmark ) {
    118                                 targets="--with-target-hosts='host:debug,host:nodebug'"
    119                         } else {
    120                                 targets="--with-target-hosts='host:debug'"
    121                         }
    122 
    123                         sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
    124 
    125                         // Configure libcfa
    126                         sh 'make -j 8 --no-print-directory configure-libcfa'
    127                 }
    128         }
    129 
    130         build_stage('Build : cfa-cpp', true) {
    131                 // Build outside of the src tree to ease cleaning
    132                 dir (BuildDir) {
    133                         // Build driver
    134                         sh 'make -j 8 --no-print-directory -C driver'
    135 
    136                         // Build translator
    137                         sh 'make -j 8 --no-print-directory -C src'
    138                 }
    139         }
    140 
    141         build_stage('Build : libcfa(debug)', debug) {
    142                 // Build outside of the src tree to ease cleaning
    143                 dir (BuildDir) {
    144                         sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
    145                 }
    146         }
    147 
    148         build_stage('Build : libcfa(nodebug)', release) {
    149                 // Build outside of the src tree to ease cleaning
    150                 dir (BuildDir) {
    151                         sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
    152                 }
    153         }
    154 }
    155 
    156 def test() {
    157         try {
    158                 build_stage('Test: short', !Settings.RunAllTests) {
    159                         dir (BuildDir) {
    160                                 //Run the tests from the tests directory
    161                                 sh "make --no-print-directory -C tests archiveerrors=${BuildDir}/tests/crashes/short"
    162                         }
    163                 }
    164 
    165                 build_stage('Test: full', Settings.RunAllTests) {
    166                         dir (BuildDir) {
    167                                         //Run the tests from the tests directory
    168                                         sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
    169                                         sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
    170                         }
    171                 }
    172         }
    173         catch (Exception err) {
    174                 echo "Archiving core dumps"
    175                 dir (BuildDir) {
    176                         archiveArtifacts artifacts: "tests/crashes/**/*", fingerprint: true
    177                 }
    178                 throw err
    179         }
    180 }
    181 
    182 def benchmark() {
    183         build_stage('Benchmark', Settings.RunBenchmark) {
    184                 dir (BuildDir) {
    185                         //Append bench results
    186                         sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
    187                 }
    188         }
    189 }
    190 
    191 def build_doc() {
    192         build_stage('Documentation', Settings.BuildDocumentation) {
    193                 dir ('doc/user') {
    194                         make_doc()
    195                 }
    196 
    197                 dir ('doc/refrat') {
    198                         make_doc()
    199                 }
    200         }
    201 }
    202 
    203 def publish() {
    204         build_stage('Publish', true) {
    205 
    206                 if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
    207 
    208                 def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
    209                 def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
    210 
    211                 //Then publish the results
    212                 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile'       , groupCompile    , false, 'Compilation')
    213                 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff'  , groupCompile    , true , 'Compilation (relative)')
    214                 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch'     , groupConcurrency, false, 'Context Switching')
    215                 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff', groupConcurrency, true , 'Context Switching (relative)')
    216                 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex'         , groupConcurrency, false, 'Mutual Exclusion')
    217                 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff'    , groupConcurrency, true , 'Mutual Exclusion (relative)')
    218                 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal'        , groupConcurrency, false, 'Internal and External Scheduling')
    219                 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal.diff'   , groupConcurrency, true , 'Internal and External Scheduling (relative)')
    220         }
    221 }
    222 
    223 //===========================================================================================================
    224 //Routine responsible of sending the email notification once the build is completed
    225 //===========================================================================================================
    226 @NonCPS
    227 def SplitLines(String text) {
    228         def list = []
    229 
    230         text.eachLine {
    231                 list += it
    232         }
    233 
    234         return list
    235 }
    236 
    237 def GitLogMessage() {
    238         if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
    239 
    240         def oldRef = Settings.GitOldRef
    241         def newRef = Settings.GitNewRef
    242 
    243         def revText = sh(returnStdout: true, script: "git rev-list ${oldRef}..${newRef}").trim()
    244         def revList = SplitLines( revText )
    245 
    246         def gitUpdate = ""
    247         revList.each { rev ->
    248                 def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
    249                 gitUpdate = gitUpdate + "       via  ${rev} (${type})"
    250         }
    251 
    252         def rev = oldRef
    253         def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
    254         gitUpdate = gitUpdate + "      from  ${rev} (${type})"
    255 
    256         def gitLog    = sh(returnStdout: true, script: "git rev-list --format=short ${oldRef}...${newRef}").trim()
    257 
    258         def gitDiff   = sh(returnStdout: true, script: "git diff --stat --color ${newRef} ${oldRef}").trim()
    259         gitDiff = gitDiff.replace('[32m', '<span style="color: #00AA00;">')
    260         gitDiff = gitDiff.replace('[31m', '<span style="color: #AA0000;">')
    261         gitDiff = gitDiff.replace('[m', '</span>')
    262 
    263         return """
    264 <pre>
    265 The branch ${env.BRANCH_NAME} has been updated.
    266 ${gitUpdate}
    267 </pre>
    268 
    269 <p>Check console output at ${env.BUILD_URL} to view the results.</p>
    270 
    271 <p>- Status --------------------------------------------------------------</p>
    272 
    273 <p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
    274 
    275 <p>- Log -----------------------------------------------------------------</p>
    276 
    277 <pre>
    278 ${gitLog}
    279 </pre>
    280 
    281 <p>-----------------------------------------------------------------------</p>
    282 <pre>
    283 Summary of changes:
    284 ${gitDiff}
    285 </pre>
    286 """
    287 }
    288 
    289 //Standard build email notification
    290 def email(boolean log) {
    291         //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
    292         //Configurations for email format
    293         echo 'Notifying users of result'
    294 
    295         def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
    296         def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
    297         def email_body = """<p>This is an automated email from the Jenkins build machine. It was
    298 generated because of a git hooks/post-receive script following
    299 a ref change which was pushed to the C\u2200 repository.</p>
    300 """ + GitLogMessage()
    301 
    302         def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
    303 
    304         if( Settings && !Settings.Silent ) {
    305                 //send email notification
    306                 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
    307         } else {
    308                 echo "Would send email to: ${email_to}"
    309                 echo "With title: ${email_subject}"
    310                 echo "Content: \n${email_body}"
    311         }
    312 }
    31382
    31483//===========================================================================================================
    31584// Helper classes/variables/routines
    31685//===========================================================================================================
    317 //Description of a compiler (Must be serializable since pipelines are persistent)
    318 class CC_Desc implements Serializable {
    319         public String name
    320         public String CXX
    321         public String CC
    322 
    323         CC_Desc(String name, String CXX, String CC) {
    324                 this.name = name
    325                 this.CXX = CXX
    326                 this.CC = CC
    327         }
    328 }
    329 
    330 //Description of an architecture (Must be serializable since pipelines are persistent)
    331 class Arch_Desc implements Serializable {
    332         public String name
    333         public String flags
    334         public String node
    335 
    336         Arch_Desc(String name, String flags, String node) {
    337                 this.name  = name
    338                 this.flags = flags
    339                 this.node  = node
    340         }
    341 }
    342 
    343 class BuildSettings implements Serializable {
    344         public final CC_Desc Compiler
    345         public final Arch_Desc Architecture
    346         public final Boolean RunAllTests
    347         public final Boolean RunBenchmark
    348         public final Boolean BuildDocumentation
    349         public final Boolean Publish
    350         public final Boolean Silent
    351         public final Boolean IsSandbox
    352         public final String DescLong
    353         public final String DescShort
    354 
    355         public String GitNewRef
    356         public String GitOldRef
    357 
    358         BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
    359                 switch( param.Compiler ) {
    360                         case 'gcc-6':
    361                                 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
    362                         break
    363                         case 'gcc-5':
    364                                 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
    365                         break
    366                         case 'gcc-4.9':
    367                                 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
    368                         break
    369                         case 'clang':
    370                                 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
    371                         break
    372                         default :
    373                                 error "Unhandled compiler : ${cc}"
    374                 }
    375 
    376                 switch( param.Architecture ) {
    377                         case 'x64':
    378                                 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
    379                         break
    380                         case 'x86':
    381                                 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
    382                         break
    383                         default :
    384                                 error "Unhandled architecture : ${arch}"
    385                 }
    386 
    387                 this.IsSandbox          = (branch == "jenkins-sandbox")
    388                 this.RunAllTests        = param.RunAllTests
    389                 this.RunBenchmark       = param.RunBenchmark
    390                 this.BuildDocumentation = param.BuildDocumentation
    391                 this.Publish            = param.Publish
    392                 this.Silent             = param.Silent
    393 
    394                 def full = param.RunAllTests ? " (Full)" : ""
    395                 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
    396 
    397                 this.DescLong = """Compiler              : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
    398 Architecture            : ${ this.Architecture.name }
    399 Arc Flags               : ${ this.Architecture.flags }
    400 Run All Tests           : ${ this.RunAllTests.toString() }
    401 Run Benchmark           : ${ this.RunBenchmark.toString() }
    402 Build Documentation     : ${ this.BuildDocumentation.toString() }
    403 Publish                 : ${ this.Publish.toString() }
    404 Silent                  : ${ this.Silent.toString() }
    405 """
    406 
    407                 this.GitNewRef = ''
    408                 this.GitOldRef = ''
    409         }
    410 }
    411 
    412 class PlotGroup implements Serializable {
    413         public String name
    414         public String unit
    415         public boolean log
    416 
    417         PlotGroup(String name, String unit, boolean log) {
    418                 this.name = name
    419                 this.unit = unit
    420                 this.log = log
    421         }
     86//Helper routine to collect information about the git history
     87def collect_git_info() {
     88
     89        checkout scm
     90
     91        //create the temporary output directory in case it doesn't already exist
     92        def out_dir = pwd tmp: true
     93        sh "mkdir -p ${out_dir}"
     94
     95        //parse git logs to find what changed
     96        gitRefName = env.BRANCH_NAME
     97        sh "git reflog > ${out_dir}/GIT_COMMIT"
     98        git_reflog = readFile("${out_dir}/GIT_COMMIT")
     99        gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]
     100        gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2]
    422101}
    423102
    424103def prepare_build() {
    425         // prepare the properties
    426104        properties ([                                                                                                   \
    427105                [$class: 'ParametersDefinitionProperty',                                                                \
     
    429107                                [$class: 'ChoiceParameterDefinition',                                           \
    430108                                        description: 'Which compiler to use',                                   \
    431                                         name: 'Compiler',                                                                       \
     109                                        name: 'pCompiler',                                                              \
    432110                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
    433111                                        defaultValue: 'gcc-6',                                                          \
     
    435113                                [$class: 'ChoiceParameterDefinition',                                           \
    436114                                        description: 'The target architecture',                                 \
    437                                         name: 'Architecture',                                                           \
     115                                        name: 'pArchitecture',                                                          \
    438116                                        choices: 'x64\nx86',                                                            \
    439117                                        defaultValue: 'x64',                                                            \
     
    441119                                [$class: 'BooleanParameterDefinition',                                                  \
    442120                                        description: 'If false, only the quick test suite is ran',              \
    443                                         name: 'RunAllTests',                                                            \
     121                                        name: 'pRunAllTests',                                                           \
    444122                                        defaultValue: false,                                                            \
    445123                                ],                                                                                              \
    446124                                [$class: 'BooleanParameterDefinition',                                                  \
    447125                                        description: 'If true, jenkins also runs benchmarks',           \
    448                                         name: 'RunBenchmark',                                                           \
     126                                        name: 'pRunBenchmark',                                                          \
     127                                        defaultValue: true,                                                             \
     128                                ],                                                                                              \
     129                                [$class: 'BooleanParameterDefinition',                                                  \
     130                                        description: 'If true, jenkins also builds documentation',              \
     131                                        name: 'pBuildDocumentation',                                                    \
     132                                        defaultValue: true,                                                             \
     133                                ],                                                                                              \
     134                                [$class: 'BooleanParameterDefinition',                                                  \
     135                                        description: 'If true, jenkins also publishes results',                 \
     136                                        name: 'pPublish',                                                               \
    449137                                        defaultValue: false,                                                            \
    450                                 ],                                                                                              \
    451                                 [$class: 'BooleanParameterDefinition',                                                  \
    452                                         description: 'If true, jenkins also builds documentation',              \
    453                                         name: 'BuildDocumentation',                                                     \
    454                                         defaultValue: true,                                                             \
    455                                 ],                                                                                              \
    456                                 [$class: 'BooleanParameterDefinition',                                                  \
    457                                         description: 'If true, jenkins also publishes results',                 \
    458                                         name: 'Publish',                                                                        \
    459                                         defaultValue: false,                                                            \
    460138                                ],                                                                                              \
    461139                                [$class: 'BooleanParameterDefinition',                                                  \
    462140                                        description: 'If true, jenkins will not send emails',           \
    463                                         name: 'Silent',                                                                         \
     141                                        name: 'pSilent',                                                                        \
    464142                                        defaultValue: false,                                                            \
    465143                                ],                                                                                              \
     
    467145                ]])
    468146
    469         // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
    470         checkout scm
    471 
    472         final settings = new BuildSettings(params, env.BRANCH_NAME)
    473 
    474         currentBuild.description = settings.DescShort
    475         echo                       settings.DescLong
    476 
    477         return settings
    478 }
    479 
    480 def build_stage(String name, boolean run, Closure block ) {
    481         StageName = name
    482         echo " -------- ${StageName} -------- "
    483         if(run) {
    484                 stage(name, block)
    485         } else {
    486                 stage(name) { Utils.markStageSkippedForConditional(STAGE_NAME) }
    487         }
     147        compiler                = compiler_from_params( pCompiler )
     148        arch_name               = pArchitecture
     149        architecture    = architecture_from_params( arch_name )
     150
     151        do_alltests             = (pRunAllTests == 'true')
     152        do_benchmark    = (pRunBenchmark == 'true')
     153        do_doc          = (pBuildDocumentation == 'true')
     154        do_publish              = (pPublish == 'true')
     155        do_sendemail    = ! (pSilent == 'true')
     156
     157        echo """Compiler              : ${compiler.cc_name} (${compiler.cpp_cc}/${compiler.cfa_cc})
     158Architecture            : ${arch_name}
     159Arc Flags               : ${architecture}
     160Run All Tests           : ${ pRunAllTests.toString() }
     161Run Benchmark           : ${ pRunBenchmark.toString() }
     162Build Documentation     : ${ pBuildDocumentation.toString() }
     163Publish                 : ${ pPublish.toString() }
     164Silent                  : ${ pSilent.toString() }
     165"""
     166
     167        collect_git_info()
     168}
     169
     170def build_stage(String name, Closure block ) {
     171        stage_name = name
     172        stage(name, block)
     173}
     174
     175def notify_server(int wait) {
     176        sh """curl --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
     177        return
    488178}
    489179
     
    496186        catch (Exception caughtError) {
    497187                err = caughtError //rethrow error later
    498                 sh 'cat build/*.log'
     188                sh 'cat *.log'
    499189        }
    500190        finally {
     
    503193}
    504194
    505 def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
    506 
    507         if(new_data) {
    508                 echo "Publishing new data"
    509         }
    510 
    511         def series = new_data ? [[
    512                                 file: "${file}.csv",
    513                                 exclusionValues: '',
    514                                 displayTableFlag: false,
    515                                 inclusionFlag: 'OFF',
    516                                 url: ''
    517                         ]] : [];
    518 
    519         echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
    520         dir("${BuildDir}/benchmark/") {
    521                 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
    522                         csvSeries: series,
    523                         group: "${group.name}",
    524                         title: "${title}",
    525                         style: 'lineSimple',
    526                         exclZero: false,
    527                         keepRecords: false,
    528                         logarithmic: !relative && group.log,
    529                         numBuilds: '120',
    530                         useDescr: true,
    531                         yaxis: group.unit,
    532                         yaxisMaximum: '',
    533                         yaxisMinimum: ''
    534         }
    535 }
     195//Description of a compiler (Must be serializable since pipelines are persistent)
     196class CC_Desc implements Serializable {
     197        public String cc_name
     198        public String cpp_cc
     199        public String cfa_cc
     200
     201        CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
     202                this.cc_name = cc_name
     203                this.cpp_cc = cpp_cc
     204                this.cfa_cc = cfa_cc
     205        }
     206}
     207
     208def compiler_from_params(cc) {
     209        switch( cc ) {
     210                case 'gcc-6':
     211                        return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
     212                break
     213                case 'gcc-5':
     214                        return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
     215                break
     216                case 'gcc-4.9':
     217                        return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
     218                break
     219                case 'clang':
     220                        return new CC_Desc('clang', 'clang++', 'gcc-6')
     221                break
     222                default :
     223                        error "Unhandled compiler : ${cc}"
     224        }
     225}
     226
     227def architecture_from_params( arch ) {
     228        switch( arch ) {
     229                case 'x64':
     230                        return '--host=x86_64'
     231                break
     232                case 'x86':
     233                        return '--host=i386'
     234                break
     235                default :
     236                        error "Unhandled architecture : ${arch}"
     237        }
     238}
     239
     240//===========================================================================================================
     241// Main compilation routines
     242//===========================================================================================================
     243//Compilation script is done here but environnement set-up and error handling is done in main loop
     244def checkout() {
     245        build_stage('Checkout') {
     246                //checkout the source code and clean the repo
     247                checkout scm
     248
     249                //Clean all temporary files to make sure no artifacts of the previous build remain
     250                sh 'git clean -fdqx'
     251
     252                //Reset the git repo so no local changes persist
     253                sh 'git reset --hard'
     254        }
     255}
     256
     257def build() {
     258        build_stage('Build') {
     259
     260                def install_dir = pwd tmp: true
     261
     262                //Output compiler version to help with debug
     263                echo """C++ Compiler :"""
     264                sh "which ${compiler.cpp_cc} && ${compiler.cpp_cc} --version"
     265                echo """C   Compiler :"""
     266                sh "which ${compiler.cfa_cc} && ${compiler.cfa_cc} --version"
     267
     268                //Configure the conpilation (Output is not relevant)
     269                //Use the current directory as the installation target so nothing escapes the sandbox
     270                //Also specify the compiler by hand
     271                sh "./configure CXX=${compiler.cpp_cc} ${architecture} --with-backend-compiler=${compiler.cfa_cc} --prefix=${install_dir} --enable-silent-rules --quiet"
     272
     273                //Compile the project
     274                sh 'make -j 8 --no-print-directory V=0 install'
     275        }
     276}
     277
     278def test() {
     279        build_stage('Test') {
     280
     281                //Run the tests from the tests directory
     282                if ( do_alltests ) {
     283                        sh 'make -C src/tests all-tests debug=yes --no-print-directory'
     284                        sh 'make -C src/tests all-tests debug=no --no-print-directory'
     285                }
     286                else {
     287                        sh 'make -C src/tests --no-print-directory'
     288                }
     289        }
     290}
     291
     292def benchmark() {
     293        build_stage('Benchmark') {
     294
     295                if( !do_benchmark ) return
     296
     297                //Append bench results
     298                sh 'make -C src/benchmark --no-print-directory jenkins githash=' + gitRefNewValue + ' arch=' + arch_name + ' | tee bench.json'
     299        }
     300}
     301
     302def clean() {
     303        build_stage('Cleanup') {
     304
     305                //do a maintainer-clean to make sure we need to remake from scratch
     306                sh 'make maintainer-clean > /dev/null'
     307        }
     308}
     309
     310def build_doc() {
     311        build_stage('Documentation') {
     312
     313                if( !do_doc ) return
     314
     315                dir ('doc/user') {
     316                        make_doc()
     317                }
     318
     319                dir ('doc/refrat') {
     320                        make_doc()
     321                }
     322        }
     323}
     324
     325def publish() {
     326        build_stage('Publish') {
     327
     328                if( !do_publish ) return
     329
     330                //Then publish the results
     331                sh 'curl -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
     332        }
     333}
     334
     335//===========================================================================================================
     336//Routine responsible of sending the email notification once the build is completed
     337//===========================================================================================================
     338//Standard build email notification
     339def email(String status, boolean log) {
     340        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
     341        //Configurations for email format
     342        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
     343
     344        def gitLog = 'Error retrieving git logs'
     345        def gitDiff = 'Error retrieving git diff'
     346
     347        try {
     348
     349                sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG"
     350                gitLog = readFile('GIT_LOG')
     351
     352                sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF"
     353                gitDiff = readFile('GIT_DIFF')
     354        }
     355        catch (Exception error) {}
     356
     357        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
     358        def email_body = """This is an automated email from the Jenkins build machine. It was
     359generated because of a git hooks/post-receive script following
     360a ref change was pushed to the repository containing
     361the project "UNNAMED PROJECT".
     362
     363The branch ${env.BRANCH_NAME} has been updated.
     364   via  ${gitRefOldValue} (commit)
     365  from  ${gitRefNewValue} (commit)
     366
     367Check console output at ${env.BUILD_URL} to view the results.
     368
     369- Status --------------------------------------------------------------
     370
     371BUILD# ${env.BUILD_NUMBER} - ${status}
     372
     373- Log -----------------------------------------------------------------
     374${gitLog}
     375-----------------------------------------------------------------------
     376Summary of changes:
     377${gitDiff}
     378"""
     379
     380        def email_to = "cforall@lists.uwaterloo.ca"
     381
     382        //send email notification
     383        emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
     384}
  • Makefile.am

    rb067d9b r7951100  
    66## file "LICENCE" distributed with Cforall.
    77##
    8 ## Makefile.am --
     8## Makefile.am -- 
    99##
    1010## Author           : Peter A. Buhr
    1111## Created On       : Sun May 31 22:14:18 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Sat Feb  2 16:54:42 2019
    14 ## Update Count     : 21
     13## Last Modified On : Wed Dec 14 14:20:48 2016
     14## Update Count     : 15
    1515###############################################################################
    1616
    17 AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
    18 ACLOCAL_AMFLAGS  = -I automake
     17AUTOMAKE_OPTIONS = foreign              # do not require all the GNU file names
     18SUBDIRS = src/driver src src/prelude src/libcfa # order important, src before prelude because cfa-cpp used to build prelude
     19EXTRA_DIST = Docs                       # non-source files
     20BACKEND_CC = @BACKEND_CC@               # C compiler used to compile Cforall programs, versus C++ compiler used to build cfa command
    1921
    20 MAINTAINERCLEANFILES = lib/* bin/* tests/.deps/* tests/.out/* # order important
    21 
    22 SUBDIRS = driver src . @LIBCFA_TARGET_DIRS@
    23 
    24 @LIBCFA_TARGET_MAKEFILES@ : Makefile $(srcdir)/libcfa/configure
    25         @$(eval config_file = $(dir $@)config.data)
    26         @ls $(config_file) || (echo "Missing config.data, re-run configure script again" && false)
    27         @$(eval config_data = $(shell cat $(config_file)))
    28         @echo "Configuring libcfa with '$(config_data)''"
    29         @cd $(dir $@) && $(abs_top_srcdir)/libcfa/configure $(config_data)
    30 
    31 noinst_DATA = @LIBCFA_TARGET_MAKEFILES@
     22MAINTAINERCLEANFILES = lib/* bin/* src/examples/.deps/* src/tests/.deps/* src/tests/.out/*
    3223
    3324man1_MANS = doc/man/cfa.1
    34 
    35 debug=yes
    36 check:
    37         $(MAKE) -C tests all-tests installed=no debug=${debug}
    38 
    39 installcheck:
    40         $(MAKE) -C tests all-tests installed=yes debug=${debug}
    41 
    42 configure-libcfa: @LIBCFA_TARGET_MAKEFILES@
    43         @true
    44 
    45 status: @LIBCFA_TARGET_MAKEFILES@
    46         @echo -ne "translator\n\t"
    47         @./config.status --config | sed "s/ /\n\t/g; s/\t'/\t/g; s/'\n/\n/g; s/^'//g; s/'$$//g"
    48         @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"
  • Makefile.in

    rb067d9b r7951100  
    1717######################## -*- Mode: Makefile-Automake -*- ######################
    1818###############################################################################
    19 
    2019VPATH = @srcdir@
    2120am__is_gnu_make = { \
     
    9493subdir = .
    9594ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    96 am__aclocal_m4_deps = $(top_srcdir)/automake/libtool.m4 \
    97         $(top_srcdir)/automake/ltoptions.m4 \
    98         $(top_srcdir)/automake/ltsugar.m4 \
    99         $(top_srcdir)/automake/ltversion.m4 \
    100         $(top_srcdir)/automake/lt~obsolete.m4 \
    101         $(top_srcdir)/automake/cfa.m4 $(top_srcdir)/configure.ac
     95am__aclocal_m4_deps = $(top_srcdir)/configure.ac
    10296am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    10397        $(ACLOCAL_M4)
     
    168162NROFF = nroff
    169163MANS = $(man1_MANS)
    170 DATA = $(noinst_DATA)
    171164RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
    172165  distclean-recursive maintainer-clean-recursive
     
    177170AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
    178171        cscope distdir dist dist-all distcheck
    179 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
     172am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
     173        $(LISP)config.h.in
    180174# Read a list of newline-separated strings from the standard input,
    181175# and print each of them once, without duplicates.  Input order is
     
    198192CSCOPE = cscope
    199193DIST_SUBDIRS = $(SUBDIRS)
    200 am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/automake/compile \
     194am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
     195        $(top_srcdir)/automake/compile \
    201196        $(top_srcdir)/automake/config.guess \
    202197        $(top_srcdir)/automake/config.sub \
    203198        $(top_srcdir)/automake/install-sh \
    204         $(top_srcdir)/automake/ltmain.sh \
    205         $(top_srcdir)/automake/missing $(top_srcdir)/src/config.h.in \
    206         INSTALL README automake/compile automake/config.guess \
    207         automake/config.sub automake/depcomp automake/install-sh \
    208         automake/ltmain.sh automake/missing automake/ylwrap
     199        $(top_srcdir)/automake/missing INSTALL README automake/compile \
     200        automake/config.guess automake/config.sub automake/depcomp \
     201        automake/install-sh automake/missing automake/ylwrap
    209202DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    210203distdir = $(PACKAGE)-$(VERSION)
     
    250243distcleancheck_listfiles = find . -type f -print
    251244ACLOCAL = @ACLOCAL@
     245ALLOCA = @ALLOCA@
    252246AMTAR = @AMTAR@
    253247AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
    254 AR = @AR@
    255248AUTOCONF = @AUTOCONF@
    256249AUTOHEADER = @AUTOHEADER@
    257250AUTOMAKE = @AUTOMAKE@
    258251AWK = @AWK@
    259 BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
     252BACKEND_CC = @BACKEND_CC@               # C compiler used to compile Cforall programs, versus C++ compiler used to build cfa command
    260253CC = @CC@
    261254CCAS = @CCAS@
     
    263256CCASFLAGS = @CCASFLAGS@
    264257CCDEPMODE = @CCDEPMODE@
    265 CFACC = @CFACC@
    266 CFACC_INSTALL = @CFACC_INSTALL@
    267 CFACPP = @CFACPP@
    268258CFA_BACKEND_CC = @CFA_BACKEND_CC@
    269259CFA_BINDIR = @CFA_BINDIR@
     
    277267CPPFLAGS = @CPPFLAGS@
    278268CXX = @CXX@
    279 CXXCPP = @CXXCPP@
    280269CXXDEPMODE = @CXXDEPMODE@
    281270CXXFLAGS = @CXXFLAGS@
    282271CYGPATH_W = @CYGPATH_W@
    283272DEFS = @DEFS@
    284 DEMANGLER = @DEMANGLER@
    285273DEPDIR = @DEPDIR@
    286 DLLTOOL = @DLLTOOL@
    287 DRIVER_DIR = @DRIVER_DIR@
    288 DSYMUTIL = @DSYMUTIL@
    289 DUMPBIN = @DUMPBIN@
    290274ECHO_C = @ECHO_C@
    291275ECHO_N = @ECHO_N@
     
    293277EGREP = @EGREP@
    294278EXEEXT = @EXEEXT@
    295 FGREP = @FGREP@
    296279GREP = @GREP@
    297 HAS_DISTCC = @HAS_DISTCC@
    298 HOST_FLAGS = @HOST_FLAGS@
    299280INSTALL = @INSTALL@
    300281INSTALL_DATA = @INSTALL_DATA@
     
    302283INSTALL_SCRIPT = @INSTALL_SCRIPT@
    303284INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
    304 LD = @LD@
    305285LDFLAGS = @LDFLAGS@
    306286LEX = @LEX@
    307287LEXLIB = @LEXLIB@
    308288LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
    309 LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
    310 LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
    311 LIBDEMANGLE = @LIBDEMANGLE@
    312289LIBOBJS = @LIBOBJS@
    313290LIBS = @LIBS@
    314 LIBTOOL = @LIBTOOL@
    315 LIPO = @LIPO@
    316 LN_S = @LN_S@
    317291LTLIBOBJS = @LTLIBOBJS@
    318 LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
     292MACHINE_TYPE = @MACHINE_TYPE@
     293MAINT = @MAINT@
    319294MAKEINFO = @MAKEINFO@
    320 MANIFEST_TOOL = @MANIFEST_TOOL@
    321295MKDIR_P = @MKDIR_P@
    322 NM = @NM@
    323 NMEDIT = @NMEDIT@
    324 OBJDUMP = @OBJDUMP@
    325296OBJEXT = @OBJEXT@
    326 OTOOL = @OTOOL@
    327 OTOOL64 = @OTOOL64@
    328297PACKAGE = @PACKAGE@
    329298PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    335304PATH_SEPARATOR = @PATH_SEPARATOR@
    336305RANLIB = @RANLIB@
    337 SED = @SED@
    338306SET_MAKE = @SET_MAKE@
    339307SHELL = @SHELL@
    340308STRIP = @STRIP@
    341 TARGET_HOSTS = @TARGET_HOSTS@
    342309VERSION = @VERSION@
    343310YACC = @YACC@
     
    347314abs_top_builddir = @abs_top_builddir@
    348315abs_top_srcdir = @abs_top_srcdir@
    349 ac_ct_AR = @ac_ct_AR@
    350316ac_ct_CC = @ac_ct_CC@
    351317ac_ct_CXX = @ac_ct_CXX@
    352 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    353318am__include = @am__include@
    354319am__leading_dot = @am__leading_dot@
     
    397362top_builddir = @top_builddir@
    398363top_srcdir = @top_srcdir@
    399 AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
    400 ACLOCAL_AMFLAGS = -I automake
    401 MAINTAINERCLEANFILES = lib/* bin/* tests/.deps/* tests/.out/* # order important
    402 SUBDIRS = driver src . @LIBCFA_TARGET_DIRS@
    403 noinst_DATA = @LIBCFA_TARGET_MAKEFILES@
     364AUTOMAKE_OPTIONS = foreign              # do not require all the GNU file names
     365SUBDIRS = src/driver src src/prelude src/libcfa # order important, src before prelude because cfa-cpp used to build prelude
     366EXTRA_DIST = Docs                       # non-source files
     367MAINTAINERCLEANFILES = lib/* bin/* src/examples/.deps/* src/tests/.deps/* src/tests/.out/*
    404368man1_MANS = doc/man/cfa.1
    405 debug = yes
    406369all: config.h
    407370        $(MAKE) $(AM_MAKEFLAGS) all-recursive
     
    410373am--refresh: Makefile
    411374        @:
    412 $(srcdir)/Makefile.in: $(srcdir)/Makefile.am  $(am__configure_deps)
     375$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
    413376        @for dep in $?; do \
    414377          case '$(am__configure_deps)' in \
     
    436399        $(SHELL) ./config.status --recheck
    437400
    438 $(top_srcdir)/configure: $(am__configure_deps)
     401$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
    439402        $(am__cd) $(srcdir) && $(AUTOCONF)
    440 $(ACLOCAL_M4): $(am__aclocal_m4_deps)
     403$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
    441404        $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
    442405$(am__aclocal_m4_deps):
     
    446409        @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
    447410
    448 stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
     411stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
    449412        @rm -f stamp-h1
    450413        cd $(top_builddir) && $(SHELL) ./config.status config.h
    451 $(top_srcdir)/src/config.h.in: $(am__configure_deps)
     414$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
    452415        ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
    453416        rm -f stamp-h1
     
    456419distclean-hdr:
    457420        -rm -f config.h stamp-h1
    458 
    459 mostlyclean-libtool:
    460         -rm -f *.lo
    461 
    462 clean-libtool:
    463         -rm -rf .libs _libs
    464 
    465 distclean-libtool:
    466         -rm -f libtool config.lt
    467421install-man1: $(man1_MANS)
    468422        @$(NORMAL_INSTALL)
     
    803757check-am: all-am
    804758check: check-recursive
    805 all-am: Makefile $(MANS) $(DATA) config.h
     759all-am: Makefile $(MANS) config.h
    806760installdirs: installdirs-recursive
    807761installdirs-am:
     
    816770install-am: all-am
    817771        @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
     772
     773installcheck: installcheck-recursive
    818774install-strip:
    819775        if test -z '$(STRIP)'; then \
     
    840796clean: clean-recursive
    841797
    842 clean-am: clean-generic clean-libtool mostlyclean-am
     798clean-am: clean-generic mostlyclean-am
    843799
    844800distclean: distclean-recursive
    845801        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
    846802        -rm -f Makefile
    847 distclean-am: clean-am distclean-generic distclean-hdr \
    848         distclean-libtool distclean-tags
     803distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
    849804
    850805dvi: dvi-recursive
     
    896851mostlyclean: mostlyclean-recursive
    897852
    898 mostlyclean-am: mostlyclean-generic mostlyclean-libtool
     853mostlyclean-am: mostlyclean-generic
    899854
    900855pdf: pdf-recursive
     
    914869.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
    915870        am--refresh check check-am clean clean-cscope clean-generic \
    916         clean-libtool cscope cscopelist-am ctags ctags-am dist \
    917         dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
    918         dist-xz dist-zip distcheck distclean distclean-generic \
    919         distclean-hdr distclean-libtool distclean-tags distcleancheck \
    920         distdir distuninstallcheck dvi dvi-am html html-am info \
    921         info-am install install-am install-data install-data-am \
    922         install-dvi install-dvi-am install-exec install-exec-am \
    923         install-html install-html-am install-info install-info-am \
    924         install-man install-man1 install-pdf install-pdf-am install-ps \
    925         install-ps-am install-strip installcheck installcheck-am \
    926         installdirs installdirs-am maintainer-clean \
    927         maintainer-clean-generic mostlyclean mostlyclean-generic \
    928         mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
    929         uninstall-am uninstall-man uninstall-man1
     871        cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
     872        dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
     873        distcheck distclean distclean-generic distclean-hdr \
     874        distclean-tags distcleancheck distdir distuninstallcheck dvi \
     875        dvi-am html html-am info info-am install install-am \
     876        install-data install-data-am install-dvi install-dvi-am \
     877        install-exec install-exec-am install-html install-html-am \
     878        install-info install-info-am install-man install-man1 \
     879        install-pdf install-pdf-am install-ps install-ps-am \
     880        install-strip installcheck installcheck-am installdirs \
     881        installdirs-am maintainer-clean maintainer-clean-generic \
     882        mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
     883        tags-am uninstall uninstall-am uninstall-man uninstall-man1
    930884
    931885.PRECIOUS: Makefile
    932886
    933 
    934 @LIBCFA_TARGET_MAKEFILES@ : Makefile $(srcdir)/libcfa/configure
    935         @$(eval config_file = $(dir $@)config.data)
    936         @ls $(config_file) || (echo "Missing config.data, re-run configure script again" && false)
    937         @$(eval config_data = $(shell cat $(config_file)))
    938         @echo "Configuring libcfa with '$(config_data)''"
    939         @cd $(dir $@) && $(abs_top_srcdir)/libcfa/configure $(config_data)
    940 check:
    941         $(MAKE) -C tests all-tests installed=no debug=${debug}
    942 
    943 installcheck:
    944         $(MAKE) -C tests all-tests installed=yes debug=${debug}
    945 
    946 configure-libcfa: @LIBCFA_TARGET_MAKEFILES@
    947         @true
    948 
    949 status: @LIBCFA_TARGET_MAKEFILES@
    950         @echo -ne "translator\n\t"
    951         @./config.status --config | sed "s/ /\n\t/g; s/\t'/\t/g; s/'\n/\n/g; s/^'//g; s/'$$//g"
    952         @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"
    953887
    954888# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • aclocal.m4

    rb067d9b r7951100  
    127127# Expand $ac_aux_dir to an absolute path.
    128128am_aux_dir=`cd "$ac_aux_dir" && pwd`
     129])
     130
     131# AM_COND_IF                                            -*- Autoconf -*-
     132
     133# Copyright (C) 2008-2014 Free Software Foundation, Inc.
     134#
     135# This file is free software; the Free Software Foundation
     136# gives unlimited permission to copy and/or distribute it,
     137# with or without modifications, as long as this notice is preserved.
     138
     139# _AM_COND_IF
     140# _AM_COND_ELSE
     141# _AM_COND_ENDIF
     142# --------------
     143# These macros are only used for tracing.
     144m4_define([_AM_COND_IF])
     145m4_define([_AM_COND_ELSE])
     146m4_define([_AM_COND_ENDIF])
     147
     148# AM_COND_IF(COND, [IF-TRUE], [IF-FALSE])
     149# ---------------------------------------
     150# If the shell condition COND is true, execute IF-TRUE, otherwise execute
     151# IF-FALSE.  Allow automake to learn about conditional instantiating macros
     152# (the AC_CONFIG_FOOS).
     153AC_DEFUN([AM_COND_IF],
     154[m4_ifndef([_AM_COND_VALUE_$1],
     155           [m4_fatal([$0: no such condition "$1"])])dnl
     156_AM_COND_IF([$1])dnl
     157if test -z "$$1_TRUE"; then :
     158  m4_n([$2])[]dnl
     159m4_ifval([$3],
     160[_AM_COND_ELSE([$1])dnl
     161else
     162  $3
     163])dnl
     164_AM_COND_ENDIF([$1])dnl
     165fi[]dnl
    129166])
    130167
     
    666703AC_SUBST([am__leading_dot])])
    667704
     705# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
     706# From Jim Meyering
     707
     708# Copyright (C) 1996-2014 Free Software Foundation, Inc.
     709#
     710# This file is free software; the Free Software Foundation
     711# gives unlimited permission to copy and/or distribute it,
     712# with or without modifications, as long as this notice is preserved.
     713
     714# AM_MAINTAINER_MODE([DEFAULT-MODE])
     715# ----------------------------------
     716# Control maintainer-specific portions of Makefiles.
     717# Default is to disable them, unless 'enable' is passed literally.
     718# For symmetry, 'disable' may be passed as well.  Anyway, the user
     719# can override the default with the --enable/--disable switch.
     720AC_DEFUN([AM_MAINTAINER_MODE],
     721[m4_case(m4_default([$1], [disable]),
     722       [enable], [m4_define([am_maintainer_other], [disable])],
     723       [disable], [m4_define([am_maintainer_other], [enable])],
     724       [m4_define([am_maintainer_other], [enable])
     725        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
     726AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
     727  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
     728  AC_ARG_ENABLE([maintainer-mode],
     729    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
     730      am_maintainer_other[ make rules and dependencies not useful
     731      (and sometimes confusing) to the casual installer])],
     732    [USE_MAINTAINER_MODE=$enableval],
     733    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
     734  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
     735  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
     736  MAINT=$MAINTAINER_MODE_TRUE
     737  AC_SUBST([MAINT])dnl
     738]
     739)
     740
    668741# Check to see how 'make' treats includes.                  -*- Autoconf -*-
    669742
     
    11711244]) # _AM_PROG_TAR
    11721245
    1173 m4_include([automake/libtool.m4])
    1174 m4_include([automake/ltoptions.m4])
    1175 m4_include([automake/ltsugar.m4])
    1176 m4_include([automake/ltversion.m4])
    1177 m4_include([automake/lt~obsolete.m4])
  • automake/compile

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/compile
     1#! /bin/sh
     2# Wrapper for compilers which do not understand '-c -o'.
     3
     4scriptversion=2012-10-14.11; # UTC
     5
     6# Copyright (C) 1999-2014 Free Software Foundation, Inc.
     7# Written by Tom Tromey <tromey@cygnus.com>.
     8#
     9# This program is free software; you can redistribute it and/or modify
     10# it under the terms of the GNU General Public License as published by
     11# the Free Software Foundation; either version 2, or (at your option)
     12# any later version.
     13#
     14# This program is distributed in the hope that it will be useful,
     15# but WITHOUT ANY WARRANTY; without even the implied warranty of
     16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17# GNU General Public License for more details.
     18#
     19# You should have received a copy of the GNU General Public License
     20# along with this program.  If not, see <http://www.gnu.org/licenses/>.
     21
     22# As a special exception to the GNU General Public License, if you
     23# distribute this file as part of a program that contains a
     24# configuration script generated by Autoconf, you may include it under
     25# the same distribution terms that you use for the rest of that program.
     26
     27# This file is maintained in Automake, please report
     28# bugs to <bug-automake@gnu.org> or send patches to
     29# <automake-patches@gnu.org>.
     30
     31nl='
     32'
     33
     34# We need space, tab and new line, in precisely that order.  Quoting is
     35# there to prevent tools from complaining about whitespace usage.
     36IFS=" ""        $nl"
     37
     38file_conv=
     39
     40# func_file_conv build_file lazy
     41# Convert a $build file to $host form and store it in $file
     42# Currently only supports Windows hosts. If the determined conversion
     43# type is listed in (the comma separated) LAZY, no conversion will
     44# take place.
     45func_file_conv ()
     46{
     47  file=$1
     48  case $file in
     49    / | /[!/]*) # absolute file, and not a UNC file
     50      if test -z "$file_conv"; then
     51        # lazily determine how to convert abs files
     52        case `uname -s` in
     53          MINGW*)
     54            file_conv=mingw
     55            ;;
     56          CYGWIN*)
     57            file_conv=cygwin
     58            ;;
     59          *)
     60            file_conv=wine
     61            ;;
     62        esac
     63      fi
     64      case $file_conv/,$2, in
     65        *,$file_conv,*)
     66          ;;
     67        mingw/*)
     68          file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
     69          ;;
     70        cygwin/*)
     71          file=`cygpath -m "$file" || echo "$file"`
     72          ;;
     73        wine/*)
     74          file=`winepath -w "$file" || echo "$file"`
     75          ;;
     76      esac
     77      ;;
     78  esac
     79}
     80
     81# func_cl_dashL linkdir
     82# Make cl look for libraries in LINKDIR
     83func_cl_dashL ()
     84{
     85  func_file_conv "$1"
     86  if test -z "$lib_path"; then
     87    lib_path=$file
     88  else
     89    lib_path="$lib_path;$file"
     90  fi
     91  linker_opts="$linker_opts -LIBPATH:$file"
     92}
     93
     94# func_cl_dashl library
     95# Do a library search-path lookup for cl
     96func_cl_dashl ()
     97{
     98  lib=$1
     99  found=no
     100  save_IFS=$IFS
     101  IFS=';'
     102  for dir in $lib_path $LIB
     103  do
     104    IFS=$save_IFS
     105    if $shared && test -f "$dir/$lib.dll.lib"; then
     106      found=yes
     107      lib=$dir/$lib.dll.lib
     108      break
     109    fi
     110    if test -f "$dir/$lib.lib"; then
     111      found=yes
     112      lib=$dir/$lib.lib
     113      break
     114    fi
     115    if test -f "$dir/lib$lib.a"; then
     116      found=yes
     117      lib=$dir/lib$lib.a
     118      break
     119    fi
     120  done
     121  IFS=$save_IFS
     122
     123  if test "$found" != yes; then
     124    lib=$lib.lib
     125  fi
     126}
     127
     128# func_cl_wrapper cl arg...
     129# Adjust compile command to suit cl
     130func_cl_wrapper ()
     131{
     132  # Assume a capable shell
     133  lib_path=
     134  shared=:
     135  linker_opts=
     136  for arg
     137  do
     138    if test -n "$eat"; then
     139      eat=
     140    else
     141      case $1 in
     142        -o)
     143          # configure might choose to run compile as 'compile cc -o foo foo.c'.
     144          eat=1
     145          case $2 in
     146            *.o | *.[oO][bB][jJ])
     147              func_file_conv "$2"
     148              set x "$@" -Fo"$file"
     149              shift
     150              ;;
     151            *)
     152              func_file_conv "$2"
     153              set x "$@" -Fe"$file"
     154              shift
     155              ;;
     156          esac
     157          ;;
     158        -I)
     159          eat=1
     160          func_file_conv "$2" mingw
     161          set x "$@" -I"$file"
     162          shift
     163          ;;
     164        -I*)
     165          func_file_conv "${1#-I}" mingw
     166          set x "$@" -I"$file"
     167          shift
     168          ;;
     169        -l)
     170          eat=1
     171          func_cl_dashl "$2"
     172          set x "$@" "$lib"
     173          shift
     174          ;;
     175        -l*)
     176          func_cl_dashl "${1#-l}"
     177          set x "$@" "$lib"
     178          shift
     179          ;;
     180        -L)
     181          eat=1
     182          func_cl_dashL "$2"
     183          ;;
     184        -L*)
     185          func_cl_dashL "${1#-L}"
     186          ;;
     187        -static)
     188          shared=false
     189          ;;
     190        -Wl,*)
     191          arg=${1#-Wl,}
     192          save_ifs="$IFS"; IFS=','
     193          for flag in $arg; do
     194            IFS="$save_ifs"
     195            linker_opts="$linker_opts $flag"
     196          done
     197          IFS="$save_ifs"
     198          ;;
     199        -Xlinker)
     200          eat=1
     201          linker_opts="$linker_opts $2"
     202          ;;
     203        -*)
     204          set x "$@" "$1"
     205          shift
     206          ;;
     207        *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
     208          func_file_conv "$1"
     209          set x "$@" -Tp"$file"
     210          shift
     211          ;;
     212        *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
     213          func_file_conv "$1" mingw
     214          set x "$@" "$file"
     215          shift
     216          ;;
     217        *)
     218          set x "$@" "$1"
     219          shift
     220          ;;
     221      esac
     222    fi
     223    shift
     224  done
     225  if test -n "$linker_opts"; then
     226    linker_opts="-link$linker_opts"
     227  fi
     228  exec "$@" $linker_opts
     229  exit 1
     230}
     231
     232eat=
     233
     234case $1 in
     235  '')
     236     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
     237     exit 1;
     238     ;;
     239  -h | --h*)
     240    cat <<\EOF
     241Usage: compile [--help] [--version] PROGRAM [ARGS]
     242
     243Wrapper for compilers which do not understand '-c -o'.
     244Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
     245arguments, and rename the output as expected.
     246
     247If you are trying to build a whole package this is not the
     248right script to run: please start by reading the file 'INSTALL'.
     249
     250Report bugs to <bug-automake@gnu.org>.
     251EOF
     252    exit $?
     253    ;;
     254  -v | --v*)
     255    echo "compile $scriptversion"
     256    exit $?
     257    ;;
     258  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
     259    func_cl_wrapper "$@"      # Doesn't return...
     260    ;;
     261esac
     262
     263ofile=
     264cfile=
     265
     266for arg
     267do
     268  if test -n "$eat"; then
     269    eat=
     270  else
     271    case $1 in
     272      -o)
     273        # configure might choose to run compile as 'compile cc -o foo foo.c'.
     274        # So we strip '-o arg' only if arg is an object.
     275        eat=1
     276        case $2 in
     277          *.o | *.obj)
     278            ofile=$2
     279            ;;
     280          *)
     281            set x "$@" -o "$2"
     282            shift
     283            ;;
     284        esac
     285        ;;
     286      *.c)
     287        cfile=$1
     288        set x "$@" "$1"
     289        shift
     290        ;;
     291      *)
     292        set x "$@" "$1"
     293        shift
     294        ;;
     295    esac
     296  fi
     297  shift
     298done
     299
     300if test -z "$ofile" || test -z "$cfile"; then
     301  # If no '-o' option was seen then we might have been invoked from a
     302  # pattern rule where we don't need one.  That is ok -- this is a
     303  # normal compilation that the losing compiler can handle.  If no
     304  # '.c' file was seen then we are probably linking.  That is also
     305  # ok.
     306  exec "$@"
     307fi
     308
     309# Name of file we expect compiler to create.
     310cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
     311
     312# Create the lock directory.
     313# Note: use '[/\\:.-]' here to ensure that we don't use the same name
     314# that we are using for the .o file.  Also, base the name on the expected
     315# object file name, since that is what matters with a parallel build.
     316lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
     317while true; do
     318  if mkdir "$lockdir" >/dev/null 2>&1; then
     319    break
     320  fi
     321  sleep 1
     322done
     323# FIXME: race condition here if user kills between mkdir and trap.
     324trap "rmdir '$lockdir'; exit 1" 1 2 15
     325
     326# Run the compile.
     327"$@"
     328ret=$?
     329
     330if test -f "$cofile"; then
     331  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
     332elif test -f "${cofile}bj"; then
     333  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
     334fi
     335
     336rmdir "$lockdir"
     337exit $ret
     338
     339# Local Variables:
     340# mode: shell-script
     341# sh-indentation: 2
     342# eval: (add-hook 'write-file-hooks 'time-stamp)
     343# time-stamp-start: "scriptversion="
     344# time-stamp-format: "%:y-%02m-%02d.%02H"
     345# time-stamp-time-zone: "UTC"
     346# time-stamp-end: "; # UTC"
     347# End:
  • automake/config.guess

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/config.guess
     1#! /bin/sh
     2# Attempt to guess a canonical system name.
     3#   Copyright 1992-2015 Free Software Foundation, Inc.
     4
     5timestamp='2015-08-20'
     6
     7# This file is free software; you can redistribute it and/or modify it
     8# under the terms of the GNU General Public License as published by
     9# the Free Software Foundation; either version 3 of the License, or
     10# (at your option) any later version.
     11#
     12# This program is distributed in the hope that it will be useful, but
     13# WITHOUT ANY WARRANTY; without even the implied warranty of
     14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15# General Public License for more details.
     16#
     17# You should have received a copy of the GNU General Public License
     18# along with this program; if not, see <http://www.gnu.org/licenses/>.
     19#
     20# As a special exception to the GNU General Public License, if you
     21# distribute this file as part of a program that contains a
     22# configuration script generated by Autoconf, you may include it under
     23# the same distribution terms that you use for the rest of that
     24# program.  This Exception is an additional permission under section 7
     25# of the GNU General Public License, version 3 ("GPLv3").
     26#
     27# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
     28#
     29# You can get the latest version of this script from:
     30# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
     31#
     32# Please send patches to <config-patches@gnu.org>.
     33
     34
     35me=`echo "$0" | sed -e 's,.*/,,'`
     36
     37usage="\
     38Usage: $0 [OPTION]
     39
     40Output the configuration name of the system \`$me' is run on.
     41
     42Operation modes:
     43  -h, --help         print this help, then exit
     44  -t, --time-stamp   print date of last modification, then exit
     45  -v, --version      print version number, then exit
     46
     47Report bugs and patches to <config-patches@gnu.org>."
     48
     49version="\
     50GNU config.guess ($timestamp)
     51
     52Originally written by Per Bothner.
     53Copyright 1992-2015 Free Software Foundation, Inc.
     54
     55This is free software; see the source for copying conditions.  There is NO
     56warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
     57
     58help="
     59Try \`$me --help' for more information."
     60
     61# Parse command line
     62while test $# -gt 0 ; do
     63  case $1 in
     64    --time-stamp | --time* | -t )
     65       echo "$timestamp" ; exit ;;
     66    --version | -v )
     67       echo "$version" ; exit ;;
     68    --help | --h* | -h )
     69       echo "$usage"; exit ;;
     70    -- )     # Stop option processing
     71       shift; break ;;
     72    - ) # Use stdin as input.
     73       break ;;
     74    -* )
     75       echo "$me: invalid option $1$help" >&2
     76       exit 1 ;;
     77    * )
     78       break ;;
     79  esac
     80done
     81
     82if test $# != 0; then
     83  echo "$me: too many arguments$help" >&2
     84  exit 1
     85fi
     86
     87trap 'exit 1' 1 2 15
     88
     89# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
     90# compiler to aid in system detection is discouraged as it requires
     91# temporary files to be created and, as you can see below, it is a
     92# headache to deal with in a portable fashion.
     93
     94# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
     95# use `HOST_CC' if defined, but it is deprecated.
     96
     97# Portable tmp directory creation inspired by the Autoconf team.
     98
     99set_cc_for_build='
     100trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
     101trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
     102: ${TMPDIR=/tmp} ;
     103 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
     104 { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
     105 { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
     106 { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
     107dummy=$tmp/dummy ;
     108tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
     109case $CC_FOR_BUILD,$HOST_CC,$CC in
     110 ,,)    echo "int x;" > $dummy.c ;
     111        for c in cc gcc c89 c99 ; do
     112          if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
     113             CC_FOR_BUILD="$c"; break ;
     114          fi ;
     115        done ;
     116        if test x"$CC_FOR_BUILD" = x ; then
     117          CC_FOR_BUILD=no_compiler_found ;
     118        fi
     119        ;;
     120 ,,*)   CC_FOR_BUILD=$CC ;;
     121 ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
     122esac ; set_cc_for_build= ;'
     123
     124# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
     125# (ghazi@noc.rutgers.edu 1994-08-24)
     126if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
     127        PATH=$PATH:/.attbin ; export PATH
     128fi
     129
     130UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
     131UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
     132UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
     133UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
     134
     135case "${UNAME_SYSTEM}" in
     136Linux|GNU|GNU/*)
     137        # If the system lacks a compiler, then just pick glibc.
     138        # We could probably try harder.
     139        LIBC=gnu
     140
     141        eval $set_cc_for_build
     142        cat <<-EOF > $dummy.c
     143        #include <features.h>
     144        #if defined(__UCLIBC__)
     145        LIBC=uclibc
     146        #elif defined(__dietlibc__)
     147        LIBC=dietlibc
     148        #else
     149        LIBC=gnu
     150        #endif
     151        EOF
     152        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
     153        ;;
     154esac
     155
     156# Note: order is significant - the case branches are not exclusive.
     157
     158case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     159    *:NetBSD:*:*)
     160        # NetBSD (nbsd) targets should (where applicable) match one or
     161        # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
     162        # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
     163        # switched to ELF, *-*-netbsd* would select the old
     164        # object file format.  This provides both forward
     165        # compatibility and a consistent mechanism for selecting the
     166        # object file format.
     167        #
     168        # Note: NetBSD doesn't particularly care about the vendor
     169        # portion of the name.  We always set it to "unknown".
     170        sysctl="sysctl -n hw.machine_arch"
     171        UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
     172            /sbin/$sysctl 2>/dev/null || \
     173            /usr/sbin/$sysctl 2>/dev/null || \
     174            echo unknown)`
     175        case "${UNAME_MACHINE_ARCH}" in
     176            armeb) machine=armeb-unknown ;;
     177            arm*) machine=arm-unknown ;;
     178            sh3el) machine=shl-unknown ;;
     179            sh3eb) machine=sh-unknown ;;
     180            sh5el) machine=sh5le-unknown ;;
     181            earmv*)
     182                arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
     183                endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
     184                machine=${arch}${endian}-unknown
     185                ;;
     186            *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
     187        esac
     188        # The Operating System including object format, if it has switched
     189        # to ELF recently, or will in the future.
     190        case "${UNAME_MACHINE_ARCH}" in
     191            arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
     192                eval $set_cc_for_build
     193                if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
     194                        | grep -q __ELF__
     195                then
     196                    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
     197                    # Return netbsd for either.  FIX?
     198                    os=netbsd
     199                else
     200                    os=netbsdelf
     201                fi
     202                ;;
     203            *)
     204                os=netbsd
     205                ;;
     206        esac
     207        # Determine ABI tags.
     208        case "${UNAME_MACHINE_ARCH}" in
     209            earm*)
     210                expr='s/^earmv[0-9]/-eabi/;s/eb$//'
     211                abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
     212                ;;
     213        esac
     214        # The OS release
     215        # Debian GNU/NetBSD machines have a different userland, and
     216        # thus, need a distinct triplet. However, they do not need
     217        # kernel version information, so it can be replaced with a
     218        # suitable tag, in the style of linux-gnu.
     219        case "${UNAME_VERSION}" in
     220            Debian*)
     221                release='-gnu'
     222                ;;
     223            *)
     224                release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
     225                ;;
     226        esac
     227        # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
     228        # contains redundant information, the shorter form:
     229        # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
     230        echo "${machine}-${os}${release}${abi}"
     231        exit ;;
     232    *:Bitrig:*:*)
     233        UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
     234        echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
     235        exit ;;
     236    *:OpenBSD:*:*)
     237        UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
     238        echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
     239        exit ;;
     240    *:ekkoBSD:*:*)
     241        echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
     242        exit ;;
     243    *:SolidBSD:*:*)
     244        echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
     245        exit ;;
     246    macppc:MirBSD:*:*)
     247        echo powerpc-unknown-mirbsd${UNAME_RELEASE}
     248        exit ;;
     249    *:MirBSD:*:*)
     250        echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
     251        exit ;;
     252    *:Sortix:*:*)
     253        echo ${UNAME_MACHINE}-unknown-sortix
     254        exit ;;
     255    alpha:OSF1:*:*)
     256        case $UNAME_RELEASE in
     257        *4.0)
     258                UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
     259                ;;
     260        *5.*)
     261                UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
     262                ;;
     263        esac
     264        # According to Compaq, /usr/sbin/psrinfo has been available on
     265        # OSF/1 and Tru64 systems produced since 1995.  I hope that
     266        # covers most systems running today.  This code pipes the CPU
     267        # types through head -n 1, so we only detect the type of CPU 0.
     268        ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
     269        case "$ALPHA_CPU_TYPE" in
     270            "EV4 (21064)")
     271                UNAME_MACHINE="alpha" ;;
     272            "EV4.5 (21064)")
     273                UNAME_MACHINE="alpha" ;;
     274            "LCA4 (21066/21068)")
     275                UNAME_MACHINE="alpha" ;;
     276            "EV5 (21164)")
     277                UNAME_MACHINE="alphaev5" ;;
     278            "EV5.6 (21164A)")
     279                UNAME_MACHINE="alphaev56" ;;
     280            "EV5.6 (21164PC)")
     281                UNAME_MACHINE="alphapca56" ;;
     282            "EV5.7 (21164PC)")
     283                UNAME_MACHINE="alphapca57" ;;
     284            "EV6 (21264)")
     285                UNAME_MACHINE="alphaev6" ;;
     286            "EV6.7 (21264A)")
     287                UNAME_MACHINE="alphaev67" ;;
     288            "EV6.8CB (21264C)")
     289                UNAME_MACHINE="alphaev68" ;;
     290            "EV6.8AL (21264B)")
     291                UNAME_MACHINE="alphaev68" ;;
     292            "EV6.8CX (21264D)")
     293                UNAME_MACHINE="alphaev68" ;;
     294            "EV6.9A (21264/EV69A)")
     295                UNAME_MACHINE="alphaev69" ;;
     296            "EV7 (21364)")
     297                UNAME_MACHINE="alphaev7" ;;
     298            "EV7.9 (21364A)")
     299                UNAME_MACHINE="alphaev79" ;;
     300        esac
     301        # A Pn.n version is a patched version.
     302        # A Vn.n version is a released version.
     303        # A Tn.n version is a released field test version.
     304        # A Xn.n version is an unreleased experimental baselevel.
     305        # 1.2 uses "1.2" for uname -r.
     306        echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
     307        # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
     308        exitcode=$?
     309        trap '' 0
     310        exit $exitcode ;;
     311    Alpha\ *:Windows_NT*:*)
     312        # How do we know it's Interix rather than the generic POSIX subsystem?
     313        # Should we change UNAME_MACHINE based on the output of uname instead
     314        # of the specific Alpha model?
     315        echo alpha-pc-interix
     316        exit ;;
     317    21064:Windows_NT:50:3)
     318        echo alpha-dec-winnt3.5
     319        exit ;;
     320    Amiga*:UNIX_System_V:4.0:*)
     321        echo m68k-unknown-sysv4
     322        exit ;;
     323    *:[Aa]miga[Oo][Ss]:*:*)
     324        echo ${UNAME_MACHINE}-unknown-amigaos
     325        exit ;;
     326    *:[Mm]orph[Oo][Ss]:*:*)
     327        echo ${UNAME_MACHINE}-unknown-morphos
     328        exit ;;
     329    *:OS/390:*:*)
     330        echo i370-ibm-openedition
     331        exit ;;
     332    *:z/VM:*:*)
     333        echo s390-ibm-zvmoe
     334        exit ;;
     335    *:OS400:*:*)
     336        echo powerpc-ibm-os400
     337        exit ;;
     338    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
     339        echo arm-acorn-riscix${UNAME_RELEASE}
     340        exit ;;
     341    arm*:riscos:*:*|arm*:RISCOS:*:*)
     342        echo arm-unknown-riscos
     343        exit ;;
     344    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
     345        echo hppa1.1-hitachi-hiuxmpp
     346        exit ;;
     347    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
     348        # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
     349        if test "`(/bin/universe) 2>/dev/null`" = att ; then
     350                echo pyramid-pyramid-sysv3
     351        else
     352                echo pyramid-pyramid-bsd
     353        fi
     354        exit ;;
     355    NILE*:*:*:dcosx)
     356        echo pyramid-pyramid-svr4
     357        exit ;;
     358    DRS?6000:unix:4.0:6*)
     359        echo sparc-icl-nx6
     360        exit ;;
     361    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
     362        case `/usr/bin/uname -p` in
     363            sparc) echo sparc-icl-nx7; exit ;;
     364        esac ;;
     365    s390x:SunOS:*:*)
     366        echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
     367        exit ;;
     368    sun4H:SunOS:5.*:*)
     369        echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
     370        exit ;;
     371    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
     372        echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
     373        exit ;;
     374    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
     375        echo i386-pc-auroraux${UNAME_RELEASE}
     376        exit ;;
     377    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
     378        eval $set_cc_for_build
     379        SUN_ARCH="i386"
     380        # If there is a compiler, see if it is configured for 64-bit objects.
     381        # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
     382        # This test works for both compilers.
     383        if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
     384            if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
     385                (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
     386                grep IS_64BIT_ARCH >/dev/null
     387            then
     388                SUN_ARCH="x86_64"
     389            fi
     390        fi
     391        echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
     392        exit ;;
     393    sun4*:SunOS:6*:*)
     394        # According to config.sub, this is the proper way to canonicalize
     395        # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
     396        # it's likely to be more like Solaris than SunOS4.
     397        echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
     398        exit ;;
     399    sun4*:SunOS:*:*)
     400        case "`/usr/bin/arch -k`" in
     401            Series*|S4*)
     402                UNAME_RELEASE=`uname -v`
     403                ;;
     404        esac
     405        # Japanese Language versions have a version number like `4.1.3-JL'.
     406        echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
     407        exit ;;
     408    sun3*:SunOS:*:*)
     409        echo m68k-sun-sunos${UNAME_RELEASE}
     410        exit ;;
     411    sun*:*:4.2BSD:*)
     412        UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
     413        test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
     414        case "`/bin/arch`" in
     415            sun3)
     416                echo m68k-sun-sunos${UNAME_RELEASE}
     417                ;;
     418            sun4)
     419                echo sparc-sun-sunos${UNAME_RELEASE}
     420                ;;
     421        esac
     422        exit ;;
     423    aushp:SunOS:*:*)
     424        echo sparc-auspex-sunos${UNAME_RELEASE}
     425        exit ;;
     426    # The situation for MiNT is a little confusing.  The machine name
     427    # can be virtually everything (everything which is not
     428    # "atarist" or "atariste" at least should have a processor
     429    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
     430    # to the lowercase version "mint" (or "freemint").  Finally
     431    # the system name "TOS" denotes a system which is actually not
     432    # MiNT.  But MiNT is downward compatible to TOS, so this should
     433    # be no problem.
     434    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
     435        echo m68k-atari-mint${UNAME_RELEASE}
     436        exit ;;
     437    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
     438        echo m68k-atari-mint${UNAME_RELEASE}
     439        exit ;;
     440    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
     441        echo m68k-atari-mint${UNAME_RELEASE}
     442        exit ;;
     443    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
     444        echo m68k-milan-mint${UNAME_RELEASE}
     445        exit ;;
     446    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
     447        echo m68k-hades-mint${UNAME_RELEASE}
     448        exit ;;
     449    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
     450        echo m68k-unknown-mint${UNAME_RELEASE}
     451        exit ;;
     452    m68k:machten:*:*)
     453        echo m68k-apple-machten${UNAME_RELEASE}
     454        exit ;;
     455    powerpc:machten:*:*)
     456        echo powerpc-apple-machten${UNAME_RELEASE}
     457        exit ;;
     458    RISC*:Mach:*:*)
     459        echo mips-dec-mach_bsd4.3
     460        exit ;;
     461    RISC*:ULTRIX:*:*)
     462        echo mips-dec-ultrix${UNAME_RELEASE}
     463        exit ;;
     464    VAX*:ULTRIX*:*:*)
     465        echo vax-dec-ultrix${UNAME_RELEASE}
     466        exit ;;
     467    2020:CLIX:*:* | 2430:CLIX:*:*)
     468        echo clipper-intergraph-clix${UNAME_RELEASE}
     469        exit ;;
     470    mips:*:*:UMIPS | mips:*:*:RISCos)
     471        eval $set_cc_for_build
     472        sed 's/^        //' << EOF >$dummy.c
     473#ifdef __cplusplus
     474#include <stdio.h>  /* for printf() prototype */
     475        int main (int argc, char *argv[]) {
     476#else
     477        int main (argc, argv) int argc; char *argv[]; {
     478#endif
     479        #if defined (host_mips) && defined (MIPSEB)
     480        #if defined (SYSTYPE_SYSV)
     481          printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
     482        #endif
     483        #if defined (SYSTYPE_SVR4)
     484          printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
     485        #endif
     486        #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
     487          printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
     488        #endif
     489        #endif
     490          exit (-1);
     491        }
     492EOF
     493        $CC_FOR_BUILD -o $dummy $dummy.c &&
     494          dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
     495          SYSTEM_NAME=`$dummy $dummyarg` &&
     496            { echo "$SYSTEM_NAME"; exit; }
     497        echo mips-mips-riscos${UNAME_RELEASE}
     498        exit ;;
     499    Motorola:PowerMAX_OS:*:*)
     500        echo powerpc-motorola-powermax
     501        exit ;;
     502    Motorola:*:4.3:PL8-*)
     503        echo powerpc-harris-powermax
     504        exit ;;
     505    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
     506        echo powerpc-harris-powermax
     507        exit ;;
     508    Night_Hawk:Power_UNIX:*:*)
     509        echo powerpc-harris-powerunix
     510        exit ;;
     511    m88k:CX/UX:7*:*)
     512        echo m88k-harris-cxux7
     513        exit ;;
     514    m88k:*:4*:R4*)
     515        echo m88k-motorola-sysv4
     516        exit ;;
     517    m88k:*:3*:R3*)
     518        echo m88k-motorola-sysv3
     519        exit ;;
     520    AViiON:dgux:*:*)
     521        # DG/UX returns AViiON for all architectures
     522        UNAME_PROCESSOR=`/usr/bin/uname -p`
     523        if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
     524        then
     525            if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
     526               [ ${TARGET_BINARY_INTERFACE}x = x ]
     527            then
     528                echo m88k-dg-dgux${UNAME_RELEASE}
     529            else
     530                echo m88k-dg-dguxbcs${UNAME_RELEASE}
     531            fi
     532        else
     533            echo i586-dg-dgux${UNAME_RELEASE}
     534        fi
     535        exit ;;
     536    M88*:DolphinOS:*:*) # DolphinOS (SVR3)
     537        echo m88k-dolphin-sysv3
     538        exit ;;
     539    M88*:*:R3*:*)
     540        # Delta 88k system running SVR3
     541        echo m88k-motorola-sysv3
     542        exit ;;
     543    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
     544        echo m88k-tektronix-sysv3
     545        exit ;;
     546    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
     547        echo m68k-tektronix-bsd
     548        exit ;;
     549    *:IRIX*:*:*)
     550        echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
     551        exit ;;
     552    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
     553        echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
     554        exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
     555    i*86:AIX:*:*)
     556        echo i386-ibm-aix
     557        exit ;;
     558    ia64:AIX:*:*)
     559        if [ -x /usr/bin/oslevel ] ; then
     560                IBM_REV=`/usr/bin/oslevel`
     561        else
     562                IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
     563        fi
     564        echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
     565        exit ;;
     566    *:AIX:2:3)
     567        if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
     568                eval $set_cc_for_build
     569                sed 's/^                //' << EOF >$dummy.c
     570                #include <sys/systemcfg.h>
     571
     572                main()
     573                        {
     574                        if (!__power_pc())
     575                                exit(1);
     576                        puts("powerpc-ibm-aix3.2.5");
     577                        exit(0);
     578                        }
     579EOF
     580                if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
     581                then
     582                        echo "$SYSTEM_NAME"
     583                else
     584                        echo rs6000-ibm-aix3.2.5
     585                fi
     586        elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
     587                echo rs6000-ibm-aix3.2.4
     588        else
     589                echo rs6000-ibm-aix3.2
     590        fi
     591        exit ;;
     592    *:AIX:*:[4567])
     593        IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
     594        if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
     595                IBM_ARCH=rs6000
     596        else
     597                IBM_ARCH=powerpc
     598        fi
     599        if [ -x /usr/bin/lslpp ] ; then
     600                IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
     601                           awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
     602        else
     603                IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
     604        fi
     605        echo ${IBM_ARCH}-ibm-aix${IBM_REV}
     606        exit ;;
     607    *:AIX:*:*)
     608        echo rs6000-ibm-aix
     609        exit ;;
     610    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
     611        echo romp-ibm-bsd4.4
     612        exit ;;
     613    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
     614        echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
     615        exit ;;                             # report: romp-ibm BSD 4.3
     616    *:BOSX:*:*)
     617        echo rs6000-bull-bosx
     618        exit ;;
     619    DPX/2?00:B.O.S.:*:*)
     620        echo m68k-bull-sysv3
     621        exit ;;
     622    9000/[34]??:4.3bsd:1.*:*)
     623        echo m68k-hp-bsd
     624        exit ;;
     625    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
     626        echo m68k-hp-bsd4.4
     627        exit ;;
     628    9000/[34678]??:HP-UX:*:*)
     629        HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
     630        case "${UNAME_MACHINE}" in
     631            9000/31? )            HP_ARCH=m68000 ;;
     632            9000/[34]?? )         HP_ARCH=m68k ;;
     633            9000/[678][0-9][0-9])
     634                if [ -x /usr/bin/getconf ]; then
     635                    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
     636                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
     637                    case "${sc_cpu_version}" in
     638                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
     639                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
     640                      532)                      # CPU_PA_RISC2_0
     641                        case "${sc_kernel_bits}" in
     642                          32) HP_ARCH="hppa2.0n" ;;
     643                          64) HP_ARCH="hppa2.0w" ;;
     644                          '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
     645                        esac ;;
     646                    esac
     647                fi
     648                if [ "${HP_ARCH}" = "" ]; then
     649                    eval $set_cc_for_build
     650                    sed 's/^            //' << EOF >$dummy.c
     651
     652                #define _HPUX_SOURCE
     653                #include <stdlib.h>
     654                #include <unistd.h>
     655
     656                int main ()
     657                {
     658                #if defined(_SC_KERNEL_BITS)
     659                    long bits = sysconf(_SC_KERNEL_BITS);
     660                #endif
     661                    long cpu  = sysconf (_SC_CPU_VERSION);
     662
     663                    switch (cpu)
     664                        {
     665                        case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
     666                        case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
     667                        case CPU_PA_RISC2_0:
     668                #if defined(_SC_KERNEL_BITS)
     669                            switch (bits)
     670                                {
     671                                case 64: puts ("hppa2.0w"); break;
     672                                case 32: puts ("hppa2.0n"); break;
     673                                default: puts ("hppa2.0"); break;
     674                                } break;
     675                #else  /* !defined(_SC_KERNEL_BITS) */
     676                            puts ("hppa2.0"); break;
     677                #endif
     678                        default: puts ("hppa1.0"); break;
     679                        }
     680                    exit (0);
     681                }
     682EOF
     683                    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
     684                    test -z "$HP_ARCH" && HP_ARCH=hppa
     685                fi ;;
     686        esac
     687        if [ ${HP_ARCH} = "hppa2.0w" ]
     688        then
     689            eval $set_cc_for_build
     690
     691            # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
     692            # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
     693            # generating 64-bit code.  GNU and HP use different nomenclature:
     694            #
     695            # $ CC_FOR_BUILD=cc ./config.guess
     696            # => hppa2.0w-hp-hpux11.23
     697            # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
     698            # => hppa64-hp-hpux11.23
     699
     700            if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
     701                grep -q __LP64__
     702            then
     703                HP_ARCH="hppa2.0w"
     704            else
     705                HP_ARCH="hppa64"
     706            fi
     707        fi
     708        echo ${HP_ARCH}-hp-hpux${HPUX_REV}
     709        exit ;;
     710    ia64:HP-UX:*:*)
     711        HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
     712        echo ia64-hp-hpux${HPUX_REV}
     713        exit ;;
     714    3050*:HI-UX:*:*)
     715        eval $set_cc_for_build
     716        sed 's/^        //' << EOF >$dummy.c
     717        #include <unistd.h>
     718        int
     719        main ()
     720        {
     721          long cpu = sysconf (_SC_CPU_VERSION);
     722          /* The order matters, because CPU_IS_HP_MC68K erroneously returns
     723             true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
     724             results, however.  */
     725          if (CPU_IS_PA_RISC (cpu))
     726            {
     727              switch (cpu)
     728                {
     729                  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
     730                  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
     731                  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
     732                  default: puts ("hppa-hitachi-hiuxwe2"); break;
     733                }
     734            }
     735          else if (CPU_IS_HP_MC68K (cpu))
     736            puts ("m68k-hitachi-hiuxwe2");
     737          else puts ("unknown-hitachi-hiuxwe2");
     738          exit (0);
     739        }
     740EOF
     741        $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
     742                { echo "$SYSTEM_NAME"; exit; }
     743        echo unknown-hitachi-hiuxwe2
     744        exit ;;
     745    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
     746        echo hppa1.1-hp-bsd
     747        exit ;;
     748    9000/8??:4.3bsd:*:*)
     749        echo hppa1.0-hp-bsd
     750        exit ;;
     751    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
     752        echo hppa1.0-hp-mpeix
     753        exit ;;
     754    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
     755        echo hppa1.1-hp-osf
     756        exit ;;
     757    hp8??:OSF1:*:*)
     758        echo hppa1.0-hp-osf
     759        exit ;;
     760    i*86:OSF1:*:*)
     761        if [ -x /usr/sbin/sysversion ] ; then
     762            echo ${UNAME_MACHINE}-unknown-osf1mk
     763        else
     764            echo ${UNAME_MACHINE}-unknown-osf1
     765        fi
     766        exit ;;
     767    parisc*:Lites*:*:*)
     768        echo hppa1.1-hp-lites
     769        exit ;;
     770    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
     771        echo c1-convex-bsd
     772        exit ;;
     773    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
     774        if getsysinfo -f scalar_acc
     775        then echo c32-convex-bsd
     776        else echo c2-convex-bsd
     777        fi
     778        exit ;;
     779    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
     780        echo c34-convex-bsd
     781        exit ;;
     782    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
     783        echo c38-convex-bsd
     784        exit ;;
     785    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
     786        echo c4-convex-bsd
     787        exit ;;
     788    CRAY*Y-MP:*:*:*)
     789        echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
     790        exit ;;
     791    CRAY*[A-Z]90:*:*:*)
     792        echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
     793        | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
     794              -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
     795              -e 's/\.[^.]*$/.X/'
     796        exit ;;
     797    CRAY*TS:*:*:*)
     798        echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
     799        exit ;;
     800    CRAY*T3E:*:*:*)
     801        echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
     802        exit ;;
     803    CRAY*SV1:*:*:*)
     804        echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
     805        exit ;;
     806    *:UNICOS/mp:*:*)
     807        echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
     808        exit ;;
     809    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
     810        FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
     811        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
     812        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
     813        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
     814        exit ;;
     815    5000:UNIX_System_V:4.*:*)
     816        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
     817        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
     818        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
     819        exit ;;
     820    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
     821        echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
     822        exit ;;
     823    sparc*:BSD/OS:*:*)
     824        echo sparc-unknown-bsdi${UNAME_RELEASE}
     825        exit ;;
     826    *:BSD/OS:*:*)
     827        echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
     828        exit ;;
     829    *:FreeBSD:*:*)
     830        UNAME_PROCESSOR=`/usr/bin/uname -p`
     831        case ${UNAME_PROCESSOR} in
     832            amd64)
     833                echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
     834            *)
     835                echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
     836        esac
     837        exit ;;
     838    i*:CYGWIN*:*)
     839        echo ${UNAME_MACHINE}-pc-cygwin
     840        exit ;;
     841    *:MINGW64*:*)
     842        echo ${UNAME_MACHINE}-pc-mingw64
     843        exit ;;
     844    *:MINGW*:*)
     845        echo ${UNAME_MACHINE}-pc-mingw32
     846        exit ;;
     847    *:MSYS*:*)
     848        echo ${UNAME_MACHINE}-pc-msys
     849        exit ;;
     850    i*:windows32*:*)
     851        # uname -m includes "-pc" on this system.
     852        echo ${UNAME_MACHINE}-mingw32
     853        exit ;;
     854    i*:PW*:*)
     855        echo ${UNAME_MACHINE}-pc-pw32
     856        exit ;;
     857    *:Interix*:*)
     858        case ${UNAME_MACHINE} in
     859            x86)
     860                echo i586-pc-interix${UNAME_RELEASE}
     861                exit ;;
     862            authenticamd | genuineintel | EM64T)
     863                echo x86_64-unknown-interix${UNAME_RELEASE}
     864                exit ;;
     865            IA64)
     866                echo ia64-unknown-interix${UNAME_RELEASE}
     867                exit ;;
     868        esac ;;
     869    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
     870        echo i${UNAME_MACHINE}-pc-mks
     871        exit ;;
     872    8664:Windows_NT:*)
     873        echo x86_64-pc-mks
     874        exit ;;
     875    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
     876        # How do we know it's Interix rather than the generic POSIX subsystem?
     877        # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
     878        # UNAME_MACHINE based on the output of uname instead of i386?
     879        echo i586-pc-interix
     880        exit ;;
     881    i*:UWIN*:*)
     882        echo ${UNAME_MACHINE}-pc-uwin
     883        exit ;;
     884    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
     885        echo x86_64-unknown-cygwin
     886        exit ;;
     887    p*:CYGWIN*:*)
     888        echo powerpcle-unknown-cygwin
     889        exit ;;
     890    prep*:SunOS:5.*:*)
     891        echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
     892        exit ;;
     893    *:GNU:*:*)
     894        # the GNU system
     895        echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
     896        exit ;;
     897    *:GNU/*:*:*)
     898        # other systems with GNU libc and userland
     899        echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
     900        exit ;;
     901    i*86:Minix:*:*)
     902        echo ${UNAME_MACHINE}-pc-minix
     903        exit ;;
     904    aarch64:Linux:*:*)
     905        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     906        exit ;;
     907    aarch64_be:Linux:*:*)
     908        UNAME_MACHINE=aarch64_be
     909        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     910        exit ;;
     911    alpha:Linux:*:*)
     912        case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
     913          EV5)   UNAME_MACHINE=alphaev5 ;;
     914          EV56)  UNAME_MACHINE=alphaev56 ;;
     915          PCA56) UNAME_MACHINE=alphapca56 ;;
     916          PCA57) UNAME_MACHINE=alphapca56 ;;
     917          EV6)   UNAME_MACHINE=alphaev6 ;;
     918          EV67)  UNAME_MACHINE=alphaev67 ;;
     919          EV68*) UNAME_MACHINE=alphaev68 ;;
     920        esac
     921        objdump --private-headers /bin/sh | grep -q ld.so.1
     922        if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
     923        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     924        exit ;;
     925    arc:Linux:*:* | arceb:Linux:*:*)
     926        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     927        exit ;;
     928    arm*:Linux:*:*)
     929        eval $set_cc_for_build
     930        if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
     931            | grep -q __ARM_EABI__
     932        then
     933            echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     934        else
     935            if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
     936                | grep -q __ARM_PCS_VFP
     937            then
     938                echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
     939            else
     940                echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
     941            fi
     942        fi
     943        exit ;;
     944    avr32*:Linux:*:*)
     945        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     946        exit ;;
     947    cris:Linux:*:*)
     948        echo ${UNAME_MACHINE}-axis-linux-${LIBC}
     949        exit ;;
     950    crisv32:Linux:*:*)
     951        echo ${UNAME_MACHINE}-axis-linux-${LIBC}
     952        exit ;;
     953    e2k:Linux:*:*)
     954        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     955        exit ;;
     956    frv:Linux:*:*)
     957        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     958        exit ;;
     959    hexagon:Linux:*:*)
     960        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     961        exit ;;
     962    i*86:Linux:*:*)
     963        echo ${UNAME_MACHINE}-pc-linux-${LIBC}
     964        exit ;;
     965    ia64:Linux:*:*)
     966        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     967        exit ;;
     968    m32r*:Linux:*:*)
     969        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     970        exit ;;
     971    m68*:Linux:*:*)
     972        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     973        exit ;;
     974    mips:Linux:*:* | mips64:Linux:*:*)
     975        eval $set_cc_for_build
     976        sed 's/^        //' << EOF >$dummy.c
     977        #undef CPU
     978        #undef ${UNAME_MACHINE}
     979        #undef ${UNAME_MACHINE}el
     980        #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
     981        CPU=${UNAME_MACHINE}el
     982        #else
     983        #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
     984        CPU=${UNAME_MACHINE}
     985        #else
     986        CPU=
     987        #endif
     988        #endif
     989EOF
     990        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
     991        test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
     992        ;;
     993    openrisc*:Linux:*:*)
     994        echo or1k-unknown-linux-${LIBC}
     995        exit ;;
     996    or32:Linux:*:* | or1k*:Linux:*:*)
     997        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     998        exit ;;
     999    padre:Linux:*:*)
     1000        echo sparc-unknown-linux-${LIBC}
     1001        exit ;;
     1002    parisc64:Linux:*:* | hppa64:Linux:*:*)
     1003        echo hppa64-unknown-linux-${LIBC}
     1004        exit ;;
     1005    parisc:Linux:*:* | hppa:Linux:*:*)
     1006        # Look for CPU level
     1007        case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
     1008          PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
     1009          PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
     1010          *)    echo hppa-unknown-linux-${LIBC} ;;
     1011        esac
     1012        exit ;;
     1013    ppc64:Linux:*:*)
     1014        echo powerpc64-unknown-linux-${LIBC}
     1015        exit ;;
     1016    ppc:Linux:*:*)
     1017        echo powerpc-unknown-linux-${LIBC}
     1018        exit ;;
     1019    ppc64le:Linux:*:*)
     1020        echo powerpc64le-unknown-linux-${LIBC}
     1021        exit ;;
     1022    ppcle:Linux:*:*)
     1023        echo powerpcle-unknown-linux-${LIBC}
     1024        exit ;;
     1025    s390:Linux:*:* | s390x:Linux:*:*)
     1026        echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
     1027        exit ;;
     1028    sh64*:Linux:*:*)
     1029        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     1030        exit ;;
     1031    sh*:Linux:*:*)
     1032        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     1033        exit ;;
     1034    sparc:Linux:*:* | sparc64:Linux:*:*)
     1035        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     1036        exit ;;
     1037    tile*:Linux:*:*)
     1038        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     1039        exit ;;
     1040    vax:Linux:*:*)
     1041        echo ${UNAME_MACHINE}-dec-linux-${LIBC}
     1042        exit ;;
     1043    x86_64:Linux:*:*)
     1044        echo ${UNAME_MACHINE}-pc-linux-${LIBC}
     1045        exit ;;
     1046    xtensa*:Linux:*:*)
     1047        echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
     1048        exit ;;
     1049    i*86:DYNIX/ptx:4*:*)
     1050        # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
     1051        # earlier versions are messed up and put the nodename in both
     1052        # sysname and nodename.
     1053        echo i386-sequent-sysv4
     1054        exit ;;
     1055    i*86:UNIX_SV:4.2MP:2.*)
     1056        # Unixware is an offshoot of SVR4, but it has its own version
     1057        # number series starting with 2...
     1058        # I am not positive that other SVR4 systems won't match this,
     1059        # I just have to hope.  -- rms.
     1060        # Use sysv4.2uw... so that sysv4* matches it.
     1061        echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
     1062        exit ;;
     1063    i*86:OS/2:*:*)
     1064        # If we were able to find `uname', then EMX Unix compatibility
     1065        # is probably installed.
     1066        echo ${UNAME_MACHINE}-pc-os2-emx
     1067        exit ;;
     1068    i*86:XTS-300:*:STOP)
     1069        echo ${UNAME_MACHINE}-unknown-stop
     1070        exit ;;
     1071    i*86:atheos:*:*)
     1072        echo ${UNAME_MACHINE}-unknown-atheos
     1073        exit ;;
     1074    i*86:syllable:*:*)
     1075        echo ${UNAME_MACHINE}-pc-syllable
     1076        exit ;;
     1077    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
     1078        echo i386-unknown-lynxos${UNAME_RELEASE}
     1079        exit ;;
     1080    i*86:*DOS:*:*)
     1081        echo ${UNAME_MACHINE}-pc-msdosdjgpp
     1082        exit ;;
     1083    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
     1084        UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
     1085        if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
     1086                echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
     1087        else
     1088                echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
     1089        fi
     1090        exit ;;
     1091    i*86:*:5:[678]*)
     1092        # UnixWare 7.x, OpenUNIX and OpenServer 6.
     1093        case `/bin/uname -X | grep "^Machine"` in
     1094            *486*)           UNAME_MACHINE=i486 ;;
     1095            *Pentium)        UNAME_MACHINE=i586 ;;
     1096            *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
     1097        esac
     1098        echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
     1099        exit ;;
     1100    i*86:*:3.2:*)
     1101        if test -f /usr/options/cb.name; then
     1102                UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
     1103                echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
     1104        elif /bin/uname -X 2>/dev/null >/dev/null ; then
     1105                UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
     1106                (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
     1107                (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
     1108                        && UNAME_MACHINE=i586
     1109                (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
     1110                        && UNAME_MACHINE=i686
     1111                (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
     1112                        && UNAME_MACHINE=i686
     1113                echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
     1114        else
     1115                echo ${UNAME_MACHINE}-pc-sysv32
     1116        fi
     1117        exit ;;
     1118    pc:*:*:*)
     1119        # Left here for compatibility:
     1120        # uname -m prints for DJGPP always 'pc', but it prints nothing about
     1121        # the processor, so we play safe by assuming i586.
     1122        # Note: whatever this is, it MUST be the same as what config.sub
     1123        # prints for the "djgpp" host, or else GDB configury will decide that
     1124        # this is a cross-build.
     1125        echo i586-pc-msdosdjgpp
     1126        exit ;;
     1127    Intel:Mach:3*:*)
     1128        echo i386-pc-mach3
     1129        exit ;;
     1130    paragon:*:*:*)
     1131        echo i860-intel-osf1
     1132        exit ;;
     1133    i860:*:4.*:*) # i860-SVR4
     1134        if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
     1135          echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
     1136        else # Add other i860-SVR4 vendors below as they are discovered.
     1137          echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
     1138        fi
     1139        exit ;;
     1140    mini*:CTIX:SYS*5:*)
     1141        # "miniframe"
     1142        echo m68010-convergent-sysv
     1143        exit ;;
     1144    mc68k:UNIX:SYSTEM5:3.51m)
     1145        echo m68k-convergent-sysv
     1146        exit ;;
     1147    M680?0:D-NIX:5.3:*)
     1148        echo m68k-diab-dnix
     1149        exit ;;
     1150    M68*:*:R3V[5678]*:*)
     1151        test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
     1152    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
     1153        OS_REL=''
     1154        test -r /etc/.relid \
     1155        && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
     1156        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
     1157          && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
     1158        /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
     1159          && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     1160    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
     1161        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
     1162          && { echo i486-ncr-sysv4; exit; } ;;
     1163    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
     1164        OS_REL='.3'
     1165        test -r /etc/.relid \
     1166            && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
     1167        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
     1168            && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
     1169        /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
     1170            && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
     1171        /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
     1172            && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     1173    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
     1174        echo m68k-unknown-lynxos${UNAME_RELEASE}
     1175        exit ;;
     1176    mc68030:UNIX_System_V:4.*:*)
     1177        echo m68k-atari-sysv4
     1178        exit ;;
     1179    TSUNAMI:LynxOS:2.*:*)
     1180        echo sparc-unknown-lynxos${UNAME_RELEASE}
     1181        exit ;;
     1182    rs6000:LynxOS:2.*:*)
     1183        echo rs6000-unknown-lynxos${UNAME_RELEASE}
     1184        exit ;;
     1185    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
     1186        echo powerpc-unknown-lynxos${UNAME_RELEASE}
     1187        exit ;;
     1188    SM[BE]S:UNIX_SV:*:*)
     1189        echo mips-dde-sysv${UNAME_RELEASE}
     1190        exit ;;
     1191    RM*:ReliantUNIX-*:*:*)
     1192        echo mips-sni-sysv4
     1193        exit ;;
     1194    RM*:SINIX-*:*:*)
     1195        echo mips-sni-sysv4
     1196        exit ;;
     1197    *:SINIX-*:*:*)
     1198        if uname -p 2>/dev/null >/dev/null ; then
     1199                UNAME_MACHINE=`(uname -p) 2>/dev/null`
     1200                echo ${UNAME_MACHINE}-sni-sysv4
     1201        else
     1202                echo ns32k-sni-sysv
     1203        fi
     1204        exit ;;
     1205    PENTIUM:*:4.0*:*)   # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
     1206                        # says <Richard.M.Bartel@ccMail.Census.GOV>
     1207        echo i586-unisys-sysv4
     1208        exit ;;
     1209    *:UNIX_System_V:4*:FTX*)
     1210        # From Gerald Hewes <hewes@openmarket.com>.
     1211        # How about differentiating between stratus architectures? -djm
     1212        echo hppa1.1-stratus-sysv4
     1213        exit ;;
     1214    *:*:*:FTX*)
     1215        # From seanf@swdc.stratus.com.
     1216        echo i860-stratus-sysv4
     1217        exit ;;
     1218    i*86:VOS:*:*)
     1219        # From Paul.Green@stratus.com.
     1220        echo ${UNAME_MACHINE}-stratus-vos
     1221        exit ;;
     1222    *:VOS:*:*)
     1223        # From Paul.Green@stratus.com.
     1224        echo hppa1.1-stratus-vos
     1225        exit ;;
     1226    mc68*:A/UX:*:*)
     1227        echo m68k-apple-aux${UNAME_RELEASE}
     1228        exit ;;
     1229    news*:NEWS-OS:6*:*)
     1230        echo mips-sony-newsos6
     1231        exit ;;
     1232    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
     1233        if [ -d /usr/nec ]; then
     1234                echo mips-nec-sysv${UNAME_RELEASE}
     1235        else
     1236                echo mips-unknown-sysv${UNAME_RELEASE}
     1237        fi
     1238        exit ;;
     1239    BeBox:BeOS:*:*)     # BeOS running on hardware made by Be, PPC only.
     1240        echo powerpc-be-beos
     1241        exit ;;
     1242    BeMac:BeOS:*:*)     # BeOS running on Mac or Mac clone, PPC only.
     1243        echo powerpc-apple-beos
     1244        exit ;;
     1245    BePC:BeOS:*:*)      # BeOS running on Intel PC compatible.
     1246        echo i586-pc-beos
     1247        exit ;;
     1248    BePC:Haiku:*:*)     # Haiku running on Intel PC compatible.
     1249        echo i586-pc-haiku
     1250        exit ;;
     1251    x86_64:Haiku:*:*)
     1252        echo x86_64-unknown-haiku
     1253        exit ;;
     1254    SX-4:SUPER-UX:*:*)
     1255        echo sx4-nec-superux${UNAME_RELEASE}
     1256        exit ;;
     1257    SX-5:SUPER-UX:*:*)
     1258        echo sx5-nec-superux${UNAME_RELEASE}
     1259        exit ;;
     1260    SX-6:SUPER-UX:*:*)
     1261        echo sx6-nec-superux${UNAME_RELEASE}
     1262        exit ;;
     1263    SX-7:SUPER-UX:*:*)
     1264        echo sx7-nec-superux${UNAME_RELEASE}
     1265        exit ;;
     1266    SX-8:SUPER-UX:*:*)
     1267        echo sx8-nec-superux${UNAME_RELEASE}
     1268        exit ;;
     1269    SX-8R:SUPER-UX:*:*)
     1270        echo sx8r-nec-superux${UNAME_RELEASE}
     1271        exit ;;
     1272    Power*:Rhapsody:*:*)
     1273        echo powerpc-apple-rhapsody${UNAME_RELEASE}
     1274        exit ;;
     1275    *:Rhapsody:*:*)
     1276        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
     1277        exit ;;
     1278    *:Darwin:*:*)
     1279        UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
     1280        eval $set_cc_for_build
     1281        if test "$UNAME_PROCESSOR" = unknown ; then
     1282            UNAME_PROCESSOR=powerpc
     1283        fi
     1284        if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
     1285            if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
     1286                if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
     1287                    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
     1288                    grep IS_64BIT_ARCH >/dev/null
     1289                then
     1290                    case $UNAME_PROCESSOR in
     1291                        i386) UNAME_PROCESSOR=x86_64 ;;
     1292                        powerpc) UNAME_PROCESSOR=powerpc64 ;;
     1293                    esac
     1294                fi
     1295            fi
     1296        elif test "$UNAME_PROCESSOR" = i386 ; then
     1297            # Avoid executing cc on OS X 10.9, as it ships with a stub
     1298            # that puts up a graphical alert prompting to install
     1299            # developer tools.  Any system running Mac OS X 10.7 or
     1300            # later (Darwin 11 and later) is required to have a 64-bit
     1301            # processor. This is not true of the ARM version of Darwin
     1302            # that Apple uses in portable devices.
     1303            UNAME_PROCESSOR=x86_64
     1304        fi
     1305        echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
     1306        exit ;;
     1307    *:procnto*:*:* | *:QNX:[0123456789]*:*)
     1308        UNAME_PROCESSOR=`uname -p`
     1309        if test "$UNAME_PROCESSOR" = "x86"; then
     1310                UNAME_PROCESSOR=i386
     1311                UNAME_MACHINE=pc
     1312        fi
     1313        echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
     1314        exit ;;
     1315    *:QNX:*:4*)
     1316        echo i386-pc-qnx
     1317        exit ;;
     1318    NEO-?:NONSTOP_KERNEL:*:*)
     1319        echo neo-tandem-nsk${UNAME_RELEASE}
     1320        exit ;;
     1321    NSE-*:NONSTOP_KERNEL:*:*)
     1322        echo nse-tandem-nsk${UNAME_RELEASE}
     1323        exit ;;
     1324    NSR-?:NONSTOP_KERNEL:*:*)
     1325        echo nsr-tandem-nsk${UNAME_RELEASE}
     1326        exit ;;
     1327    *:NonStop-UX:*:*)
     1328        echo mips-compaq-nonstopux
     1329        exit ;;
     1330    BS2000:POSIX*:*:*)
     1331        echo bs2000-siemens-sysv
     1332        exit ;;
     1333    DS/*:UNIX_System_V:*:*)
     1334        echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
     1335        exit ;;
     1336    *:Plan9:*:*)
     1337        # "uname -m" is not consistent, so use $cputype instead. 386
     1338        # is converted to i386 for consistency with other x86
     1339        # operating systems.
     1340        if test "$cputype" = "386"; then
     1341            UNAME_MACHINE=i386
     1342        else
     1343            UNAME_MACHINE="$cputype"
     1344        fi
     1345        echo ${UNAME_MACHINE}-unknown-plan9
     1346        exit ;;
     1347    *:TOPS-10:*:*)
     1348        echo pdp10-unknown-tops10
     1349        exit ;;
     1350    *:TENEX:*:*)
     1351        echo pdp10-unknown-tenex
     1352        exit ;;
     1353    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
     1354        echo pdp10-dec-tops20
     1355        exit ;;
     1356    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
     1357        echo pdp10-xkl-tops20
     1358        exit ;;
     1359    *:TOPS-20:*:*)
     1360        echo pdp10-unknown-tops20
     1361        exit ;;
     1362    *:ITS:*:*)
     1363        echo pdp10-unknown-its
     1364        exit ;;
     1365    SEI:*:*:SEIUX)
     1366        echo mips-sei-seiux${UNAME_RELEASE}
     1367        exit ;;
     1368    *:DragonFly:*:*)
     1369        echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
     1370        exit ;;
     1371    *:*VMS:*:*)
     1372        UNAME_MACHINE=`(uname -p) 2>/dev/null`
     1373        case "${UNAME_MACHINE}" in
     1374            A*) echo alpha-dec-vms ; exit ;;
     1375            I*) echo ia64-dec-vms ; exit ;;
     1376            V*) echo vax-dec-vms ; exit ;;
     1377        esac ;;
     1378    *:XENIX:*:SysV)
     1379        echo i386-pc-xenix
     1380        exit ;;
     1381    i*86:skyos:*:*)
     1382        echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
     1383        exit ;;
     1384    i*86:rdos:*:*)
     1385        echo ${UNAME_MACHINE}-pc-rdos
     1386        exit ;;
     1387    i*86:AROS:*:*)
     1388        echo ${UNAME_MACHINE}-pc-aros
     1389        exit ;;
     1390    x86_64:VMkernel:*:*)
     1391        echo ${UNAME_MACHINE}-unknown-esx
     1392        exit ;;
     1393esac
     1394
     1395cat >&2 <<EOF
     1396$0: unable to guess system type
     1397
     1398This script, last modified $timestamp, has failed to recognize
     1399the operating system you are using. It is advised that you
     1400download the most up to date version of the config scripts from
     1401
     1402  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
     1403and
     1404  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
     1405
     1406If the version you run ($0) is already up to date, please
     1407send the following data and any information you think might be
     1408pertinent to <config-patches@gnu.org> in order to provide the needed
     1409information to handle your system.
     1410
     1411config.guess timestamp = $timestamp
     1412
     1413uname -m = `(uname -m) 2>/dev/null || echo unknown`
     1414uname -r = `(uname -r) 2>/dev/null || echo unknown`
     1415uname -s = `(uname -s) 2>/dev/null || echo unknown`
     1416uname -v = `(uname -v) 2>/dev/null || echo unknown`
     1417
     1418/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
     1419/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
     1420
     1421hostinfo               = `(hostinfo) 2>/dev/null`
     1422/bin/universe          = `(/bin/universe) 2>/dev/null`
     1423/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
     1424/bin/arch              = `(/bin/arch) 2>/dev/null`
     1425/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
     1426/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
     1427
     1428UNAME_MACHINE = ${UNAME_MACHINE}
     1429UNAME_RELEASE = ${UNAME_RELEASE}
     1430UNAME_SYSTEM  = ${UNAME_SYSTEM}
     1431UNAME_VERSION = ${UNAME_VERSION}
     1432EOF
     1433
     1434exit 1
     1435
     1436# Local variables:
     1437# eval: (add-hook 'write-file-hooks 'time-stamp)
     1438# time-stamp-start: "timestamp='"
     1439# time-stamp-format: "%:y-%02m-%02d"
     1440# time-stamp-end: "'"
     1441# End:
  • automake/config.sub

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/config.sub
     1#! /bin/sh
     2# Configuration validation subroutine script.
     3#   Copyright 1992-2015 Free Software Foundation, Inc.
     4
     5timestamp='2015-08-20'
     6
     7# This file is free software; you can redistribute it and/or modify it
     8# under the terms of the GNU General Public License as published by
     9# the Free Software Foundation; either version 3 of the License, or
     10# (at your option) any later version.
     11#
     12# This program is distributed in the hope that it will be useful, but
     13# WITHOUT ANY WARRANTY; without even the implied warranty of
     14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15# General Public License for more details.
     16#
     17# You should have received a copy of the GNU General Public License
     18# along with this program; if not, see <http://www.gnu.org/licenses/>.
     19#
     20# As a special exception to the GNU General Public License, if you
     21# distribute this file as part of a program that contains a
     22# configuration script generated by Autoconf, you may include it under
     23# the same distribution terms that you use for the rest of that
     24# program.  This Exception is an additional permission under section 7
     25# of the GNU General Public License, version 3 ("GPLv3").
     26
     27
     28# Please send patches to <config-patches@gnu.org>.
     29#
     30# Configuration subroutine to validate and canonicalize a configuration type.
     31# Supply the specified configuration type as an argument.
     32# If it is invalid, we print an error message on stderr and exit with code 1.
     33# Otherwise, we print the canonical config type on stdout and succeed.
     34
     35# You can get the latest version of this script from:
     36# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
     37
     38# This file is supposed to be the same for all GNU packages
     39# and recognize all the CPU types, system types and aliases
     40# that are meaningful with *any* GNU software.
     41# Each package is responsible for reporting which valid configurations
     42# it does not support.  The user should be able to distinguish
     43# a failure to support a valid configuration from a meaningless
     44# configuration.
     45
     46# The goal of this file is to map all the various variations of a given
     47# machine specification into a single specification in the form:
     48#       CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
     49# or in some cases, the newer four-part form:
     50#       CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
     51# It is wrong to echo any other type of specification.
     52
     53me=`echo "$0" | sed -e 's,.*/,,'`
     54
     55usage="\
     56Usage: $0 [OPTION] CPU-MFR-OPSYS
     57       $0 [OPTION] ALIAS
     58
     59Canonicalize a configuration name.
     60
     61Operation modes:
     62  -h, --help         print this help, then exit
     63  -t, --time-stamp   print date of last modification, then exit
     64  -v, --version      print version number, then exit
     65
     66Report bugs and patches to <config-patches@gnu.org>."
     67
     68version="\
     69GNU config.sub ($timestamp)
     70
     71Copyright 1992-2015 Free Software Foundation, Inc.
     72
     73This is free software; see the source for copying conditions.  There is NO
     74warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
     75
     76help="
     77Try \`$me --help' for more information."
     78
     79# Parse command line
     80while test $# -gt 0 ; do
     81  case $1 in
     82    --time-stamp | --time* | -t )
     83       echo "$timestamp" ; exit ;;
     84    --version | -v )
     85       echo "$version" ; exit ;;
     86    --help | --h* | -h )
     87       echo "$usage"; exit ;;
     88    -- )     # Stop option processing
     89       shift; break ;;
     90    - ) # Use stdin as input.
     91       break ;;
     92    -* )
     93       echo "$me: invalid option $1$help"
     94       exit 1 ;;
     95
     96    *local*)
     97       # First pass through any local machine types.
     98       echo $1
     99       exit ;;
     100
     101    * )
     102       break ;;
     103  esac
     104done
     105
     106case $# in
     107 0) echo "$me: missing argument$help" >&2
     108    exit 1;;
     109 1) ;;
     110 *) echo "$me: too many arguments$help" >&2
     111    exit 1;;
     112esac
     113
     114# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
     115# Here we must recognize all the valid KERNEL-OS combinations.
     116maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
     117case $maybe_os in
     118  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
     119  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
     120  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
     121  kopensolaris*-gnu* | \
     122  storm-chaos* | os2-emx* | rtmk-nova*)
     123    os=-$maybe_os
     124    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     125    ;;
     126  android-linux)
     127    os=-linux-android
     128    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
     129    ;;
     130  *)
     131    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
     132    if [ $basic_machine != $1 ]
     133    then os=`echo $1 | sed 's/.*-/-/'`
     134    else os=; fi
     135    ;;
     136esac
     137
     138### Let's recognize common machines as not being operating systems so
     139### that things like config.sub decstation-3100 work.  We also
     140### recognize some manufacturers as not being operating systems, so we
     141### can provide default operating systems below.
     142case $os in
     143        -sun*os*)
     144                # Prevent following clause from handling this invalid input.
     145                ;;
     146        -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
     147        -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
     148        -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
     149        -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
     150        -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
     151        -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
     152        -apple | -axis | -knuth | -cray | -microblaze*)
     153                os=
     154                basic_machine=$1
     155                ;;
     156        -bluegene*)
     157                os=-cnk
     158                ;;
     159        -sim | -cisco | -oki | -wec | -winbond)
     160                os=
     161                basic_machine=$1
     162                ;;
     163        -scout)
     164                ;;
     165        -wrs)
     166                os=-vxworks
     167                basic_machine=$1
     168                ;;
     169        -chorusos*)
     170                os=-chorusos
     171                basic_machine=$1
     172                ;;
     173        -chorusrdb)
     174                os=-chorusrdb
     175                basic_machine=$1
     176                ;;
     177        -hiux*)
     178                os=-hiuxwe2
     179                ;;
     180        -sco6)
     181                os=-sco5v6
     182                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     183                ;;
     184        -sco5)
     185                os=-sco3.2v5
     186                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     187                ;;
     188        -sco4)
     189                os=-sco3.2v4
     190                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     191                ;;
     192        -sco3.2.[4-9]*)
     193                os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
     194                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     195                ;;
     196        -sco3.2v[4-9]*)
     197                # Don't forget version if it is 3.2v4 or newer.
     198                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     199                ;;
     200        -sco5v6*)
     201                # Don't forget version if it is 3.2v4 or newer.
     202                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     203                ;;
     204        -sco*)
     205                os=-sco3.2v2
     206                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     207                ;;
     208        -udk*)
     209                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     210                ;;
     211        -isc)
     212                os=-isc2.2
     213                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     214                ;;
     215        -clix*)
     216                basic_machine=clipper-intergraph
     217                ;;
     218        -isc*)
     219                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
     220                ;;
     221        -lynx*178)
     222                os=-lynxos178
     223                ;;
     224        -lynx*5)
     225                os=-lynxos5
     226                ;;
     227        -lynx*)
     228                os=-lynxos
     229                ;;
     230        -ptx*)
     231                basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
     232                ;;
     233        -windowsnt*)
     234                os=`echo $os | sed -e 's/windowsnt/winnt/'`
     235                ;;
     236        -psos*)
     237                os=-psos
     238                ;;
     239        -mint | -mint[0-9]*)
     240                basic_machine=m68k-atari
     241                os=-mint
     242                ;;
     243esac
     244
     245# Decode aliases for certain CPU-COMPANY combinations.
     246case $basic_machine in
     247        # Recognize the basic CPU types without company name.
     248        # Some are omitted here because they have special meanings below.
     249        1750a | 580 \
     250        | a29k \
     251        | aarch64 | aarch64_be \
     252        | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
     253        | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
     254        | am33_2.0 \
     255        | arc | arceb \
     256        | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
     257        | avr | avr32 \
     258        | ba \
     259        | be32 | be64 \
     260        | bfin \
     261        | c4x | c8051 | clipper \
     262        | d10v | d30v | dlx | dsp16xx \
     263        | e2k | epiphany \
     264        | fido | fr30 | frv | ft32 \
     265        | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
     266        | hexagon \
     267        | i370 | i860 | i960 | ia64 \
     268        | ip2k | iq2000 \
     269        | k1om \
     270        | le32 | le64 \
     271        | lm32 \
     272        | m32c | m32r | m32rle | m68000 | m68k | m88k \
     273        | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
     274        | mips | mipsbe | mipseb | mipsel | mipsle \
     275        | mips16 \
     276        | mips64 | mips64el \
     277        | mips64octeon | mips64octeonel \
     278        | mips64orion | mips64orionel \
     279        | mips64r5900 | mips64r5900el \
     280        | mips64vr | mips64vrel \
     281        | mips64vr4100 | mips64vr4100el \
     282        | mips64vr4300 | mips64vr4300el \
     283        | mips64vr5000 | mips64vr5000el \
     284        | mips64vr5900 | mips64vr5900el \
     285        | mipsisa32 | mipsisa32el \
     286        | mipsisa32r2 | mipsisa32r2el \
     287        | mipsisa32r6 | mipsisa32r6el \
     288        | mipsisa64 | mipsisa64el \
     289        | mipsisa64r2 | mipsisa64r2el \
     290        | mipsisa64r6 | mipsisa64r6el \
     291        | mipsisa64sb1 | mipsisa64sb1el \
     292        | mipsisa64sr71k | mipsisa64sr71kel \
     293        | mipsr5900 | mipsr5900el \
     294        | mipstx39 | mipstx39el \
     295        | mn10200 | mn10300 \
     296        | moxie \
     297        | mt \
     298        | msp430 \
     299        | nds32 | nds32le | nds32be \
     300        | nios | nios2 | nios2eb | nios2el \
     301        | ns16k | ns32k \
     302        | open8 | or1k | or1knd | or32 \
     303        | pdp10 | pdp11 | pj | pjl \
     304        | powerpc | powerpc64 | powerpc64le | powerpcle \
     305        | pyramid \
     306        | riscv32 | riscv64 \
     307        | rl78 | rx \
     308        | score \
     309        | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
     310        | sh64 | sh64le \
     311        | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
     312        | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
     313        | spu \
     314        | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
     315        | ubicom32 \
     316        | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
     317        | visium \
     318        | we32k \
     319        | x86 | xc16x | xstormy16 | xtensa \
     320        | z8k | z80)
     321                basic_machine=$basic_machine-unknown
     322                ;;
     323        c54x)
     324                basic_machine=tic54x-unknown
     325                ;;
     326        c55x)
     327                basic_machine=tic55x-unknown
     328                ;;
     329        c6x)
     330                basic_machine=tic6x-unknown
     331                ;;
     332        leon|leon[3-9])
     333                basic_machine=sparc-$basic_machine
     334                ;;
     335        m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
     336                basic_machine=$basic_machine-unknown
     337                os=-none
     338                ;;
     339        m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
     340                ;;
     341        ms1)
     342                basic_machine=mt-unknown
     343                ;;
     344
     345        strongarm | thumb | xscale)
     346                basic_machine=arm-unknown
     347                ;;
     348        xgate)
     349                basic_machine=$basic_machine-unknown
     350                os=-none
     351                ;;
     352        xscaleeb)
     353                basic_machine=armeb-unknown
     354                ;;
     355
     356        xscaleel)
     357                basic_machine=armel-unknown
     358                ;;
     359
     360        # We use `pc' rather than `unknown'
     361        # because (1) that's what they normally are, and
     362        # (2) the word "unknown" tends to confuse beginning users.
     363        i*86 | x86_64)
     364          basic_machine=$basic_machine-pc
     365          ;;
     366        # Object if more than one company name word.
     367        *-*-*)
     368                echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
     369                exit 1
     370                ;;
     371        # Recognize the basic CPU types with company name.
     372        580-* \
     373        | a29k-* \
     374        | aarch64-* | aarch64_be-* \
     375        | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
     376        | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
     377        | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
     378        | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
     379        | avr-* | avr32-* \
     380        | ba-* \
     381        | be32-* | be64-* \
     382        | bfin-* | bs2000-* \
     383        | c[123]* | c30-* | [cjt]90-* | c4x-* \
     384        | c8051-* | clipper-* | craynv-* | cydra-* \
     385        | d10v-* | d30v-* | dlx-* \
     386        | e2k-* | elxsi-* \
     387        | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
     388        | h8300-* | h8500-* \
     389        | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
     390        | hexagon-* \
     391        | i*86-* | i860-* | i960-* | ia64-* \
     392        | ip2k-* | iq2000-* \
     393        | k1om-* \
     394        | le32-* | le64-* \
     395        | lm32-* \
     396        | m32c-* | m32r-* | m32rle-* \
     397        | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
     398        | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
     399        | microblaze-* | microblazeel-* \
     400        | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
     401        | mips16-* \
     402        | mips64-* | mips64el-* \
     403        | mips64octeon-* | mips64octeonel-* \
     404        | mips64orion-* | mips64orionel-* \
     405        | mips64r5900-* | mips64r5900el-* \
     406        | mips64vr-* | mips64vrel-* \
     407        | mips64vr4100-* | mips64vr4100el-* \
     408        | mips64vr4300-* | mips64vr4300el-* \
     409        | mips64vr5000-* | mips64vr5000el-* \
     410        | mips64vr5900-* | mips64vr5900el-* \
     411        | mipsisa32-* | mipsisa32el-* \
     412        | mipsisa32r2-* | mipsisa32r2el-* \
     413        | mipsisa32r6-* | mipsisa32r6el-* \
     414        | mipsisa64-* | mipsisa64el-* \
     415        | mipsisa64r2-* | mipsisa64r2el-* \
     416        | mipsisa64r6-* | mipsisa64r6el-* \
     417        | mipsisa64sb1-* | mipsisa64sb1el-* \
     418        | mipsisa64sr71k-* | mipsisa64sr71kel-* \
     419        | mipsr5900-* | mipsr5900el-* \
     420        | mipstx39-* | mipstx39el-* \
     421        | mmix-* \
     422        | mt-* \
     423        | msp430-* \
     424        | nds32-* | nds32le-* | nds32be-* \
     425        | nios-* | nios2-* | nios2eb-* | nios2el-* \
     426        | none-* | np1-* | ns16k-* | ns32k-* \
     427        | open8-* \
     428        | or1k*-* \
     429        | orion-* \
     430        | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
     431        | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
     432        | pyramid-* \
     433        | riscv32-* | riscv64-* \
     434        | rl78-* | romp-* | rs6000-* | rx-* \
     435        | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
     436        | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
     437        | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
     438        | sparclite-* \
     439        | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
     440        | tahoe-* \
     441        | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
     442        | tile*-* \
     443        | tron-* \
     444        | ubicom32-* \
     445        | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
     446        | vax-* \
     447        | visium-* \
     448        | we32k-* \
     449        | x86-* | x86_64-* | xc16x-* | xps100-* \
     450        | xstormy16-* | xtensa*-* \
     451        | ymp-* \
     452        | z8k-* | z80-*)
     453                ;;
     454        # Recognize the basic CPU types without company name, with glob match.
     455        xtensa*)
     456                basic_machine=$basic_machine-unknown
     457                ;;
     458        # Recognize the various machine names and aliases which stand
     459        # for a CPU type and a company and sometimes even an OS.
     460        386bsd)
     461                basic_machine=i386-unknown
     462                os=-bsd
     463                ;;
     464        3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
     465                basic_machine=m68000-att
     466                ;;
     467        3b*)
     468                basic_machine=we32k-att
     469                ;;
     470        a29khif)
     471                basic_machine=a29k-amd
     472                os=-udi
     473                ;;
     474        abacus)
     475                basic_machine=abacus-unknown
     476                ;;
     477        adobe68k)
     478                basic_machine=m68010-adobe
     479                os=-scout
     480                ;;
     481        alliant | fx80)
     482                basic_machine=fx80-alliant
     483                ;;
     484        altos | altos3068)
     485                basic_machine=m68k-altos
     486                ;;
     487        am29k)
     488                basic_machine=a29k-none
     489                os=-bsd
     490                ;;
     491        amd64)
     492                basic_machine=x86_64-pc
     493                ;;
     494        amd64-*)
     495                basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
     496                ;;
     497        amdahl)
     498                basic_machine=580-amdahl
     499                os=-sysv
     500                ;;
     501        amiga | amiga-*)
     502                basic_machine=m68k-unknown
     503                ;;
     504        amigaos | amigados)
     505                basic_machine=m68k-unknown
     506                os=-amigaos
     507                ;;
     508        amigaunix | amix)
     509                basic_machine=m68k-unknown
     510                os=-sysv4
     511                ;;
     512        apollo68)
     513                basic_machine=m68k-apollo
     514                os=-sysv
     515                ;;
     516        apollo68bsd)
     517                basic_machine=m68k-apollo
     518                os=-bsd
     519                ;;
     520        aros)
     521                basic_machine=i386-pc
     522                os=-aros
     523                ;;
     524        asmjs)
     525                basic_machine=asmjs-unknown
     526                ;;
     527        aux)
     528                basic_machine=m68k-apple
     529                os=-aux
     530                ;;
     531        balance)
     532                basic_machine=ns32k-sequent
     533                os=-dynix
     534                ;;
     535        blackfin)
     536                basic_machine=bfin-unknown
     537                os=-linux
     538                ;;
     539        blackfin-*)
     540                basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
     541                os=-linux
     542                ;;
     543        bluegene*)
     544                basic_machine=powerpc-ibm
     545                os=-cnk
     546                ;;
     547        c54x-*)
     548                basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
     549                ;;
     550        c55x-*)
     551                basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
     552                ;;
     553        c6x-*)
     554                basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
     555                ;;
     556        c90)
     557                basic_machine=c90-cray
     558                os=-unicos
     559                ;;
     560        cegcc)
     561                basic_machine=arm-unknown
     562                os=-cegcc
     563                ;;
     564        convex-c1)
     565                basic_machine=c1-convex
     566                os=-bsd
     567                ;;
     568        convex-c2)
     569                basic_machine=c2-convex
     570                os=-bsd
     571                ;;
     572        convex-c32)
     573                basic_machine=c32-convex
     574                os=-bsd
     575                ;;
     576        convex-c34)
     577                basic_machine=c34-convex
     578                os=-bsd
     579                ;;
     580        convex-c38)
     581                basic_machine=c38-convex
     582                os=-bsd
     583                ;;
     584        cray | j90)
     585                basic_machine=j90-cray
     586                os=-unicos
     587                ;;
     588        craynv)
     589                basic_machine=craynv-cray
     590                os=-unicosmp
     591                ;;
     592        cr16 | cr16-*)
     593                basic_machine=cr16-unknown
     594                os=-elf
     595                ;;
     596        crds | unos)
     597                basic_machine=m68k-crds
     598                ;;
     599        crisv32 | crisv32-* | etraxfs*)
     600                basic_machine=crisv32-axis
     601                ;;
     602        cris | cris-* | etrax*)
     603                basic_machine=cris-axis
     604                ;;
     605        crx)
     606                basic_machine=crx-unknown
     607                os=-elf
     608                ;;
     609        da30 | da30-*)
     610                basic_machine=m68k-da30
     611                ;;
     612        decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
     613                basic_machine=mips-dec
     614                ;;
     615        decsystem10* | dec10*)
     616                basic_machine=pdp10-dec
     617                os=-tops10
     618                ;;
     619        decsystem20* | dec20*)
     620                basic_machine=pdp10-dec
     621                os=-tops20
     622                ;;
     623        delta | 3300 | motorola-3300 | motorola-delta \
     624              | 3300-motorola | delta-motorola)
     625                basic_machine=m68k-motorola
     626                ;;
     627        delta88)
     628                basic_machine=m88k-motorola
     629                os=-sysv3
     630                ;;
     631        dicos)
     632                basic_machine=i686-pc
     633                os=-dicos
     634                ;;
     635        djgpp)
     636                basic_machine=i586-pc
     637                os=-msdosdjgpp
     638                ;;
     639        dpx20 | dpx20-*)
     640                basic_machine=rs6000-bull
     641                os=-bosx
     642                ;;
     643        dpx2* | dpx2*-bull)
     644                basic_machine=m68k-bull
     645                os=-sysv3
     646                ;;
     647        ebmon29k)
     648                basic_machine=a29k-amd
     649                os=-ebmon
     650                ;;
     651        elxsi)
     652                basic_machine=elxsi-elxsi
     653                os=-bsd
     654                ;;
     655        encore | umax | mmax)
     656                basic_machine=ns32k-encore
     657                ;;
     658        es1800 | OSE68k | ose68k | ose | OSE)
     659                basic_machine=m68k-ericsson
     660                os=-ose
     661                ;;
     662        fx2800)
     663                basic_machine=i860-alliant
     664                ;;
     665        genix)
     666                basic_machine=ns32k-ns
     667                ;;
     668        gmicro)
     669                basic_machine=tron-gmicro
     670                os=-sysv
     671                ;;
     672        go32)
     673                basic_machine=i386-pc
     674                os=-go32
     675                ;;
     676        h3050r* | hiux*)
     677                basic_machine=hppa1.1-hitachi
     678                os=-hiuxwe2
     679                ;;
     680        h8300hms)
     681                basic_machine=h8300-hitachi
     682                os=-hms
     683                ;;
     684        h8300xray)
     685                basic_machine=h8300-hitachi
     686                os=-xray
     687                ;;
     688        h8500hms)
     689                basic_machine=h8500-hitachi
     690                os=-hms
     691                ;;
     692        harris)
     693                basic_machine=m88k-harris
     694                os=-sysv3
     695                ;;
     696        hp300-*)
     697                basic_machine=m68k-hp
     698                ;;
     699        hp300bsd)
     700                basic_machine=m68k-hp
     701                os=-bsd
     702                ;;
     703        hp300hpux)
     704                basic_machine=m68k-hp
     705                os=-hpux
     706                ;;
     707        hp3k9[0-9][0-9] | hp9[0-9][0-9])
     708                basic_machine=hppa1.0-hp
     709                ;;
     710        hp9k2[0-9][0-9] | hp9k31[0-9])
     711                basic_machine=m68000-hp
     712                ;;
     713        hp9k3[2-9][0-9])
     714                basic_machine=m68k-hp
     715                ;;
     716        hp9k6[0-9][0-9] | hp6[0-9][0-9])
     717                basic_machine=hppa1.0-hp
     718                ;;
     719        hp9k7[0-79][0-9] | hp7[0-79][0-9])
     720                basic_machine=hppa1.1-hp
     721                ;;
     722        hp9k78[0-9] | hp78[0-9])
     723                # FIXME: really hppa2.0-hp
     724                basic_machine=hppa1.1-hp
     725                ;;
     726        hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
     727                # FIXME: really hppa2.0-hp
     728                basic_machine=hppa1.1-hp
     729                ;;
     730        hp9k8[0-9][13679] | hp8[0-9][13679])
     731                basic_machine=hppa1.1-hp
     732                ;;
     733        hp9k8[0-9][0-9] | hp8[0-9][0-9])
     734                basic_machine=hppa1.0-hp
     735                ;;
     736        hppa-next)
     737                os=-nextstep3
     738                ;;
     739        hppaosf)
     740                basic_machine=hppa1.1-hp
     741                os=-osf
     742                ;;
     743        hppro)
     744                basic_machine=hppa1.1-hp
     745                os=-proelf
     746                ;;
     747        i370-ibm* | ibm*)
     748                basic_machine=i370-ibm
     749                ;;
     750        i*86v32)
     751                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
     752                os=-sysv32
     753                ;;
     754        i*86v4*)
     755                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
     756                os=-sysv4
     757                ;;
     758        i*86v)
     759                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
     760                os=-sysv
     761                ;;
     762        i*86sol2)
     763                basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
     764                os=-solaris2
     765                ;;
     766        i386mach)
     767                basic_machine=i386-mach
     768                os=-mach
     769                ;;
     770        i386-vsta | vsta)
     771                basic_machine=i386-unknown
     772                os=-vsta
     773                ;;
     774        iris | iris4d)
     775                basic_machine=mips-sgi
     776                case $os in
     777                    -irix*)
     778                        ;;
     779                    *)
     780                        os=-irix4
     781                        ;;
     782                esac
     783                ;;
     784        isi68 | isi)
     785                basic_machine=m68k-isi
     786                os=-sysv
     787                ;;
     788        leon-*|leon[3-9]-*)
     789                basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
     790                ;;
     791        m68knommu)
     792                basic_machine=m68k-unknown
     793                os=-linux
     794                ;;
     795        m68knommu-*)
     796                basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
     797                os=-linux
     798                ;;
     799        m88k-omron*)
     800                basic_machine=m88k-omron
     801                ;;
     802        magnum | m3230)
     803                basic_machine=mips-mips
     804                os=-sysv
     805                ;;
     806        merlin)
     807                basic_machine=ns32k-utek
     808                os=-sysv
     809                ;;
     810        microblaze*)
     811                basic_machine=microblaze-xilinx
     812                ;;
     813        mingw64)
     814                basic_machine=x86_64-pc
     815                os=-mingw64
     816                ;;
     817        mingw32)
     818                basic_machine=i686-pc
     819                os=-mingw32
     820                ;;
     821        mingw32ce)
     822                basic_machine=arm-unknown
     823                os=-mingw32ce
     824                ;;
     825        miniframe)
     826                basic_machine=m68000-convergent
     827                ;;
     828        *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
     829                basic_machine=m68k-atari
     830                os=-mint
     831                ;;
     832        mips3*-*)
     833                basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
     834                ;;
     835        mips3*)
     836                basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
     837                ;;
     838        monitor)
     839                basic_machine=m68k-rom68k
     840                os=-coff
     841                ;;
     842        morphos)
     843                basic_machine=powerpc-unknown
     844                os=-morphos
     845                ;;
     846        moxiebox)
     847                basic_machine=moxie-unknown
     848                os=-moxiebox
     849                ;;
     850        msdos)
     851                basic_machine=i386-pc
     852                os=-msdos
     853                ;;
     854        ms1-*)
     855                basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
     856                ;;
     857        msys)
     858                basic_machine=i686-pc
     859                os=-msys
     860                ;;
     861        mvs)
     862                basic_machine=i370-ibm
     863                os=-mvs
     864                ;;
     865        nacl)
     866                basic_machine=le32-unknown
     867                os=-nacl
     868                ;;
     869        ncr3000)
     870                basic_machine=i486-ncr
     871                os=-sysv4
     872                ;;
     873        netbsd386)
     874                basic_machine=i386-unknown
     875                os=-netbsd
     876                ;;
     877        netwinder)
     878                basic_machine=armv4l-rebel
     879                os=-linux
     880                ;;
     881        news | news700 | news800 | news900)
     882                basic_machine=m68k-sony
     883                os=-newsos
     884                ;;
     885        news1000)
     886                basic_machine=m68030-sony
     887                os=-newsos
     888                ;;
     889        news-3600 | risc-news)
     890                basic_machine=mips-sony
     891                os=-newsos
     892                ;;
     893        necv70)
     894                basic_machine=v70-nec
     895                os=-sysv
     896                ;;
     897        next | m*-next )
     898                basic_machine=m68k-next
     899                case $os in
     900                    -nextstep* )
     901                        ;;
     902                    -ns2*)
     903                      os=-nextstep2
     904                        ;;
     905                    *)
     906                      os=-nextstep3
     907                        ;;
     908                esac
     909                ;;
     910        nh3000)
     911                basic_machine=m68k-harris
     912                os=-cxux
     913                ;;
     914        nh[45]000)
     915                basic_machine=m88k-harris
     916                os=-cxux
     917                ;;
     918        nindy960)
     919                basic_machine=i960-intel
     920                os=-nindy
     921                ;;
     922        mon960)
     923                basic_machine=i960-intel
     924                os=-mon960
     925                ;;
     926        nonstopux)
     927                basic_machine=mips-compaq
     928                os=-nonstopux
     929                ;;
     930        np1)
     931                basic_machine=np1-gould
     932                ;;
     933        neo-tandem)
     934                basic_machine=neo-tandem
     935                ;;
     936        nse-tandem)
     937                basic_machine=nse-tandem
     938                ;;
     939        nsr-tandem)
     940                basic_machine=nsr-tandem
     941                ;;
     942        op50n-* | op60c-*)
     943                basic_machine=hppa1.1-oki
     944                os=-proelf
     945                ;;
     946        openrisc | openrisc-*)
     947                basic_machine=or32-unknown
     948                ;;
     949        os400)
     950                basic_machine=powerpc-ibm
     951                os=-os400
     952                ;;
     953        OSE68000 | ose68000)
     954                basic_machine=m68000-ericsson
     955                os=-ose
     956                ;;
     957        os68k)
     958                basic_machine=m68k-none
     959                os=-os68k
     960                ;;
     961        pa-hitachi)
     962                basic_machine=hppa1.1-hitachi
     963                os=-hiuxwe2
     964                ;;
     965        paragon)
     966                basic_machine=i860-intel
     967                os=-osf
     968                ;;
     969        parisc)
     970                basic_machine=hppa-unknown
     971                os=-linux
     972                ;;
     973        parisc-*)
     974                basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
     975                os=-linux
     976                ;;
     977        pbd)
     978                basic_machine=sparc-tti
     979                ;;
     980        pbb)
     981                basic_machine=m68k-tti
     982                ;;
     983        pc532 | pc532-*)
     984                basic_machine=ns32k-pc532
     985                ;;
     986        pc98)
     987                basic_machine=i386-pc
     988                ;;
     989        pc98-*)
     990                basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
     991                ;;
     992        pentium | p5 | k5 | k6 | nexgen | viac3)
     993                basic_machine=i586-pc
     994                ;;
     995        pentiumpro | p6 | 6x86 | athlon | athlon_*)
     996                basic_machine=i686-pc
     997                ;;
     998        pentiumii | pentium2 | pentiumiii | pentium3)
     999                basic_machine=i686-pc
     1000                ;;
     1001        pentium4)
     1002                basic_machine=i786-pc
     1003                ;;
     1004        pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
     1005                basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
     1006                ;;
     1007        pentiumpro-* | p6-* | 6x86-* | athlon-*)
     1008                basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
     1009                ;;
     1010        pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
     1011                basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
     1012                ;;
     1013        pentium4-*)
     1014                basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
     1015                ;;
     1016        pn)
     1017                basic_machine=pn-gould
     1018                ;;
     1019        power)  basic_machine=power-ibm
     1020                ;;
     1021        ppc | ppcbe)    basic_machine=powerpc-unknown
     1022                ;;
     1023        ppc-* | ppcbe-*)
     1024                basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
     1025                ;;
     1026        ppcle | powerpclittle | ppc-le | powerpc-little)
     1027                basic_machine=powerpcle-unknown
     1028                ;;
     1029        ppcle-* | powerpclittle-*)
     1030                basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
     1031                ;;
     1032        ppc64)  basic_machine=powerpc64-unknown
     1033                ;;
     1034        ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
     1035                ;;
     1036        ppc64le | powerpc64little | ppc64-le | powerpc64-little)
     1037                basic_machine=powerpc64le-unknown
     1038                ;;
     1039        ppc64le-* | powerpc64little-*)
     1040                basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
     1041                ;;
     1042        ps2)
     1043                basic_machine=i386-ibm
     1044                ;;
     1045        pw32)
     1046                basic_machine=i586-unknown
     1047                os=-pw32
     1048                ;;
     1049        rdos | rdos64)
     1050                basic_machine=x86_64-pc
     1051                os=-rdos
     1052                ;;
     1053        rdos32)
     1054                basic_machine=i386-pc
     1055                os=-rdos
     1056                ;;
     1057        rom68k)
     1058                basic_machine=m68k-rom68k
     1059                os=-coff
     1060                ;;
     1061        rm[46]00)
     1062                basic_machine=mips-siemens
     1063                ;;
     1064        rtpc | rtpc-*)
     1065                basic_machine=romp-ibm
     1066                ;;
     1067        s390 | s390-*)
     1068                basic_machine=s390-ibm
     1069                ;;
     1070        s390x | s390x-*)
     1071                basic_machine=s390x-ibm
     1072                ;;
     1073        sa29200)
     1074                basic_machine=a29k-amd
     1075                os=-udi
     1076                ;;
     1077        sb1)
     1078                basic_machine=mipsisa64sb1-unknown
     1079                ;;
     1080        sb1el)
     1081                basic_machine=mipsisa64sb1el-unknown
     1082                ;;
     1083        sde)
     1084                basic_machine=mipsisa32-sde
     1085                os=-elf
     1086                ;;
     1087        sei)
     1088                basic_machine=mips-sei
     1089                os=-seiux
     1090                ;;
     1091        sequent)
     1092                basic_machine=i386-sequent
     1093                ;;
     1094        sh)
     1095                basic_machine=sh-hitachi
     1096                os=-hms
     1097                ;;
     1098        sh5el)
     1099                basic_machine=sh5le-unknown
     1100                ;;
     1101        sh64)
     1102                basic_machine=sh64-unknown
     1103                ;;
     1104        sparclite-wrs | simso-wrs)
     1105                basic_machine=sparclite-wrs
     1106                os=-vxworks
     1107                ;;
     1108        sps7)
     1109                basic_machine=m68k-bull
     1110                os=-sysv2
     1111                ;;
     1112        spur)
     1113                basic_machine=spur-unknown
     1114                ;;
     1115        st2000)
     1116                basic_machine=m68k-tandem
     1117                ;;
     1118        stratus)
     1119                basic_machine=i860-stratus
     1120                os=-sysv4
     1121                ;;
     1122        strongarm-* | thumb-*)
     1123                basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
     1124                ;;
     1125        sun2)
     1126                basic_machine=m68000-sun
     1127                ;;
     1128        sun2os3)
     1129                basic_machine=m68000-sun
     1130                os=-sunos3
     1131                ;;
     1132        sun2os4)
     1133                basic_machine=m68000-sun
     1134                os=-sunos4
     1135                ;;
     1136        sun3os3)
     1137                basic_machine=m68k-sun
     1138                os=-sunos3
     1139                ;;
     1140        sun3os4)
     1141                basic_machine=m68k-sun
     1142                os=-sunos4
     1143                ;;
     1144        sun4os3)
     1145                basic_machine=sparc-sun
     1146                os=-sunos3
     1147                ;;
     1148        sun4os4)
     1149                basic_machine=sparc-sun
     1150                os=-sunos4
     1151                ;;
     1152        sun4sol2)
     1153                basic_machine=sparc-sun
     1154                os=-solaris2
     1155                ;;
     1156        sun3 | sun3-*)
     1157                basic_machine=m68k-sun
     1158                ;;
     1159        sun4)
     1160                basic_machine=sparc-sun
     1161                ;;
     1162        sun386 | sun386i | roadrunner)
     1163                basic_machine=i386-sun
     1164                ;;
     1165        sv1)
     1166                basic_machine=sv1-cray
     1167                os=-unicos
     1168                ;;
     1169        symmetry)
     1170                basic_machine=i386-sequent
     1171                os=-dynix
     1172                ;;
     1173        t3e)
     1174                basic_machine=alphaev5-cray
     1175                os=-unicos
     1176                ;;
     1177        t90)
     1178                basic_machine=t90-cray
     1179                os=-unicos
     1180                ;;
     1181        tile*)
     1182                basic_machine=$basic_machine-unknown
     1183                os=-linux-gnu
     1184                ;;
     1185        tx39)
     1186                basic_machine=mipstx39-unknown
     1187                ;;
     1188        tx39el)
     1189                basic_machine=mipstx39el-unknown
     1190                ;;
     1191        toad1)
     1192                basic_machine=pdp10-xkl
     1193                os=-tops20
     1194                ;;
     1195        tower | tower-32)
     1196                basic_machine=m68k-ncr
     1197                ;;
     1198        tpf)
     1199                basic_machine=s390x-ibm
     1200                os=-tpf
     1201                ;;
     1202        udi29k)
     1203                basic_machine=a29k-amd
     1204                os=-udi
     1205                ;;
     1206        ultra3)
     1207                basic_machine=a29k-nyu
     1208                os=-sym1
     1209                ;;
     1210        v810 | necv810)
     1211                basic_machine=v810-nec
     1212                os=-none
     1213                ;;
     1214        vaxv)
     1215                basic_machine=vax-dec
     1216                os=-sysv
     1217                ;;
     1218        vms)
     1219                basic_machine=vax-dec
     1220                os=-vms
     1221                ;;
     1222        vpp*|vx|vx-*)
     1223                basic_machine=f301-fujitsu
     1224                ;;
     1225        vxworks960)
     1226                basic_machine=i960-wrs
     1227                os=-vxworks
     1228                ;;
     1229        vxworks68)
     1230                basic_machine=m68k-wrs
     1231                os=-vxworks
     1232                ;;
     1233        vxworks29k)
     1234                basic_machine=a29k-wrs
     1235                os=-vxworks
     1236                ;;
     1237        w65*)
     1238                basic_machine=w65-wdc
     1239                os=-none
     1240                ;;
     1241        w89k-*)
     1242                basic_machine=hppa1.1-winbond
     1243                os=-proelf
     1244                ;;
     1245        xbox)
     1246                basic_machine=i686-pc
     1247                os=-mingw32
     1248                ;;
     1249        xps | xps100)
     1250                basic_machine=xps100-honeywell
     1251                ;;
     1252        xscale-* | xscalee[bl]-*)
     1253                basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
     1254                ;;
     1255        ymp)
     1256                basic_machine=ymp-cray
     1257                os=-unicos
     1258                ;;
     1259        z8k-*-coff)
     1260                basic_machine=z8k-unknown
     1261                os=-sim
     1262                ;;
     1263        z80-*-coff)
     1264                basic_machine=z80-unknown
     1265                os=-sim
     1266                ;;
     1267        none)
     1268                basic_machine=none-none
     1269                os=-none
     1270                ;;
     1271
     1272# Here we handle the default manufacturer of certain CPU types.  It is in
     1273# some cases the only manufacturer, in others, it is the most popular.
     1274        w89k)
     1275                basic_machine=hppa1.1-winbond
     1276                ;;
     1277        op50n)
     1278                basic_machine=hppa1.1-oki
     1279                ;;
     1280        op60c)
     1281                basic_machine=hppa1.1-oki
     1282                ;;
     1283        romp)
     1284                basic_machine=romp-ibm
     1285                ;;
     1286        mmix)
     1287                basic_machine=mmix-knuth
     1288                ;;
     1289        rs6000)
     1290                basic_machine=rs6000-ibm
     1291                ;;
     1292        vax)
     1293                basic_machine=vax-dec
     1294                ;;
     1295        pdp10)
     1296                # there are many clones, so DEC is not a safe bet
     1297                basic_machine=pdp10-unknown
     1298                ;;
     1299        pdp11)
     1300                basic_machine=pdp11-dec
     1301                ;;
     1302        we32k)
     1303                basic_machine=we32k-att
     1304                ;;
     1305        sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
     1306                basic_machine=sh-unknown
     1307                ;;
     1308        sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
     1309                basic_machine=sparc-sun
     1310                ;;
     1311        cydra)
     1312                basic_machine=cydra-cydrome
     1313                ;;
     1314        orion)
     1315                basic_machine=orion-highlevel
     1316                ;;
     1317        orion105)
     1318                basic_machine=clipper-highlevel
     1319                ;;
     1320        mac | mpw | mac-mpw)
     1321                basic_machine=m68k-apple
     1322                ;;
     1323        pmac | pmac-mpw)
     1324                basic_machine=powerpc-apple
     1325                ;;
     1326        *-unknown)
     1327                # Make sure to match an already-canonicalized machine name.
     1328                ;;
     1329        *)
     1330                echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
     1331                exit 1
     1332                ;;
     1333esac
     1334
     1335# Here we canonicalize certain aliases for manufacturers.
     1336case $basic_machine in
     1337        *-digital*)
     1338                basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
     1339                ;;
     1340        *-commodore*)
     1341                basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
     1342                ;;
     1343        *)
     1344                ;;
     1345esac
     1346
     1347# Decode manufacturer-specific aliases for certain operating systems.
     1348
     1349if [ x"$os" != x"" ]
     1350then
     1351case $os in
     1352        # First match some system type aliases
     1353        # that might get confused with valid system types.
     1354        # -solaris* is a basic system type, with this one exception.
     1355        -auroraux)
     1356                os=-auroraux
     1357                ;;
     1358        -solaris1 | -solaris1.*)
     1359                os=`echo $os | sed -e 's|solaris1|sunos4|'`
     1360                ;;
     1361        -solaris)
     1362                os=-solaris2
     1363                ;;
     1364        -svr4*)
     1365                os=-sysv4
     1366                ;;
     1367        -unixware*)
     1368                os=-sysv4.2uw
     1369                ;;
     1370        -gnu/linux*)
     1371                os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
     1372                ;;
     1373        # First accept the basic system types.
     1374        # The portable systems comes first.
     1375        # Each alternative MUST END IN A *, to match a version number.
     1376        # -sysv* is not here because it comes later, after sysvr4.
     1377        -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
     1378              | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
     1379              | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
     1380              | -sym* | -kopensolaris* | -plan9* \
     1381              | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
     1382              | -aos* | -aros* | -cloudabi* | -sortix* \
     1383              | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
     1384              | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
     1385              | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
     1386              | -bitrig* | -openbsd* | -solidbsd* \
     1387              | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
     1388              | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
     1389              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
     1390              | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
     1391              | -chorusos* | -chorusrdb* | -cegcc* \
     1392              | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
     1393              | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
     1394              | -linux-newlib* | -linux-musl* | -linux-uclibc* \
     1395              | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
     1396              | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
     1397              | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
     1398              | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
     1399              | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
     1400              | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
     1401              | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
     1402              | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
     1403        # Remember, each alternative MUST END IN *, to match a version number.
     1404                ;;
     1405        -qnx*)
     1406                case $basic_machine in
     1407                    x86-* | i*86-*)
     1408                        ;;
     1409                    *)
     1410                        os=-nto$os
     1411                        ;;
     1412                esac
     1413                ;;
     1414        -nto-qnx*)
     1415                ;;
     1416        -nto*)
     1417                os=`echo $os | sed -e 's|nto|nto-qnx|'`
     1418                ;;
     1419        -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
     1420              | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
     1421              | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
     1422                ;;
     1423        -mac*)
     1424                os=`echo $os | sed -e 's|mac|macos|'`
     1425                ;;
     1426        -linux-dietlibc)
     1427                os=-linux-dietlibc
     1428                ;;
     1429        -linux*)
     1430                os=`echo $os | sed -e 's|linux|linux-gnu|'`
     1431                ;;
     1432        -sunos5*)
     1433                os=`echo $os | sed -e 's|sunos5|solaris2|'`
     1434                ;;
     1435        -sunos6*)
     1436                os=`echo $os | sed -e 's|sunos6|solaris3|'`
     1437                ;;
     1438        -opened*)
     1439                os=-openedition
     1440                ;;
     1441        -os400*)
     1442                os=-os400
     1443                ;;
     1444        -wince*)
     1445                os=-wince
     1446                ;;
     1447        -osfrose*)
     1448                os=-osfrose
     1449                ;;
     1450        -osf*)
     1451                os=-osf
     1452                ;;
     1453        -utek*)
     1454                os=-bsd
     1455                ;;
     1456        -dynix*)
     1457                os=-bsd
     1458                ;;
     1459        -acis*)
     1460                os=-aos
     1461                ;;
     1462        -atheos*)
     1463                os=-atheos
     1464                ;;
     1465        -syllable*)
     1466                os=-syllable
     1467                ;;
     1468        -386bsd)
     1469                os=-bsd
     1470                ;;
     1471        -ctix* | -uts*)
     1472                os=-sysv
     1473                ;;
     1474        -nova*)
     1475                os=-rtmk-nova
     1476                ;;
     1477        -ns2 )
     1478                os=-nextstep2
     1479                ;;
     1480        -nsk*)
     1481                os=-nsk
     1482                ;;
     1483        # Preserve the version number of sinix5.
     1484        -sinix5.*)
     1485                os=`echo $os | sed -e 's|sinix|sysv|'`
     1486                ;;
     1487        -sinix*)
     1488                os=-sysv4
     1489                ;;
     1490        -tpf*)
     1491                os=-tpf
     1492                ;;
     1493        -triton*)
     1494                os=-sysv3
     1495                ;;
     1496        -oss*)
     1497                os=-sysv3
     1498                ;;
     1499        -svr4)
     1500                os=-sysv4
     1501                ;;
     1502        -svr3)
     1503                os=-sysv3
     1504                ;;
     1505        -sysvr4)
     1506                os=-sysv4
     1507                ;;
     1508        # This must come after -sysvr4.
     1509        -sysv*)
     1510                ;;
     1511        -ose*)
     1512                os=-ose
     1513                ;;
     1514        -es1800*)
     1515                os=-ose
     1516                ;;
     1517        -xenix)
     1518                os=-xenix
     1519                ;;
     1520        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
     1521                os=-mint
     1522                ;;
     1523        -aros*)
     1524                os=-aros
     1525                ;;
     1526        -zvmoe)
     1527                os=-zvmoe
     1528                ;;
     1529        -dicos*)
     1530                os=-dicos
     1531                ;;
     1532        -nacl*)
     1533                ;;
     1534        -none)
     1535                ;;
     1536        *)
     1537                # Get rid of the `-' at the beginning of $os.
     1538                os=`echo $os | sed 's/[^-]*-//'`
     1539                echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
     1540                exit 1
     1541                ;;
     1542esac
     1543else
     1544
     1545# Here we handle the default operating systems that come with various machines.
     1546# The value should be what the vendor currently ships out the door with their
     1547# machine or put another way, the most popular os provided with the machine.
     1548
     1549# Note that if you're going to try to match "-MANUFACTURER" here (say,
     1550# "-sun"), then you have to tell the case statement up towards the top
     1551# that MANUFACTURER isn't an operating system.  Otherwise, code above
     1552# will signal an error saying that MANUFACTURER isn't an operating
     1553# system, and we'll never get to this point.
     1554
     1555case $basic_machine in
     1556        score-*)
     1557                os=-elf
     1558                ;;
     1559        spu-*)
     1560                os=-elf
     1561                ;;
     1562        *-acorn)
     1563                os=-riscix1.2
     1564                ;;
     1565        arm*-rebel)
     1566                os=-linux
     1567                ;;
     1568        arm*-semi)
     1569                os=-aout
     1570                ;;
     1571        c4x-* | tic4x-*)
     1572                os=-coff
     1573                ;;
     1574        c8051-*)
     1575                os=-elf
     1576                ;;
     1577        hexagon-*)
     1578                os=-elf
     1579                ;;
     1580        tic54x-*)
     1581                os=-coff
     1582                ;;
     1583        tic55x-*)
     1584                os=-coff
     1585                ;;
     1586        tic6x-*)
     1587                os=-coff
     1588                ;;
     1589        # This must come before the *-dec entry.
     1590        pdp10-*)
     1591                os=-tops20
     1592                ;;
     1593        pdp11-*)
     1594                os=-none
     1595                ;;
     1596        *-dec | vax-*)
     1597                os=-ultrix4.2
     1598                ;;
     1599        m68*-apollo)
     1600                os=-domain
     1601                ;;
     1602        i386-sun)
     1603                os=-sunos4.0.2
     1604                ;;
     1605        m68000-sun)
     1606                os=-sunos3
     1607                ;;
     1608        m68*-cisco)
     1609                os=-aout
     1610                ;;
     1611        mep-*)
     1612                os=-elf
     1613                ;;
     1614        mips*-cisco)
     1615                os=-elf
     1616                ;;
     1617        mips*-*)
     1618                os=-elf
     1619                ;;
     1620        or32-*)
     1621                os=-coff
     1622                ;;
     1623        *-tti)  # must be before sparc entry or we get the wrong os.
     1624                os=-sysv3
     1625                ;;
     1626        sparc-* | *-sun)
     1627                os=-sunos4.1.1
     1628                ;;
     1629        *-be)
     1630                os=-beos
     1631                ;;
     1632        *-haiku)
     1633                os=-haiku
     1634                ;;
     1635        *-ibm)
     1636                os=-aix
     1637                ;;
     1638        *-knuth)
     1639                os=-mmixware
     1640                ;;
     1641        *-wec)
     1642                os=-proelf
     1643                ;;
     1644        *-winbond)
     1645                os=-proelf
     1646                ;;
     1647        *-oki)
     1648                os=-proelf
     1649                ;;
     1650        *-hp)
     1651                os=-hpux
     1652                ;;
     1653        *-hitachi)
     1654                os=-hiux
     1655                ;;
     1656        i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
     1657                os=-sysv
     1658                ;;
     1659        *-cbm)
     1660                os=-amigaos
     1661                ;;
     1662        *-dg)
     1663                os=-dgux
     1664                ;;
     1665        *-dolphin)
     1666                os=-sysv3
     1667                ;;
     1668        m68k-ccur)
     1669                os=-rtu
     1670                ;;
     1671        m88k-omron*)
     1672                os=-luna
     1673                ;;
     1674        *-next )
     1675                os=-nextstep
     1676                ;;
     1677        *-sequent)
     1678                os=-ptx
     1679                ;;
     1680        *-crds)
     1681                os=-unos
     1682                ;;
     1683        *-ns)
     1684                os=-genix
     1685                ;;
     1686        i370-*)
     1687                os=-mvs
     1688                ;;
     1689        *-next)
     1690                os=-nextstep3
     1691                ;;
     1692        *-gould)
     1693                os=-sysv
     1694                ;;
     1695        *-highlevel)
     1696                os=-bsd
     1697                ;;
     1698        *-encore)
     1699                os=-bsd
     1700                ;;
     1701        *-sgi)
     1702                os=-irix
     1703                ;;
     1704        *-siemens)
     1705                os=-sysv4
     1706                ;;
     1707        *-masscomp)
     1708                os=-rtu
     1709                ;;
     1710        f30[01]-fujitsu | f700-fujitsu)
     1711                os=-uxpv
     1712                ;;
     1713        *-rom68k)
     1714                os=-coff
     1715                ;;
     1716        *-*bug)
     1717                os=-coff
     1718                ;;
     1719        *-apple)
     1720                os=-macos
     1721                ;;
     1722        *-atari*)
     1723                os=-mint
     1724                ;;
     1725        *)
     1726                os=-none
     1727                ;;
     1728esac
     1729fi
     1730
     1731# Here we handle the case where we know the os, and the CPU type, but not the
     1732# manufacturer.  We pick the logical manufacturer.
     1733vendor=unknown
     1734case $basic_machine in
     1735        *-unknown)
     1736                case $os in
     1737                        -riscix*)
     1738                                vendor=acorn
     1739                                ;;
     1740                        -sunos*)
     1741                                vendor=sun
     1742                                ;;
     1743                        -cnk*|-aix*)
     1744                                vendor=ibm
     1745                                ;;
     1746                        -beos*)
     1747                                vendor=be
     1748                                ;;
     1749                        -hpux*)
     1750                                vendor=hp
     1751                                ;;
     1752                        -mpeix*)
     1753                                vendor=hp
     1754                                ;;
     1755                        -hiux*)
     1756                                vendor=hitachi
     1757                                ;;
     1758                        -unos*)
     1759                                vendor=crds
     1760                                ;;
     1761                        -dgux*)
     1762                                vendor=dg
     1763                                ;;
     1764                        -luna*)
     1765                                vendor=omron
     1766                                ;;
     1767                        -genix*)
     1768                                vendor=ns
     1769                                ;;
     1770                        -mvs* | -opened*)
     1771                                vendor=ibm
     1772                                ;;
     1773                        -os400*)
     1774                                vendor=ibm
     1775                                ;;
     1776                        -ptx*)
     1777                                vendor=sequent
     1778                                ;;
     1779                        -tpf*)
     1780                                vendor=ibm
     1781                                ;;
     1782                        -vxsim* | -vxworks* | -windiss*)
     1783                                vendor=wrs
     1784                                ;;
     1785                        -aux*)
     1786                                vendor=apple
     1787                                ;;
     1788                        -hms*)
     1789                                vendor=hitachi
     1790                                ;;
     1791                        -mpw* | -macos*)
     1792                                vendor=apple
     1793                                ;;
     1794                        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
     1795                                vendor=atari
     1796                                ;;
     1797                        -vos*)
     1798                                vendor=stratus
     1799                                ;;
     1800                esac
     1801                basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
     1802                ;;
     1803esac
     1804
     1805echo $basic_machine$os
     1806exit
     1807
     1808# Local variables:
     1809# eval: (add-hook 'write-file-hooks 'time-stamp)
     1810# time-stamp-start: "timestamp='"
     1811# time-stamp-format: "%:y-%02m-%02d"
     1812# time-stamp-end: "'"
     1813# End:
  • automake/depcomp

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/depcomp
     1#! /bin/sh
     2# depcomp - compile a program generating dependencies as side-effects
     3
     4scriptversion=2013-05-30.07; # UTC
     5
     6# Copyright (C) 1999-2014 Free Software Foundation, Inc.
     7
     8# This program is free software; you can redistribute it and/or modify
     9# it under the terms of the GNU General Public License as published by
     10# the Free Software Foundation; either version 2, or (at your option)
     11# any later version.
     12
     13# This program is distributed in the hope that it will be useful,
     14# but WITHOUT ANY WARRANTY; without even the implied warranty of
     15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16# GNU General Public License for more details.
     17
     18# You should have received a copy of the GNU General Public License
     19# along with this program.  If not, see <http://www.gnu.org/licenses/>.
     20
     21# As a special exception to the GNU General Public License, if you
     22# distribute this file as part of a program that contains a
     23# configuration script generated by Autoconf, you may include it under
     24# the same distribution terms that you use for the rest of that program.
     25
     26# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
     27
     28case $1 in
     29  '')
     30    echo "$0: No command.  Try '$0 --help' for more information." 1>&2
     31    exit 1;
     32    ;;
     33  -h | --h*)
     34    cat <<\EOF
     35Usage: depcomp [--help] [--version] PROGRAM [ARGS]
     36
     37Run PROGRAMS ARGS to compile a file, generating dependencies
     38as side-effects.
     39
     40Environment variables:
     41  depmode     Dependency tracking mode.
     42  source      Source file read by 'PROGRAMS ARGS'.
     43  object      Object file output by 'PROGRAMS ARGS'.
     44  DEPDIR      directory where to store dependencies.
     45  depfile     Dependency file to output.
     46  tmpdepfile  Temporary file to use when outputting dependencies.
     47  libtool     Whether libtool is used (yes/no).
     48
     49Report bugs to <bug-automake@gnu.org>.
     50EOF
     51    exit $?
     52    ;;
     53  -v | --v*)
     54    echo "depcomp $scriptversion"
     55    exit $?
     56    ;;
     57esac
     58
     59# Get the directory component of the given path, and save it in the
     60# global variables '$dir'.  Note that this directory component will
     61# be either empty or ending with a '/' character.  This is deliberate.
     62set_dir_from ()
     63{
     64  case $1 in
     65    */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
     66      *) dir=;;
     67  esac
     68}
     69
     70# Get the suffix-stripped basename of the given path, and save it the
     71# global variable '$base'.
     72set_base_from ()
     73{
     74  base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
     75}
     76
     77# If no dependency file was actually created by the compiler invocation,
     78# we still have to create a dummy depfile, to avoid errors with the
     79# Makefile "include basename.Plo" scheme.
     80make_dummy_depfile ()
     81{
     82  echo "#dummy" > "$depfile"
     83}
     84
     85# Factor out some common post-processing of the generated depfile.
     86# Requires the auxiliary global variable '$tmpdepfile' to be set.
     87aix_post_process_depfile ()
     88{
     89  # If the compiler actually managed to produce a dependency file,
     90  # post-process it.
     91  if test -f "$tmpdepfile"; then
     92    # Each line is of the form 'foo.o: dependency.h'.
     93    # Do two passes, one to just change these to
     94    #   $object: dependency.h
     95    # and one to simply output
     96    #   dependency.h:
     97    # which is needed to avoid the deleted-header problem.
     98    { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
     99      sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
     100    } > "$depfile"
     101    rm -f "$tmpdepfile"
     102  else
     103    make_dummy_depfile
     104  fi
     105}
     106
     107# A tabulation character.
     108tab='   '
     109# A newline character.
     110nl='
     111'
     112# Character ranges might be problematic outside the C locale.
     113# These definitions help.
     114upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
     115lower=abcdefghijklmnopqrstuvwxyz
     116digits=0123456789
     117alpha=${upper}${lower}
     118
     119if test -z "$depmode" || test -z "$source" || test -z "$object"; then
     120  echo "depcomp: Variables source, object and depmode must be set" 1>&2
     121  exit 1
     122fi
     123
     124# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
     125depfile=${depfile-`echo "$object" |
     126  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
     127tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
     128
     129rm -f "$tmpdepfile"
     130
     131# Avoid interferences from the environment.
     132gccflag= dashmflag=
     133
     134# Some modes work just like other modes, but use different flags.  We
     135# parameterize here, but still list the modes in the big case below,
     136# to make depend.m4 easier to write.  Note that we *cannot* use a case
     137# here, because this file can only contain one case statement.
     138if test "$depmode" = hp; then
     139  # HP compiler uses -M and no extra arg.
     140  gccflag=-M
     141  depmode=gcc
     142fi
     143
     144if test "$depmode" = dashXmstdout; then
     145  # This is just like dashmstdout with a different argument.
     146  dashmflag=-xM
     147  depmode=dashmstdout
     148fi
     149
     150cygpath_u="cygpath -u -f -"
     151if test "$depmode" = msvcmsys; then
     152  # This is just like msvisualcpp but w/o cygpath translation.
     153  # Just convert the backslash-escaped backslashes to single forward
     154  # slashes to satisfy depend.m4
     155  cygpath_u='sed s,\\\\,/,g'
     156  depmode=msvisualcpp
     157fi
     158
     159if test "$depmode" = msvc7msys; then
     160  # This is just like msvc7 but w/o cygpath translation.
     161  # Just convert the backslash-escaped backslashes to single forward
     162  # slashes to satisfy depend.m4
     163  cygpath_u='sed s,\\\\,/,g'
     164  depmode=msvc7
     165fi
     166
     167if test "$depmode" = xlc; then
     168  # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
     169  gccflag=-qmakedep=gcc,-MF
     170  depmode=gcc
     171fi
     172
     173case "$depmode" in
     174gcc3)
     175## gcc 3 implements dependency tracking that does exactly what
     176## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
     177## it if -MD -MP comes after the -MF stuff.  Hmm.
     178## Unfortunately, FreeBSD c89 acceptance of flags depends upon
     179## the command line argument order; so add the flags where they
     180## appear in depend2.am.  Note that the slowdown incurred here
     181## affects only configure: in makefiles, %FASTDEP% shortcuts this.
     182  for arg
     183  do
     184    case $arg in
     185    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
     186    *)  set fnord "$@" "$arg" ;;
     187    esac
     188    shift # fnord
     189    shift # $arg
     190  done
     191  "$@"
     192  stat=$?
     193  if test $stat -ne 0; then
     194    rm -f "$tmpdepfile"
     195    exit $stat
     196  fi
     197  mv "$tmpdepfile" "$depfile"
     198  ;;
     199
     200gcc)
     201## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
     202## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
     203## (see the conditional assignment to $gccflag above).
     204## There are various ways to get dependency output from gcc.  Here's
     205## why we pick this rather obscure method:
     206## - Don't want to use -MD because we'd like the dependencies to end
     207##   up in a subdir.  Having to rename by hand is ugly.
     208##   (We might end up doing this anyway to support other compilers.)
     209## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
     210##   -MM, not -M (despite what the docs say).  Also, it might not be
     211##   supported by the other compilers which use the 'gcc' depmode.
     212## - Using -M directly means running the compiler twice (even worse
     213##   than renaming).
     214  if test -z "$gccflag"; then
     215    gccflag=-MD,
     216  fi
     217  "$@" -Wp,"$gccflag$tmpdepfile"
     218  stat=$?
     219  if test $stat -ne 0; then
     220    rm -f "$tmpdepfile"
     221    exit $stat
     222  fi
     223  rm -f "$depfile"
     224  echo "$object : \\" > "$depfile"
     225  # The second -e expression handles DOS-style file names with drive
     226  # letters.
     227  sed -e 's/^[^:]*: / /' \
     228      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
     229## This next piece of magic avoids the "deleted header file" problem.
     230## The problem is that when a header file which appears in a .P file
     231## is deleted, the dependency causes make to die (because there is
     232## typically no way to rebuild the header).  We avoid this by adding
     233## dummy dependencies for each header file.  Too bad gcc doesn't do
     234## this for us directly.
     235## Some versions of gcc put a space before the ':'.  On the theory
     236## that the space means something, we add a space to the output as
     237## well.  hp depmode also adds that space, but also prefixes the VPATH
     238## to the object.  Take care to not repeat it in the output.
     239## Some versions of the HPUX 10.20 sed can't process this invocation
     240## correctly.  Breaking it into two sed invocations is a workaround.
     241  tr ' ' "$nl" < "$tmpdepfile" \
     242    | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
     243    | sed -e 's/$/ :/' >> "$depfile"
     244  rm -f "$tmpdepfile"
     245  ;;
     246
     247hp)
     248  # This case exists only to let depend.m4 do its work.  It works by
     249  # looking at the text of this script.  This case will never be run,
     250  # since it is checked for above.
     251  exit 1
     252  ;;
     253
     254sgi)
     255  if test "$libtool" = yes; then
     256    "$@" "-Wp,-MDupdate,$tmpdepfile"
     257  else
     258    "$@" -MDupdate "$tmpdepfile"
     259  fi
     260  stat=$?
     261  if test $stat -ne 0; then
     262    rm -f "$tmpdepfile"
     263    exit $stat
     264  fi
     265  rm -f "$depfile"
     266
     267  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
     268    echo "$object : \\" > "$depfile"
     269    # Clip off the initial element (the dependent).  Don't try to be
     270    # clever and replace this with sed code, as IRIX sed won't handle
     271    # lines with more than a fixed number of characters (4096 in
     272    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
     273    # the IRIX cc adds comments like '#:fec' to the end of the
     274    # dependency line.
     275    tr ' ' "$nl" < "$tmpdepfile" \
     276      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
     277      | tr "$nl" ' ' >> "$depfile"
     278    echo >> "$depfile"
     279    # The second pass generates a dummy entry for each header file.
     280    tr ' ' "$nl" < "$tmpdepfile" \
     281      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
     282      >> "$depfile"
     283  else
     284    make_dummy_depfile
     285  fi
     286  rm -f "$tmpdepfile"
     287  ;;
     288
     289xlc)
     290  # This case exists only to let depend.m4 do its work.  It works by
     291  # looking at the text of this script.  This case will never be run,
     292  # since it is checked for above.
     293  exit 1
     294  ;;
     295
     296aix)
     297  # The C for AIX Compiler uses -M and outputs the dependencies
     298  # in a .u file.  In older versions, this file always lives in the
     299  # current directory.  Also, the AIX compiler puts '$object:' at the
     300  # start of each line; $object doesn't have directory information.
     301  # Version 6 uses the directory in both cases.
     302  set_dir_from "$object"
     303  set_base_from "$object"
     304  if test "$libtool" = yes; then
     305    tmpdepfile1=$dir$base.u
     306    tmpdepfile2=$base.u
     307    tmpdepfile3=$dir.libs/$base.u
     308    "$@" -Wc,-M
     309  else
     310    tmpdepfile1=$dir$base.u
     311    tmpdepfile2=$dir$base.u
     312    tmpdepfile3=$dir$base.u
     313    "$@" -M
     314  fi
     315  stat=$?
     316  if test $stat -ne 0; then
     317    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
     318    exit $stat
     319  fi
     320
     321  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
     322  do
     323    test -f "$tmpdepfile" && break
     324  done
     325  aix_post_process_depfile
     326  ;;
     327
     328tcc)
     329  # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
     330  # FIXME: That version still under development at the moment of writing.
     331  #        Make that this statement remains true also for stable, released
     332  #        versions.
     333  # It will wrap lines (doesn't matter whether long or short) with a
     334  # trailing '\', as in:
     335  #
     336  #   foo.o : \
     337  #    foo.c \
     338  #    foo.h \
     339  #
     340  # It will put a trailing '\' even on the last line, and will use leading
     341  # spaces rather than leading tabs (at least since its commit 0394caf7
     342  # "Emit spaces for -MD").
     343  "$@" -MD -MF "$tmpdepfile"
     344  stat=$?
     345  if test $stat -ne 0; then
     346    rm -f "$tmpdepfile"
     347    exit $stat
     348  fi
     349  rm -f "$depfile"
     350  # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
     351  # We have to change lines of the first kind to '$object: \'.
     352  sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
     353  # And for each line of the second kind, we have to emit a 'dep.h:'
     354  # dummy dependency, to avoid the deleted-header problem.
     355  sed -n -e 's|^  *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
     356  rm -f "$tmpdepfile"
     357  ;;
     358
     359## The order of this option in the case statement is important, since the
     360## shell code in configure will try each of these formats in the order
     361## listed in this file.  A plain '-MD' option would be understood by many
     362## compilers, so we must ensure this comes after the gcc and icc options.
     363pgcc)
     364  # Portland's C compiler understands '-MD'.
     365  # Will always output deps to 'file.d' where file is the root name of the
     366  # source file under compilation, even if file resides in a subdirectory.
     367  # The object file name does not affect the name of the '.d' file.
     368  # pgcc 10.2 will output
     369  #    foo.o: sub/foo.c sub/foo.h
     370  # and will wrap long lines using '\' :
     371  #    foo.o: sub/foo.c ... \
     372  #     sub/foo.h ... \
     373  #     ...
     374  set_dir_from "$object"
     375  # Use the source, not the object, to determine the base name, since
     376  # that's sadly what pgcc will do too.
     377  set_base_from "$source"
     378  tmpdepfile=$base.d
     379
     380  # For projects that build the same source file twice into different object
     381  # files, the pgcc approach of using the *source* file root name can cause
     382  # problems in parallel builds.  Use a locking strategy to avoid stomping on
     383  # the same $tmpdepfile.
     384  lockdir=$base.d-lock
     385  trap "
     386    echo '$0: caught signal, cleaning up...' >&2
     387    rmdir '$lockdir'
     388    exit 1
     389  " 1 2 13 15
     390  numtries=100
     391  i=$numtries
     392  while test $i -gt 0; do
     393    # mkdir is a portable test-and-set.
     394    if mkdir "$lockdir" 2>/dev/null; then
     395      # This process acquired the lock.
     396      "$@" -MD
     397      stat=$?
     398      # Release the lock.
     399      rmdir "$lockdir"
     400      break
     401    else
     402      # If the lock is being held by a different process, wait
     403      # until the winning process is done or we timeout.
     404      while test -d "$lockdir" && test $i -gt 0; do
     405        sleep 1
     406        i=`expr $i - 1`
     407      done
     408    fi
     409    i=`expr $i - 1`
     410  done
     411  trap - 1 2 13 15
     412  if test $i -le 0; then
     413    echo "$0: failed to acquire lock after $numtries attempts" >&2
     414    echo "$0: check lockdir '$lockdir'" >&2
     415    exit 1
     416  fi
     417
     418  if test $stat -ne 0; then
     419    rm -f "$tmpdepfile"
     420    exit $stat
     421  fi
     422  rm -f "$depfile"
     423  # Each line is of the form `foo.o: dependent.h',
     424  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
     425  # Do two passes, one to just change these to
     426  # `$object: dependent.h' and one to simply `dependent.h:'.
     427  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
     428  # Some versions of the HPUX 10.20 sed can't process this invocation
     429  # correctly.  Breaking it into two sed invocations is a workaround.
     430  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
     431    | sed -e 's/$/ :/' >> "$depfile"
     432  rm -f "$tmpdepfile"
     433  ;;
     434
     435hp2)
     436  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
     437  # compilers, which have integrated preprocessors.  The correct option
     438  # to use with these is +Maked; it writes dependencies to a file named
     439  # 'foo.d', which lands next to the object file, wherever that
     440  # happens to be.
     441  # Much of this is similar to the tru64 case; see comments there.
     442  set_dir_from  "$object"
     443  set_base_from "$object"
     444  if test "$libtool" = yes; then
     445    tmpdepfile1=$dir$base.d
     446    tmpdepfile2=$dir.libs/$base.d
     447    "$@" -Wc,+Maked
     448  else
     449    tmpdepfile1=$dir$base.d
     450    tmpdepfile2=$dir$base.d
     451    "$@" +Maked
     452  fi
     453  stat=$?
     454  if test $stat -ne 0; then
     455     rm -f "$tmpdepfile1" "$tmpdepfile2"
     456     exit $stat
     457  fi
     458
     459  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
     460  do
     461    test -f "$tmpdepfile" && break
     462  done
     463  if test -f "$tmpdepfile"; then
     464    sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
     465    # Add 'dependent.h:' lines.
     466    sed -ne '2,${
     467               s/^ *//
     468               s/ \\*$//
     469               s/$/:/
     470               p
     471             }' "$tmpdepfile" >> "$depfile"
     472  else
     473    make_dummy_depfile
     474  fi
     475  rm -f "$tmpdepfile" "$tmpdepfile2"
     476  ;;
     477
     478tru64)
     479  # The Tru64 compiler uses -MD to generate dependencies as a side
     480  # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
     481  # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
     482  # dependencies in 'foo.d' instead, so we check for that too.
     483  # Subdirectories are respected.
     484  set_dir_from  "$object"
     485  set_base_from "$object"
     486
     487  if test "$libtool" = yes; then
     488    # Libtool generates 2 separate objects for the 2 libraries.  These
     489    # two compilations output dependencies in $dir.libs/$base.o.d and
     490    # in $dir$base.o.d.  We have to check for both files, because
     491    # one of the two compilations can be disabled.  We should prefer
     492    # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
     493    # automatically cleaned when .libs/ is deleted, while ignoring
     494    # the former would cause a distcleancheck panic.
     495    tmpdepfile1=$dir$base.o.d          # libtool 1.5
     496    tmpdepfile2=$dir.libs/$base.o.d    # Likewise.
     497    tmpdepfile3=$dir.libs/$base.d      # Compaq CCC V6.2-504
     498    "$@" -Wc,-MD
     499  else
     500    tmpdepfile1=$dir$base.d
     501    tmpdepfile2=$dir$base.d
     502    tmpdepfile3=$dir$base.d
     503    "$@" -MD
     504  fi
     505
     506  stat=$?
     507  if test $stat -ne 0; then
     508    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
     509    exit $stat
     510  fi
     511
     512  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
     513  do
     514    test -f "$tmpdepfile" && break
     515  done
     516  # Same post-processing that is required for AIX mode.
     517  aix_post_process_depfile
     518  ;;
     519
     520msvc7)
     521  if test "$libtool" = yes; then
     522    showIncludes=-Wc,-showIncludes
     523  else
     524    showIncludes=-showIncludes
     525  fi
     526  "$@" $showIncludes > "$tmpdepfile"
     527  stat=$?
     528  grep -v '^Note: including file: ' "$tmpdepfile"
     529  if test $stat -ne 0; then
     530    rm -f "$tmpdepfile"
     531    exit $stat
     532  fi
     533  rm -f "$depfile"
     534  echo "$object : \\" > "$depfile"
     535  # The first sed program below extracts the file names and escapes
     536  # backslashes for cygpath.  The second sed program outputs the file
     537  # name when reading, but also accumulates all include files in the
     538  # hold buffer in order to output them again at the end.  This only
     539  # works with sed implementations that can handle large buffers.
     540  sed < "$tmpdepfile" -n '
     541/^Note: including file:  *\(.*\)/ {
     542  s//\1/
     543  s/\\/\\\\/g
     544  p
     545}' | $cygpath_u | sort -u | sed -n '
     546s/ /\\ /g
     547s/\(.*\)/'"$tab"'\1 \\/p
     548s/.\(.*\) \\/\1:/
     549H
     550$ {
     551  s/.*/'"$tab"'/
     552  G
     553  p
     554}' >> "$depfile"
     555  echo >> "$depfile" # make sure the fragment doesn't end with a backslash
     556  rm -f "$tmpdepfile"
     557  ;;
     558
     559msvc7msys)
     560  # This case exists only to let depend.m4 do its work.  It works by
     561  # looking at the text of this script.  This case will never be run,
     562  # since it is checked for above.
     563  exit 1
     564  ;;
     565
     566#nosideeffect)
     567  # This comment above is used by automake to tell side-effect
     568  # dependency tracking mechanisms from slower ones.
     569
     570dashmstdout)
     571  # Important note: in order to support this mode, a compiler *must*
     572  # always write the preprocessed file to stdout, regardless of -o.
     573  "$@" || exit $?
     574
     575  # Remove the call to Libtool.
     576  if test "$libtool" = yes; then
     577    while test "X$1" != 'X--mode=compile'; do
     578      shift
     579    done
     580    shift
     581  fi
     582
     583  # Remove '-o $object'.
     584  IFS=" "
     585  for arg
     586  do
     587    case $arg in
     588    -o)
     589      shift
     590      ;;
     591    $object)
     592      shift
     593      ;;
     594    *)
     595      set fnord "$@" "$arg"
     596      shift # fnord
     597      shift # $arg
     598      ;;
     599    esac
     600  done
     601
     602  test -z "$dashmflag" && dashmflag=-M
     603  # Require at least two characters before searching for ':'
     604  # in the target name.  This is to cope with DOS-style filenames:
     605  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
     606  "$@" $dashmflag |
     607    sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
     608  rm -f "$depfile"
     609  cat < "$tmpdepfile" > "$depfile"
     610  # Some versions of the HPUX 10.20 sed can't process this sed invocation
     611  # correctly.  Breaking it into two sed invocations is a workaround.
     612  tr ' ' "$nl" < "$tmpdepfile" \
     613    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
     614    | sed -e 's/$/ :/' >> "$depfile"
     615  rm -f "$tmpdepfile"
     616  ;;
     617
     618dashXmstdout)
     619  # This case only exists to satisfy depend.m4.  It is never actually
     620  # run, as this mode is specially recognized in the preamble.
     621  exit 1
     622  ;;
     623
     624makedepend)
     625  "$@" || exit $?
     626  # Remove any Libtool call
     627  if test "$libtool" = yes; then
     628    while test "X$1" != 'X--mode=compile'; do
     629      shift
     630    done
     631    shift
     632  fi
     633  # X makedepend
     634  shift
     635  cleared=no eat=no
     636  for arg
     637  do
     638    case $cleared in
     639    no)
     640      set ""; shift
     641      cleared=yes ;;
     642    esac
     643    if test $eat = yes; then
     644      eat=no
     645      continue
     646    fi
     647    case "$arg" in
     648    -D*|-I*)
     649      set fnord "$@" "$arg"; shift ;;
     650    # Strip any option that makedepend may not understand.  Remove
     651    # the object too, otherwise makedepend will parse it as a source file.
     652    -arch)
     653      eat=yes ;;
     654    -*|$object)
     655      ;;
     656    *)
     657      set fnord "$@" "$arg"; shift ;;
     658    esac
     659  done
     660  obj_suffix=`echo "$object" | sed 's/^.*\././'`
     661  touch "$tmpdepfile"
     662  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
     663  rm -f "$depfile"
     664  # makedepend may prepend the VPATH from the source file name to the object.
     665  # No need to regex-escape $object, excess matching of '.' is harmless.
     666  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
     667  # Some versions of the HPUX 10.20 sed can't process the last invocation
     668  # correctly.  Breaking it into two sed invocations is a workaround.
     669  sed '1,2d' "$tmpdepfile" \
     670    | tr ' ' "$nl" \
     671    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
     672    | sed -e 's/$/ :/' >> "$depfile"
     673  rm -f "$tmpdepfile" "$tmpdepfile".bak
     674  ;;
     675
     676cpp)
     677  # Important note: in order to support this mode, a compiler *must*
     678  # always write the preprocessed file to stdout.
     679  "$@" || exit $?
     680
     681  # Remove the call to Libtool.
     682  if test "$libtool" = yes; then
     683    while test "X$1" != 'X--mode=compile'; do
     684      shift
     685    done
     686    shift
     687  fi
     688
     689  # Remove '-o $object'.
     690  IFS=" "
     691  for arg
     692  do
     693    case $arg in
     694    -o)
     695      shift
     696      ;;
     697    $object)
     698      shift
     699      ;;
     700    *)
     701      set fnord "$@" "$arg"
     702      shift # fnord
     703      shift # $arg
     704      ;;
     705    esac
     706  done
     707
     708  "$@" -E \
     709    | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
     710             -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
     711    | sed '$ s: \\$::' > "$tmpdepfile"
     712  rm -f "$depfile"
     713  echo "$object : \\" > "$depfile"
     714  cat < "$tmpdepfile" >> "$depfile"
     715  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
     716  rm -f "$tmpdepfile"
     717  ;;
     718
     719msvisualcpp)
     720  # Important note: in order to support this mode, a compiler *must*
     721  # always write the preprocessed file to stdout.
     722  "$@" || exit $?
     723
     724  # Remove the call to Libtool.
     725  if test "$libtool" = yes; then
     726    while test "X$1" != 'X--mode=compile'; do
     727      shift
     728    done
     729    shift
     730  fi
     731
     732  IFS=" "
     733  for arg
     734  do
     735    case "$arg" in
     736    -o)
     737      shift
     738      ;;
     739    $object)
     740      shift
     741      ;;
     742    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
     743        set fnord "$@"
     744        shift
     745        shift
     746        ;;
     747    *)
     748        set fnord "$@" "$arg"
     749        shift
     750        shift
     751        ;;
     752    esac
     753  done
     754  "$@" -E 2>/dev/null |
     755  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
     756  rm -f "$depfile"
     757  echo "$object : \\" > "$depfile"
     758  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
     759  echo "$tab" >> "$depfile"
     760  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
     761  rm -f "$tmpdepfile"
     762  ;;
     763
     764msvcmsys)
     765  # This case exists only to let depend.m4 do its work.  It works by
     766  # looking at the text of this script.  This case will never be run,
     767  # since it is checked for above.
     768  exit 1
     769  ;;
     770
     771none)
     772  exec "$@"
     773  ;;
     774
     775*)
     776  echo "Unknown depmode $depmode" 1>&2
     777  exit 1
     778  ;;
     779esac
     780
     781exit 0
     782
     783# Local Variables:
     784# mode: shell-script
     785# sh-indentation: 2
     786# eval: (add-hook 'write-file-hooks 'time-stamp)
     787# time-stamp-start: "scriptversion="
     788# time-stamp-format: "%:y-%02m-%02d.%02H"
     789# time-stamp-time-zone: "UTC"
     790# time-stamp-end: "; # UTC"
     791# End:
  • automake/install-sh

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/install-sh
     1#!/bin/sh
     2# install - install a program, script, or datafile
     3
     4scriptversion=2014-09-12.12; # UTC
     5
     6# This originates from X11R5 (mit/util/scripts/install.sh), which was
     7# later released in X11R6 (xc/config/util/install.sh) with the
     8# following copyright and license.
     9#
     10# Copyright (C) 1994 X Consortium
     11#
     12# Permission is hereby granted, free of charge, to any person obtaining a copy
     13# of this software and associated documentation files (the "Software"), to
     14# deal in the Software without restriction, including without limitation the
     15# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     16# sell copies of the Software, and to permit persons to whom the Software is
     17# furnished to do so, subject to the following conditions:
     18#
     19# The above copyright notice and this permission notice shall be included in
     20# all copies or substantial portions of the Software.
     21#
     22# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     25# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     26# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
     27# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     28#
     29# Except as contained in this notice, the name of the X Consortium shall not
     30# be used in advertising or otherwise to promote the sale, use or other deal-
     31# ings in this Software without prior written authorization from the X Consor-
     32# tium.
     33#
     34#
     35# FSF changes to this file are in the public domain.
     36#
     37# Calling this script install-sh is preferred over install.sh, to prevent
     38# 'make' implicit rules from creating a file called install from it
     39# when there is no Makefile.
     40#
     41# This script is compatible with the BSD install script, but was written
     42# from scratch.
     43
     44tab='   '
     45nl='
     46'
     47IFS=" $tab$nl"
     48
     49# Set DOITPROG to "echo" to test this script.
     50
     51doit=${DOITPROG-}
     52doit_exec=${doit:-exec}
     53
     54# Put in absolute file names if you don't have them in your path;
     55# or use environment vars.
     56
     57chgrpprog=${CHGRPPROG-chgrp}
     58chmodprog=${CHMODPROG-chmod}
     59chownprog=${CHOWNPROG-chown}
     60cmpprog=${CMPPROG-cmp}
     61cpprog=${CPPROG-cp}
     62mkdirprog=${MKDIRPROG-mkdir}
     63mvprog=${MVPROG-mv}
     64rmprog=${RMPROG-rm}
     65stripprog=${STRIPPROG-strip}
     66
     67posix_mkdir=
     68
     69# Desired mode of installed file.
     70mode=0755
     71
     72chgrpcmd=
     73chmodcmd=$chmodprog
     74chowncmd=
     75mvcmd=$mvprog
     76rmcmd="$rmprog -f"
     77stripcmd=
     78
     79src=
     80dst=
     81dir_arg=
     82dst_arg=
     83
     84copy_on_change=false
     85is_target_a_directory=possibly
     86
     87usage="\
     88Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
     89   or: $0 [OPTION]... SRCFILES... DIRECTORY
     90   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
     91   or: $0 [OPTION]... -d DIRECTORIES...
     92
     93In the 1st form, copy SRCFILE to DSTFILE.
     94In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
     95In the 4th, create DIRECTORIES.
     96
     97Options:
     98     --help     display this help and exit.
     99     --version  display version info and exit.
     100
     101  -c            (ignored)
     102  -C            install only if different (preserve the last data modification time)
     103  -d            create directories instead of installing files.
     104  -g GROUP      $chgrpprog installed files to GROUP.
     105  -m MODE       $chmodprog installed files to MODE.
     106  -o USER       $chownprog installed files to USER.
     107  -s            $stripprog installed files.
     108  -t DIRECTORY  install into DIRECTORY.
     109  -T            report an error if DSTFILE is a directory.
     110
     111Environment variables override the default commands:
     112  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
     113  RMPROG STRIPPROG
     114"
     115
     116while test $# -ne 0; do
     117  case $1 in
     118    -c) ;;
     119
     120    -C) copy_on_change=true;;
     121
     122    -d) dir_arg=true;;
     123
     124    -g) chgrpcmd="$chgrpprog $2"
     125        shift;;
     126
     127    --help) echo "$usage"; exit $?;;
     128
     129    -m) mode=$2
     130        case $mode in
     131          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
     132            echo "$0: invalid mode: $mode" >&2
     133            exit 1;;
     134        esac
     135        shift;;
     136
     137    -o) chowncmd="$chownprog $2"
     138        shift;;
     139
     140    -s) stripcmd=$stripprog;;
     141
     142    -t)
     143        is_target_a_directory=always
     144        dst_arg=$2
     145        # Protect names problematic for 'test' and other utilities.
     146        case $dst_arg in
     147          -* | [=\(\)!]) dst_arg=./$dst_arg;;
     148        esac
     149        shift;;
     150
     151    -T) is_target_a_directory=never;;
     152
     153    --version) echo "$0 $scriptversion"; exit $?;;
     154
     155    --) shift
     156        break;;
     157
     158    -*) echo "$0: invalid option: $1" >&2
     159        exit 1;;
     160
     161    *)  break;;
     162  esac
     163  shift
     164done
     165
     166# We allow the use of options -d and -T together, by making -d
     167# take the precedence; this is for compatibility with GNU install.
     168
     169if test -n "$dir_arg"; then
     170  if test -n "$dst_arg"; then
     171    echo "$0: target directory not allowed when installing a directory." >&2
     172    exit 1
     173  fi
     174fi
     175
     176if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
     177  # When -d is used, all remaining arguments are directories to create.
     178  # When -t is used, the destination is already specified.
     179  # Otherwise, the last argument is the destination.  Remove it from $@.
     180  for arg
     181  do
     182    if test -n "$dst_arg"; then
     183      # $@ is not empty: it contains at least $arg.
     184      set fnord "$@" "$dst_arg"
     185      shift # fnord
     186    fi
     187    shift # arg
     188    dst_arg=$arg
     189    # Protect names problematic for 'test' and other utilities.
     190    case $dst_arg in
     191      -* | [=\(\)!]) dst_arg=./$dst_arg;;
     192    esac
     193  done
     194fi
     195
     196if test $# -eq 0; then
     197  if test -z "$dir_arg"; then
     198    echo "$0: no input file specified." >&2
     199    exit 1
     200  fi
     201  # It's OK to call 'install-sh -d' without argument.
     202  # This can happen when creating conditional directories.
     203  exit 0
     204fi
     205
     206if test -z "$dir_arg"; then
     207  if test $# -gt 1 || test "$is_target_a_directory" = always; then
     208    if test ! -d "$dst_arg"; then
     209      echo "$0: $dst_arg: Is not a directory." >&2
     210      exit 1
     211    fi
     212  fi
     213fi
     214
     215if test -z "$dir_arg"; then
     216  do_exit='(exit $ret); exit $ret'
     217  trap "ret=129; $do_exit" 1
     218  trap "ret=130; $do_exit" 2
     219  trap "ret=141; $do_exit" 13
     220  trap "ret=143; $do_exit" 15
     221
     222  # Set umask so as not to create temps with too-generous modes.
     223  # However, 'strip' requires both read and write access to temps.
     224  case $mode in
     225    # Optimize common cases.
     226    *644) cp_umask=133;;
     227    *755) cp_umask=22;;
     228
     229    *[0-7])
     230      if test -z "$stripcmd"; then
     231        u_plus_rw=
     232      else
     233        u_plus_rw='% 200'
     234      fi
     235      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
     236    *)
     237      if test -z "$stripcmd"; then
     238        u_plus_rw=
     239      else
     240        u_plus_rw=,u+rw
     241      fi
     242      cp_umask=$mode$u_plus_rw;;
     243  esac
     244fi
     245
     246for src
     247do
     248  # Protect names problematic for 'test' and other utilities.
     249  case $src in
     250    -* | [=\(\)!]) src=./$src;;
     251  esac
     252
     253  if test -n "$dir_arg"; then
     254    dst=$src
     255    dstdir=$dst
     256    test -d "$dstdir"
     257    dstdir_status=$?
     258  else
     259
     260    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
     261    # might cause directories to be created, which would be especially bad
     262    # if $src (and thus $dsttmp) contains '*'.
     263    if test ! -f "$src" && test ! -d "$src"; then
     264      echo "$0: $src does not exist." >&2
     265      exit 1
     266    fi
     267
     268    if test -z "$dst_arg"; then
     269      echo "$0: no destination specified." >&2
     270      exit 1
     271    fi
     272    dst=$dst_arg
     273
     274    # If destination is a directory, append the input filename; won't work
     275    # if double slashes aren't ignored.
     276    if test -d "$dst"; then
     277      if test "$is_target_a_directory" = never; then
     278        echo "$0: $dst_arg: Is a directory" >&2
     279        exit 1
     280      fi
     281      dstdir=$dst
     282      dst=$dstdir/`basename "$src"`
     283      dstdir_status=0
     284    else
     285      dstdir=`dirname "$dst"`
     286      test -d "$dstdir"
     287      dstdir_status=$?
     288    fi
     289  fi
     290
     291  obsolete_mkdir_used=false
     292
     293  if test $dstdir_status != 0; then
     294    case $posix_mkdir in
     295      '')
     296        # Create intermediate dirs using mode 755 as modified by the umask.
     297        # This is like FreeBSD 'install' as of 1997-10-28.
     298        umask=`umask`
     299        case $stripcmd.$umask in
     300          # Optimize common cases.
     301          *[2367][2367]) mkdir_umask=$umask;;
     302          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
     303
     304          *[0-7])
     305            mkdir_umask=`expr $umask + 22 \
     306              - $umask % 100 % 40 + $umask % 20 \
     307              - $umask % 10 % 4 + $umask % 2
     308            `;;
     309          *) mkdir_umask=$umask,go-w;;
     310        esac
     311
     312        # With -d, create the new directory with the user-specified mode.
     313        # Otherwise, rely on $mkdir_umask.
     314        if test -n "$dir_arg"; then
     315          mkdir_mode=-m$mode
     316        else
     317          mkdir_mode=
     318        fi
     319
     320        posix_mkdir=false
     321        case $umask in
     322          *[123567][0-7][0-7])
     323            # POSIX mkdir -p sets u+wx bits regardless of umask, which
     324            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
     325            ;;
     326          *)
     327            # $RANDOM is not portable (e.g. dash);  use it when possible to
     328            # lower collision chance
     329            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
     330            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
     331
     332            # As "mkdir -p" follows symlinks and we work in /tmp possibly;  so
     333            # create the $tmpdir first (and fail if unsuccessful) to make sure
     334            # that nobody tries to guess the $tmpdir name.
     335            if (umask $mkdir_umask &&
     336                $mkdirprog $mkdir_mode "$tmpdir" &&
     337                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
     338            then
     339              if test -z "$dir_arg" || {
     340                   # Check for POSIX incompatibilities with -m.
     341                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
     342                   # other-writable bit of parent directory when it shouldn't.
     343                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
     344                   test_tmpdir="$tmpdir/a"
     345                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
     346                   case $ls_ld_tmpdir in
     347                     d????-?r-*) different_mode=700;;
     348                     d????-?--*) different_mode=755;;
     349                     *) false;;
     350                   esac &&
     351                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
     352                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
     353                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
     354                   }
     355                 }
     356              then posix_mkdir=:
     357              fi
     358              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
     359            else
     360              # Remove any dirs left behind by ancient mkdir implementations.
     361              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
     362            fi
     363            trap '' 0;;
     364        esac;;
     365    esac
     366
     367    if
     368      $posix_mkdir && (
     369        umask $mkdir_umask &&
     370        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
     371      )
     372    then :
     373    else
     374
     375      # The umask is ridiculous, or mkdir does not conform to POSIX,
     376      # or it failed possibly due to a race condition.  Create the
     377      # directory the slow way, step by step, checking for races as we go.
     378
     379      case $dstdir in
     380        /*) prefix='/';;
     381        [-=\(\)!]*) prefix='./';;
     382        *)  prefix='';;
     383      esac
     384
     385      oIFS=$IFS
     386      IFS=/
     387      set -f
     388      set fnord $dstdir
     389      shift
     390      set +f
     391      IFS=$oIFS
     392
     393      prefixes=
     394
     395      for d
     396      do
     397        test X"$d" = X && continue
     398
     399        prefix=$prefix$d
     400        if test -d "$prefix"; then
     401          prefixes=
     402        else
     403          if $posix_mkdir; then
     404            (umask=$mkdir_umask &&
     405             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
     406            # Don't fail if two instances are running concurrently.
     407            test -d "$prefix" || exit 1
     408          else
     409            case $prefix in
     410              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
     411              *) qprefix=$prefix;;
     412            esac
     413            prefixes="$prefixes '$qprefix'"
     414          fi
     415        fi
     416        prefix=$prefix/
     417      done
     418
     419      if test -n "$prefixes"; then
     420        # Don't fail if two instances are running concurrently.
     421        (umask $mkdir_umask &&
     422         eval "\$doit_exec \$mkdirprog $prefixes") ||
     423          test -d "$dstdir" || exit 1
     424        obsolete_mkdir_used=true
     425      fi
     426    fi
     427  fi
     428
     429  if test -n "$dir_arg"; then
     430    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
     431    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
     432    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
     433      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
     434  else
     435
     436    # Make a couple of temp file names in the proper directory.
     437    dsttmp=$dstdir/_inst.$$_
     438    rmtmp=$dstdir/_rm.$$_
     439
     440    # Trap to clean up those temp files at exit.
     441    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
     442
     443    # Copy the file name to the temp name.
     444    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
     445
     446    # and set any options; do chmod last to preserve setuid bits.
     447    #
     448    # If any of these fail, we abort the whole thing.  If we want to
     449    # ignore errors from any of these, just make sure not to ignore
     450    # errors from the above "$doit $cpprog $src $dsttmp" command.
     451    #
     452    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
     453    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
     454    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
     455    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
     456
     457    # If -C, don't bother to copy if it wouldn't change the file.
     458    if $copy_on_change &&
     459       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
     460       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
     461       set -f &&
     462       set X $old && old=:$2:$4:$5:$6 &&
     463       set X $new && new=:$2:$4:$5:$6 &&
     464       set +f &&
     465       test "$old" = "$new" &&
     466       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
     467    then
     468      rm -f "$dsttmp"
     469    else
     470      # Rename the file to the real destination.
     471      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
     472
     473      # The rename failed, perhaps because mv can't rename something else
     474      # to itself, or perhaps because mv is so ancient that it does not
     475      # support -f.
     476      {
     477        # Now remove or move aside any old file at destination location.
     478        # We try this two ways since rm can't unlink itself on some
     479        # systems and the destination file might be busy for other
     480        # reasons.  In this case, the final cleanup might fail but the new
     481        # file should still install successfully.
     482        {
     483          test ! -f "$dst" ||
     484          $doit $rmcmd -f "$dst" 2>/dev/null ||
     485          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
     486            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
     487          } ||
     488          { echo "$0: cannot unlink or rename $dst" >&2
     489            (exit 1); exit 1
     490          }
     491        } &&
     492
     493        # Now rename the file to the real destination.
     494        $doit $mvcmd "$dsttmp" "$dst"
     495      }
     496    fi || exit 1
     497
     498    trap '' 0
     499  fi
     500done
     501
     502# Local variables:
     503# eval: (add-hook 'write-file-hooks 'time-stamp)
     504# time-stamp-start: "scriptversion="
     505# time-stamp-format: "%:y-%02m-%02d.%02H"
     506# time-stamp-time-zone: "UTC"
     507# time-stamp-end: "; # UTC"
     508# End:
  • automake/missing

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/missing
     1#! /bin/sh
     2# Common wrapper for a few potentially missing GNU programs.
     3
     4scriptversion=2013-10-28.13; # UTC
     5
     6# Copyright (C) 1996-2014 Free Software Foundation, Inc.
     7# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
     8
     9# This program is free software; you can redistribute it and/or modify
     10# it under the terms of the GNU General Public License as published by
     11# the Free Software Foundation; either version 2, or (at your option)
     12# any later version.
     13
     14# This program is distributed in the hope that it will be useful,
     15# but WITHOUT ANY WARRANTY; without even the implied warranty of
     16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17# GNU General Public License for more details.
     18
     19# You should have received a copy of the GNU General Public License
     20# along with this program.  If not, see <http://www.gnu.org/licenses/>.
     21
     22# As a special exception to the GNU General Public License, if you
     23# distribute this file as part of a program that contains a
     24# configuration script generated by Autoconf, you may include it under
     25# the same distribution terms that you use for the rest of that program.
     26
     27if test $# -eq 0; then
     28  echo 1>&2 "Try '$0 --help' for more information"
     29  exit 1
     30fi
     31
     32case $1 in
     33
     34  --is-lightweight)
     35    # Used by our autoconf macros to check whether the available missing
     36    # script is modern enough.
     37    exit 0
     38    ;;
     39
     40  --run)
     41    # Back-compat with the calling convention used by older automake.
     42    shift
     43    ;;
     44
     45  -h|--h|--he|--hel|--help)
     46    echo "\
     47$0 [OPTION]... PROGRAM [ARGUMENT]...
     48
     49Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
     50to PROGRAM being missing or too old.
     51
     52Options:
     53  -h, --help      display this help and exit
     54  -v, --version   output version information and exit
     55
     56Supported PROGRAM values:
     57  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
     58  bison     yacc      flex         lex       help2man
     59
     60Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
     61'g' are ignored when checking the name.
     62
     63Send bug reports to <bug-automake@gnu.org>."
     64    exit $?
     65    ;;
     66
     67  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
     68    echo "missing $scriptversion (GNU Automake)"
     69    exit $?
     70    ;;
     71
     72  -*)
     73    echo 1>&2 "$0: unknown '$1' option"
     74    echo 1>&2 "Try '$0 --help' for more information"
     75    exit 1
     76    ;;
     77
     78esac
     79
     80# Run the given program, remember its exit status.
     81"$@"; st=$?
     82
     83# If it succeeded, we are done.
     84test $st -eq 0 && exit 0
     85
     86# Also exit now if we it failed (or wasn't found), and '--version' was
     87# passed; such an option is passed most likely to detect whether the
     88# program is present and works.
     89case $2 in --version|--help) exit $st;; esac
     90
     91# Exit code 63 means version mismatch.  This often happens when the user
     92# tries to use an ancient version of a tool on a file that requires a
     93# minimum version.
     94if test $st -eq 63; then
     95  msg="probably too old"
     96elif test $st -eq 127; then
     97  # Program was missing.
     98  msg="missing on your system"
     99else
     100  # Program was found and executed, but failed.  Give up.
     101  exit $st
     102fi
     103
     104perl_URL=http://www.perl.org/
     105flex_URL=http://flex.sourceforge.net/
     106gnu_software_URL=http://www.gnu.org/software
     107
     108program_details ()
     109{
     110  case $1 in
     111    aclocal|automake)
     112      echo "The '$1' program is part of the GNU Automake package:"
     113      echo "<$gnu_software_URL/automake>"
     114      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
     115      echo "<$gnu_software_URL/autoconf>"
     116      echo "<$gnu_software_URL/m4/>"
     117      echo "<$perl_URL>"
     118      ;;
     119    autoconf|autom4te|autoheader)
     120      echo "The '$1' program is part of the GNU Autoconf package:"
     121      echo "<$gnu_software_URL/autoconf/>"
     122      echo "It also requires GNU m4 and Perl in order to run:"
     123      echo "<$gnu_software_URL/m4/>"
     124      echo "<$perl_URL>"
     125      ;;
     126  esac
     127}
     128
     129give_advice ()
     130{
     131  # Normalize program name to check for.
     132  normalized_program=`echo "$1" | sed '
     133    s/^gnu-//; t
     134    s/^gnu//; t
     135    s/^g//; t'`
     136
     137  printf '%s\n' "'$1' is $msg."
     138
     139  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
     140  case $normalized_program in
     141    autoconf*)
     142      echo "You should only need it if you modified 'configure.ac',"
     143      echo "or m4 files included by it."
     144      program_details 'autoconf'
     145      ;;
     146    autoheader*)
     147      echo "You should only need it if you modified 'acconfig.h' or"
     148      echo "$configure_deps."
     149      program_details 'autoheader'
     150      ;;
     151    automake*)
     152      echo "You should only need it if you modified 'Makefile.am' or"
     153      echo "$configure_deps."
     154      program_details 'automake'
     155      ;;
     156    aclocal*)
     157      echo "You should only need it if you modified 'acinclude.m4' or"
     158      echo "$configure_deps."
     159      program_details 'aclocal'
     160      ;;
     161   autom4te*)
     162      echo "You might have modified some maintainer files that require"
     163      echo "the 'autom4te' program to be rebuilt."
     164      program_details 'autom4te'
     165      ;;
     166    bison*|yacc*)
     167      echo "You should only need it if you modified a '.y' file."
     168      echo "You may want to install the GNU Bison package:"
     169      echo "<$gnu_software_URL/bison/>"
     170      ;;
     171    lex*|flex*)
     172      echo "You should only need it if you modified a '.l' file."
     173      echo "You may want to install the Fast Lexical Analyzer package:"
     174      echo "<$flex_URL>"
     175      ;;
     176    help2man*)
     177      echo "You should only need it if you modified a dependency" \
     178           "of a man page."
     179      echo "You may want to install the GNU Help2man package:"
     180      echo "<$gnu_software_URL/help2man/>"
     181    ;;
     182    makeinfo*)
     183      echo "You should only need it if you modified a '.texi' file, or"
     184      echo "any other file indirectly affecting the aspect of the manual."
     185      echo "You might want to install the Texinfo package:"
     186      echo "<$gnu_software_URL/texinfo/>"
     187      echo "The spurious makeinfo call might also be the consequence of"
     188      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
     189      echo "want to install GNU make:"
     190      echo "<$gnu_software_URL/make/>"
     191      ;;
     192    *)
     193      echo "You might have modified some files without having the proper"
     194      echo "tools for further handling them.  Check the 'README' file, it"
     195      echo "often tells you about the needed prerequisites for installing"
     196      echo "this package.  You may also peek at any GNU archive site, in"
     197      echo "case some other package contains this missing '$1' program."
     198      ;;
     199  esac
     200}
     201
     202give_advice "$1" | sed -e '1s/^/WARNING: /' \
     203                       -e '2,$s/^/         /' >&2
     204
     205# Propagate the correct exit status (expected to be 127 for a program
     206# not found, 63 for a program that failed due to version mismatch).
     207exit $st
     208
     209# Local variables:
     210# eval: (add-hook 'write-file-hooks 'time-stamp)
     211# time-stamp-start: "scriptversion="
     212# time-stamp-format: "%:y-%02m-%02d.%02H"
     213# time-stamp-time-zone: "UTC"
     214# time-stamp-end: "; # UTC"
     215# End:
  • automake/test-driver

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/test-driver
     1#! /bin/sh
     2# test-driver - basic testsuite driver script.
     3
     4scriptversion=2013-07-13.22; # UTC
     5
     6# Copyright (C) 2011-2014 Free Software Foundation, Inc.
     7#
     8# This program is free software; you can redistribute it and/or modify
     9# it under the terms of the GNU General Public License as published by
     10# the Free Software Foundation; either version 2, or (at your option)
     11# any later version.
     12#
     13# This program is distributed in the hope that it will be useful,
     14# but WITHOUT ANY WARRANTY; without even the implied warranty of
     15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16# GNU General Public License for more details.
     17#
     18# You should have received a copy of the GNU General Public License
     19# along with this program.  If not, see <http://www.gnu.org/licenses/>.
     20
     21# As a special exception to the GNU General Public License, if you
     22# distribute this file as part of a program that contains a
     23# configuration script generated by Autoconf, you may include it under
     24# the same distribution terms that you use for the rest of that program.
     25
     26# This file is maintained in Automake, please report
     27# bugs to <bug-automake@gnu.org> or send patches to
     28# <automake-patches@gnu.org>.
     29
     30# Make unconditional expansion of undefined variables an error.  This
     31# helps a lot in preventing typo-related bugs.
     32set -u
     33
     34usage_error ()
     35{
     36  echo "$0: $*" >&2
     37  print_usage >&2
     38  exit 2
     39}
     40
     41print_usage ()
     42{
     43  cat <<END
     44Usage:
     45  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
     46              [--expect-failure={yes|no}] [--color-tests={yes|no}]
     47              [--enable-hard-errors={yes|no}] [--]
     48              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
     49The '--test-name', '--log-file' and '--trs-file' options are mandatory.
     50END
     51}
     52
     53test_name= # Used for reporting.
     54log_file=  # Where to save the output of the test script.
     55trs_file=  # Where to save the metadata of the test run.
     56expect_failure=no
     57color_tests=no
     58enable_hard_errors=yes
     59while test $# -gt 0; do
     60  case $1 in
     61  --help) print_usage; exit $?;;
     62  --version) echo "test-driver $scriptversion"; exit $?;;
     63  --test-name) test_name=$2; shift;;
     64  --log-file) log_file=$2; shift;;
     65  --trs-file) trs_file=$2; shift;;
     66  --color-tests) color_tests=$2; shift;;
     67  --expect-failure) expect_failure=$2; shift;;
     68  --enable-hard-errors) enable_hard_errors=$2; shift;;
     69  --) shift; break;;
     70  -*) usage_error "invalid option: '$1'";;
     71   *) break;;
     72  esac
     73  shift
     74done
     75
     76missing_opts=
     77test x"$test_name" = x && missing_opts="$missing_opts --test-name"
     78test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
     79test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
     80if test x"$missing_opts" != x; then
     81  usage_error "the following mandatory options are missing:$missing_opts"
     82fi
     83
     84if test $# -eq 0; then
     85  usage_error "missing argument"
     86fi
     87
     88if test $color_tests = yes; then
     89  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
     90  red='[0;31m' # Red.
     91  grn='[0;32m' # Green.
     92  lgn='[1;32m' # Light green.
     93  blu='[1;34m' # Blue.
     94  mgn='[0;35m' # Magenta.
     95  std='[m'     # No color.
     96else
     97  red= grn= lgn= blu= mgn= std=
     98fi
     99
     100do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
     101trap "st=129; $do_exit" 1
     102trap "st=130; $do_exit" 2
     103trap "st=141; $do_exit" 13
     104trap "st=143; $do_exit" 15
     105
     106# Test script is run here.
     107"$@" >$log_file 2>&1
     108estatus=$?
     109
     110if test $enable_hard_errors = no && test $estatus -eq 99; then
     111  tweaked_estatus=1
     112else
     113  tweaked_estatus=$estatus
     114fi
     115
     116case $tweaked_estatus:$expect_failure in
     117  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
     118  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
     119  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
     120  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
     121  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
     122  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
     123esac
     124
     125# Report the test outcome and exit status in the logs, so that one can
     126# know whether the test passed or failed simply by looking at the '.log'
     127# file, without the need of also peaking into the corresponding '.trs'
     128# file (automake bug#11814).
     129echo "$res $test_name (exit status: $estatus)" >>$log_file
     130
     131# Report outcome to console.
     132echo "${col}${res}${std}: $test_name"
     133
     134# Register the test result, and other relevant metadata.
     135echo ":test-result: $res" > $trs_file
     136echo ":global-test-result: $res" >> $trs_file
     137echo ":recheck: $recheck" >> $trs_file
     138echo ":copy-in-global-log: $gcopy" >> $trs_file
     139
     140# Local Variables:
     141# mode: shell-script
     142# sh-indentation: 2
     143# eval: (add-hook 'write-file-hooks 'time-stamp)
     144# time-stamp-start: "scriptversion="
     145# time-stamp-format: "%:y-%02m-%02d.%02H"
     146# time-stamp-time-zone: "UTC"
     147# time-stamp-end: "; # UTC"
     148# End:
  • automake/ylwrap

    • Property mode changed from 120000 to 100755
    rb067d9b r7951100  
    1 /usr/share/automake-1.15/ylwrap
     1#! /bin/sh
     2# ylwrap - wrapper for lex/yacc invocations.
     3
     4scriptversion=2013-01-12.17; # UTC
     5
     6# Copyright (C) 1996-2014 Free Software Foundation, Inc.
     7#
     8# Written by Tom Tromey <tromey@cygnus.com>.
     9#
     10# This program is free software; you can redistribute it and/or modify
     11# it under the terms of the GNU General Public License as published by
     12# the Free Software Foundation; either version 2, or (at your option)
     13# any later version.
     14#
     15# This program is distributed in the hope that it will be useful,
     16# but WITHOUT ANY WARRANTY; without even the implied warranty of
     17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18# GNU General Public License for more details.
     19#
     20# You should have received a copy of the GNU General Public License
     21# along with this program.  If not, see <http://www.gnu.org/licenses/>.
     22
     23# As a special exception to the GNU General Public License, if you
     24# distribute this file as part of a program that contains a
     25# configuration script generated by Autoconf, you may include it under
     26# the same distribution terms that you use for the rest of that program.
     27
     28# This file is maintained in Automake, please report
     29# bugs to <bug-automake@gnu.org> or send patches to
     30# <automake-patches@gnu.org>.
     31
     32get_dirname ()
     33{
     34  case $1 in
     35    */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
     36    # Otherwise,  we want the empty string (not ".").
     37  esac
     38}
     39
     40# guard FILE
     41# ----------
     42# The CPP macro used to guard inclusion of FILE.
     43guard ()
     44{
     45  printf '%s\n' "$1"                                                    \
     46    | sed                                                               \
     47        -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'   \
     48        -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'                        \
     49        -e 's/__*/_/g'
     50}
     51
     52# quote_for_sed [STRING]
     53# ----------------------
     54# Return STRING (or stdin) quoted to be used as a sed pattern.
     55quote_for_sed ()
     56{
     57  case $# in
     58    0) cat;;
     59    1) printf '%s\n' "$1";;
     60  esac \
     61    | sed -e 's|[][\\.*]|\\&|g'
     62}
     63
     64case "$1" in
     65  '')
     66    echo "$0: No files given.  Try '$0 --help' for more information." 1>&2
     67    exit 1
     68    ;;
     69  --basedir)
     70    basedir=$2
     71    shift 2
     72    ;;
     73  -h|--h*)
     74    cat <<\EOF
     75Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
     76
     77Wrapper for lex/yacc invocations, renaming files as desired.
     78
     79  INPUT is the input file
     80  OUTPUT is one file PROG generates
     81  DESIRED is the file we actually want instead of OUTPUT
     82  PROGRAM is program to run
     83  ARGS are passed to PROG
     84
     85Any number of OUTPUT,DESIRED pairs may be used.
     86
     87Report bugs to <bug-automake@gnu.org>.
     88EOF
     89    exit $?
     90    ;;
     91  -v|--v*)
     92    echo "ylwrap $scriptversion"
     93    exit $?
     94    ;;
     95esac
     96
     97
     98# The input.
     99input=$1
     100shift
     101# We'll later need for a correct munging of "#line" directives.
     102input_sub_rx=`get_dirname "$input" | quote_for_sed`
     103case $input in
     104  [\\/]* | ?:[\\/]*)
     105    # Absolute path; do nothing.
     106    ;;
     107  *)
     108    # Relative path.  Make it absolute.
     109    input=`pwd`/$input
     110    ;;
     111esac
     112input_rx=`get_dirname "$input" | quote_for_sed`
     113
     114# Since DOS filename conventions don't allow two dots,
     115# the DOS version of Bison writes out y_tab.c instead of y.tab.c
     116# and y_tab.h instead of y.tab.h. Test to see if this is the case.
     117y_tab_nodot=false
     118if test -f y_tab.c || test -f y_tab.h; then
     119  y_tab_nodot=true
     120fi
     121
     122# The parser itself, the first file, is the destination of the .y.c
     123# rule in the Makefile.
     124parser=$1
     125
     126# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
     127# instance, we rename #include "y.tab.h" into #include "parse.h"
     128# during the conversion from y.tab.c to parse.c.
     129sed_fix_filenames=
     130
     131# Also rename header guards, as Bison 2.7 for instance uses its header
     132# guard in its implementation file.
     133sed_fix_header_guards=
     134
     135while test $# -ne 0; do
     136  if test x"$1" = x"--"; then
     137    shift
     138    break
     139  fi
     140  from=$1
     141  # Handle y_tab.c and y_tab.h output by DOS
     142  if $y_tab_nodot; then
     143    case $from in
     144      "y.tab.c") from=y_tab.c;;
     145      "y.tab.h") from=y_tab.h;;
     146    esac
     147  fi
     148  shift
     149  to=$1
     150  shift
     151  sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
     152  sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
     153done
     154
     155# The program to run.
     156prog=$1
     157shift
     158# Make any relative path in $prog absolute.
     159case $prog in
     160  [\\/]* | ?:[\\/]*) ;;
     161  *[\\/]*) prog=`pwd`/$prog ;;
     162esac
     163
     164dirname=ylwrap$$
     165do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
     166trap "ret=129; $do_exit" 1
     167trap "ret=130; $do_exit" 2
     168trap "ret=141; $do_exit" 13
     169trap "ret=143; $do_exit" 15
     170mkdir $dirname || exit 1
     171
     172cd $dirname
     173
     174case $# in
     175  0) "$prog" "$input" ;;
     176  *) "$prog" "$@" "$input" ;;
     177esac
     178ret=$?
     179
     180if test $ret -eq 0; then
     181  for from in *
     182  do
     183    to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
     184    if test -f "$from"; then
     185      # If $2 is an absolute path name, then just use that,
     186      # otherwise prepend '../'.
     187      case $to in
     188        [\\/]* | ?:[\\/]*) target=$to;;
     189        *) target=../$to;;
     190      esac
     191
     192      # Do not overwrite unchanged header files to avoid useless
     193      # recompilations.  Always update the parser itself: it is the
     194      # destination of the .y.c rule in the Makefile.  Divert the
     195      # output of all other files to a temporary file so we can
     196      # compare them to existing versions.
     197      if test $from != $parser; then
     198        realtarget=$target
     199        target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
     200      fi
     201
     202      # Munge "#line" or "#" directives.  Don't let the resulting
     203      # debug information point at an absolute srcdir.  Use the real
     204      # output file name, not yy.lex.c for instance.  Adjust the
     205      # include guards too.
     206      sed -e "/^#/!b"                           \
     207          -e "s|$input_rx|$input_sub_rx|"       \
     208          -e "$sed_fix_filenames"               \
     209          -e "$sed_fix_header_guards"           \
     210        "$from" >"$target" || ret=$?
     211
     212      # Check whether files must be updated.
     213      if test "$from" != "$parser"; then
     214        if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
     215          echo "$to is unchanged"
     216          rm -f "$target"
     217        else
     218          echo "updating $to"
     219          mv -f "$target" "$realtarget"
     220        fi
     221      fi
     222    else
     223      # A missing file is only an error for the parser.  This is a
     224      # blatant hack to let us support using "yacc -d".  If -d is not
     225      # specified, don't fail when the header file is "missing".
     226      if test "$from" = "$parser"; then
     227        ret=1
     228      fi
     229    fi
     230  done
     231fi
     232
     233# Remove the directory.
     234cd ..
     235rm -rf $dirname
     236
     237exit $ret
     238
     239# Local Variables:
     240# mode: shell-script
     241# sh-indentation: 2
     242# eval: (add-hook 'write-file-hooks 'time-stamp)
     243# time-stamp-start: "scriptversion="
     244# time-stamp-format: "%:y-%02m-%02d.%02H"
     245# time-stamp-time-zone: "UTC"
     246# time-stamp-end: "; # UTC"
     247# End:
  • configure

    rb067d9b r7951100  
    199199  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
    200200  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
    201 
    202   test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
    203     ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
    204     ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
    205     ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
    206     PATH=/empty FPATH=/empty; export PATH FPATH
    207     test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
    208       || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
    209201test \$(( 1 + 1 )) = 2 || exit 1"
    210202  if (eval "$as_required") 2>/dev/null; then :
     
    565557as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
    566558
    567 SHELL=${CONFIG_SHELL-/bin/sh}
    568 
    569559
    570560test -n "$DJDIR" || exec 7<&0 </dev/null
     
    636626LTLIBOBJS
    637627LIBOBJS
    638 CFA_BACKEND_CC
    639 DEMANGLER
    640 LIBDEMANGLE
    641 WITH_LIBTCMALLOC_FALSE
    642 WITH_LIBTCMALLOC_TRUE
    643 WITH_LIBPROFILER_FALSE
    644 WITH_LIBPROFILER_TRUE
    645 WITH_LIBFIBRE_FALSE
    646 WITH_LIBFIBRE_TRUE
    647 CXXCPP
    648 CPP
    649 LT_SYS_LIBRARY_PATH
    650 OTOOL64
    651 OTOOL
    652 LIPO
    653 NMEDIT
    654 DSYMUTIL
    655 MANIFEST_TOOL
    656 RANLIB
    657 ac_ct_AR
    658 AR
    659 DLLTOOL
    660 OBJDUMP
    661 LN_S
    662 NM
    663 ac_ct_DUMPBIN
    664 DUMPBIN
    665 FGREP
     628ALLOCA
    666629EGREP
    667630GREP
    668 SED
    669 LIBTOOL
     631CPP
     632RANLIB
    670633LEXLIB
    671634LEX_OUTPUT_ROOT
     
    700663LDFLAGS
    701664CXXFLAGS
     665CXX
    702666CFA_FLAGS
    703 LIBCFA_TARGET_MAKEFILES
    704 LIBCFA_TARGET_DIRS
    705 TARGET_HOSTS
    706 HOST_FLAGS
     667MACHINE_TYPE
    707668host_os
    708669host_vendor
     
    713674build_cpu
    714675build
    715 BUILD_IN_TREE_FLAGS
    716 CFACPP
    717 CFACC_INSTALL
    718 CFACC
    719 DRIVER_DIR
    720676CFA_LIBDIR
    721677CFA_BINDIR
    722678CFA_INCDIR
    723679CFA_PREFIX
    724 HAS_DISTCC
    725 LD
    726 CXX
    727 ENABLE_DISTCC_FALSE
    728 ENABLE_DISTCC_TRUE
    729680DOendif
    730681DOifskipcompile
     682BUILD_CONCURRENCY_FALSE
     683BUILD_CONCURRENCY_TRUE
     684BUILD_NO_LIB_FALSE
     685BUILD_NO_LIB_TRUE
     686BUILD_DEBUG_FALSE
     687BUILD_DEBUG_TRUE
     688BUILD_RELEASE_FALSE
     689BUILD_RELEASE_TRUE
     690CFA_BACKEND_CC
     691BACKEND_CC
    731692CFA_NAME
     693MAINT
     694MAINTAINER_MODE_FALSE
     695MAINTAINER_MODE_TRUE
    732696am__untar
    733697am__tar
     
    800764enable_option_checking
    801765enable_silent_rules
     766enable_maintainer_mode
    802767with_cfa_name
    803 enable_distcc
    804 with_target_hosts
    805 enable_gprofiler
    806 enable_demangler
     768with_backend_compiler
     769enable_target_release
     770enable_target_debug
     771enable_threading
    807772enable_dependency_tracking
    808 enable_shared
    809 enable_static
    810 with_pic
    811 enable_fast_install
    812 with_aix_soname
    813 with_gnu_ld
    814 with_sysroot
    815 enable_libtool_lock
    816773'
    817774      ac_precious_vars='build_alias
     
    830787YACC
    831788YFLAGS
    832 LT_SYS_LIBRARY_PATH
    833 CPP
    834 CXXCPP'
     789CPP'
    835790
    836791
     
    14641419  --enable-silent-rules   less verbose build output (undo: "make V=1")
    14651420  --disable-silent-rules  verbose build output (undo: "make V=0")
    1466   --enable-distcc     whether or not to enable distributed compilation
    1467   --enable-gprofiler     whether or not to enable gprofiler tools (if available)
    1468   --enable-demangler     whether or not to build the demangler (executable and library)
     1421  --disable-maintainer-mode
     1422                          disable make rules and dependencies not useful (and
     1423                          sometimes confusing) to the casual installer
     1424  --enable-target-release Build and install the release target
     1425  --enable-target-debug   Build and install the debug target
     1426  --enable-threading      Build and install libcfa with threading support
     1427                          (Enabled by default)
    14691428  --enable-dependency-tracking
    14701429                          do not reject slow dependency extractors
    14711430  --disable-dependency-tracking
    14721431                          speeds up one-time build
    1473   --enable-shared[=PKGS]  build shared libraries [default=yes]
    1474   --enable-static[=PKGS]  build static libraries [default=yes]
    1475   --enable-fast-install[=PKGS]
    1476                           optimize for fast installation [default=yes]
    1477   --disable-libtool-lock  avoid locking (might break parallel builds)
    14781432
    14791433Optional Packages:
     
    14811435  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
    14821436  --with-cfa-name=NAME     NAME too which cfa will be installed
    1483   --with-target-hosts=HOSTS     HOSTS comma seperated list of hosts to build for, format ARCH:debug|nodebug|nolib
    1484   --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
    1485                           both]
    1486   --with-aix-soname=aix|svr4|both
    1487                           shared library versioning (aka "SONAME") variant to
    1488                           provide on AIX, [default=aix].
    1489   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
    1490   --with-sysroot[=DIR]    Search for dependent libraries within DIR (or the
    1491                           compiler's sysroot if not specified).
     1437  --with-backend-compiler=PROGRAM     PROGRAM that performs the final code compilation (must be gcc-compatible)
    14921438
    14931439Some influential environment variables:
     
    15091455              This script will default YFLAGS to the empty string to avoid a
    15101456              default value of `-d' given by some make applications.
    1511   LT_SYS_LIBRARY_PATH
    1512               User-defined run-time library search path.
    15131457  CPP         C preprocessor
    1514   CXXCPP      C++ preprocessor
    15151458
    15161459Use these variables to override the choices made by `configure' or to help
     
    17161659} # ac_fn_c_try_link
    17171660
    1718 # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
    1719 # -------------------------------------------------------
    1720 # Tests whether HEADER exists and can be compiled using the include files in
    1721 # INCLUDES, setting the cache variable VAR accordingly.
    1722 ac_fn_c_check_header_compile ()
     1661# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
     1662# -------------------------------------------
     1663# Tests whether TYPE exists after having included INCLUDES, setting cache
     1664# variable VAR accordingly.
     1665ac_fn_c_check_type ()
    17231666{
    17241667  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
     
    17281671  $as_echo_n "(cached) " >&6
    17291672else
     1673  eval "$3=no"
    17301674  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    17311675/* end confdefs.h.  */
    17321676$4
    1733 #include <$2>
     1677int
     1678main ()
     1679{
     1680if (sizeof ($2))
     1681         return 0;
     1682  ;
     1683  return 0;
     1684}
    17341685_ACEOF
    17351686if ac_fn_c_try_compile "$LINENO"; then :
     1687  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     1688/* end confdefs.h.  */
     1689$4
     1690int
     1691main ()
     1692{
     1693if (sizeof (($2)))
     1694            return 0;
     1695  ;
     1696  return 0;
     1697}
     1698_ACEOF
     1699if ac_fn_c_try_compile "$LINENO"; then :
     1700
     1701else
    17361702  eval "$3=yes"
    1737 else
    1738   eval "$3=no"
     1703fi
     1704rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    17391705fi
    17401706rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     
    17451711  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
    17461712
    1747 } # ac_fn_c_check_header_compile
     1713} # ac_fn_c_check_type
    17481714
    17491715# ac_fn_c_try_cpp LINENO
     
    18261792} # ac_fn_c_try_run
    18271793
     1794# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
     1795# -------------------------------------------------------
     1796# Tests whether HEADER exists and can be compiled using the include files in
     1797# INCLUDES, setting the cache variable VAR accordingly.
     1798ac_fn_c_check_header_compile ()
     1799{
     1800  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
     1801  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
     1802$as_echo_n "checking for $2... " >&6; }
     1803if eval \${$3+:} false; then :
     1804  $as_echo_n "(cached) " >&6
     1805else
     1806  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     1807/* end confdefs.h.  */
     1808$4
     1809#include <$2>
     1810_ACEOF
     1811if ac_fn_c_try_compile "$LINENO"; then :
     1812  eval "$3=yes"
     1813else
     1814  eval "$3=no"
     1815fi
     1816rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     1817fi
     1818eval ac_res=\$$3
     1819               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
     1820$as_echo "$ac_res" >&6; }
     1821  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
     1822
     1823} # ac_fn_c_check_header_compile
     1824
    18281825# ac_fn_c_check_func LINENO FUNC VAR
    18291826# ----------------------------------
     
    18921889
    18931890} # ac_fn_c_check_func
    1894 
    1895 # ac_fn_cxx_try_cpp LINENO
    1896 # ------------------------
    1897 # Try to preprocess conftest.$ac_ext, and return whether this succeeded.
    1898 ac_fn_cxx_try_cpp ()
    1899 {
    1900   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    1901   if { { ac_try="$ac_cpp conftest.$ac_ext"
    1902 case "(($ac_try" in
    1903   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
    1904   *) ac_try_echo=$ac_try;;
    1905 esac
    1906 eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
    1907 $as_echo "$ac_try_echo"; } >&5
    1908   (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
    1909   ac_status=$?
    1910   if test -s conftest.err; then
    1911     grep -v '^ *+' conftest.err >conftest.er1
    1912     cat conftest.er1 >&5
    1913     mv -f conftest.er1 conftest.err
    1914   fi
    1915   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    1916   test $ac_status = 0; } > conftest.i && {
    1917          test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
    1918          test ! -s conftest.err
    1919        }; then :
    1920   ac_retval=0
    1921 else
    1922   $as_echo "$as_me: failed program was:" >&5
    1923 sed 's/^/| /' conftest.$ac_ext >&5
    1924 
    1925     ac_retval=1
    1926 fi
    1927   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
    1928   as_fn_set_status $ac_retval
    1929 
    1930 } # ac_fn_cxx_try_cpp
    1931 
    1932 # ac_fn_cxx_try_link LINENO
    1933 # -------------------------
    1934 # Try to link conftest.$ac_ext, and return whether this succeeded.
    1935 ac_fn_cxx_try_link ()
    1936 {
    1937   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    1938   rm -f conftest.$ac_objext conftest$ac_exeext
    1939   if { { ac_try="$ac_link"
    1940 case "(($ac_try" in
    1941   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
    1942   *) ac_try_echo=$ac_try;;
    1943 esac
    1944 eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
    1945 $as_echo "$ac_try_echo"; } >&5
    1946   (eval "$ac_link") 2>conftest.err
    1947   ac_status=$?
    1948   if test -s conftest.err; then
    1949     grep -v '^ *+' conftest.err >conftest.er1
    1950     cat conftest.er1 >&5
    1951     mv -f conftest.er1 conftest.err
    1952   fi
    1953   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    1954   test $ac_status = 0; } && {
    1955          test -z "$ac_cxx_werror_flag" ||
    1956          test ! -s conftest.err
    1957        } && test -s conftest$ac_exeext && {
    1958          test "$cross_compiling" = yes ||
    1959          test -x conftest$ac_exeext
    1960        }; then :
    1961   ac_retval=0
    1962 else
    1963   $as_echo "$as_me: failed program was:" >&5
    1964 sed 's/^/| /' conftest.$ac_ext >&5
    1965 
    1966         ac_retval=1
    1967 fi
    1968   # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
    1969   # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
    1970   # interfere with the next link command; also delete a directory that is
    1971   # left behind by Apple's compiler.  We do this before executing the actions.
    1972   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
    1973   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
    1974   as_fn_set_status $ac_retval
    1975 
    1976 } # ac_fn_cxx_try_link
    19771891
    19781892# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
     
    20671981} # ac_fn_c_check_header_mongrel
    20681982
    2069 # ac_fn_c_check_type LINENO TYPE VAR INCLUDES
    2070 # -------------------------------------------
    2071 # Tests whether TYPE exists after having included INCLUDES, setting cache
    2072 # variable VAR accordingly.
    2073 ac_fn_c_check_type ()
     1983# ac_fn_c_find_intX_t LINENO BITS VAR
     1984# -----------------------------------
     1985# Finds a signed integer type with width BITS, setting cache variable VAR
     1986# accordingly.
     1987ac_fn_c_find_intX_t ()
    20741988{
    20751989  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    2076   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
    2077 $as_echo_n "checking for $2... " >&6; }
     1990  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
     1991$as_echo_n "checking for int$2_t... " >&6; }
    20781992if eval \${$3+:} false; then :
    20791993  $as_echo_n "(cached) " >&6
    20801994else
    20811995  eval "$3=no"
    2082   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     1996     # Order is important - never check a type that is potentially smaller
     1997     # than half of the expected target width.
     1998     for ac_type in int$2_t 'int' 'long int' \
     1999         'long long int' 'short int' 'signed char'; do
     2000       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    20832001/* end confdefs.h.  */
    2084 $4
     2002$ac_includes_default
     2003             enum { N = $2 / 2 - 1 };
    20852004int
    20862005main ()
    20872006{
    2088 if (sizeof ($2))
    2089          return 0;
     2007static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
     2008test_array [0] = 0;
     2009return test_array [0];
     2010
    20902011  ;
    20912012  return 0;
     
    20952016  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    20962017/* end confdefs.h.  */
    2097 $4
     2018$ac_includes_default
     2019                enum { N = $2 / 2 - 1 };
    20982020int
    20992021main ()
    21002022{
    2101 if (sizeof (($2)))
    2102             return 0;
     2023static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
     2024                 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
     2025test_array [0] = 0;
     2026return test_array [0];
     2027
    21032028  ;
    21042029  return 0;
     
    21082033
    21092034else
    2110   eval "$3=yes"
     2035  case $ac_type in #(
     2036  int$2_t) :
     2037    eval "$3=yes" ;; #(
     2038  *) :
     2039    eval "$3=\$ac_type" ;;
     2040esac
    21112041fi
    21122042rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    21132043fi
    21142044rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     2045       if eval test \"x\$"$3"\" = x"no"; then :
     2046
     2047else
     2048  break
     2049fi
     2050     done
    21152051fi
    21162052eval ac_res=\$$3
     
    21192055  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
    21202056
    2121 } # ac_fn_c_check_type
     2057} # ac_fn_c_find_intX_t
     2058
     2059# ac_fn_c_find_uintX_t LINENO BITS VAR
     2060# ------------------------------------
     2061# Finds an unsigned integer type with width BITS, setting cache variable VAR
     2062# accordingly.
     2063ac_fn_c_find_uintX_t ()
     2064{
     2065  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
     2066  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
     2067$as_echo_n "checking for uint$2_t... " >&6; }
     2068if eval \${$3+:} false; then :
     2069  $as_echo_n "(cached) " >&6
     2070else
     2071  eval "$3=no"
     2072     # Order is important - never check a type that is potentially smaller
     2073     # than half of the expected target width.
     2074     for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
     2075         'unsigned long long int' 'unsigned short int' 'unsigned char'; do
     2076       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     2077/* end confdefs.h.  */
     2078$ac_includes_default
     2079int
     2080main ()
     2081{
     2082static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
     2083test_array [0] = 0;
     2084return test_array [0];
     2085
     2086  ;
     2087  return 0;
     2088}
     2089_ACEOF
     2090if ac_fn_c_try_compile "$LINENO"; then :
     2091  case $ac_type in #(
     2092  uint$2_t) :
     2093    eval "$3=yes" ;; #(
     2094  *) :
     2095    eval "$3=\$ac_type" ;;
     2096esac
     2097fi
     2098rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     2099       if eval test \"x\$"$3"\" = x"no"; then :
     2100
     2101else
     2102  break
     2103fi
     2104     done
     2105fi
     2106eval ac_res=\$$3
     2107               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
     2108$as_echo "$ac_res" >&6; }
     2109  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
     2110
     2111} # ac_fn_c_find_uintX_t
    21222112cat >config.log <<_ACEOF
    21232113This file contains any messages produced by compilers while
     
    25012491
    25022492
    2503 
    25042493#AC_CONFIG_SRCDIR([src/main.cc])
    2505 ac_config_headers="$ac_config_headers config.h:src/config.h.in"
     2494ac_config_headers="$ac_config_headers config.h"
    25062495
    25072496# Check whether --enable-silent-rules was given.
     
    25132502  yes) AM_DEFAULT_VERBOSITY=0;;
    25142503   no) AM_DEFAULT_VERBOSITY=1;;
    2515     *) AM_DEFAULT_VERBOSITY=0;;
     2504    *) AM_DEFAULT_VERBOSITY=1;;
    25162505esac
    25172506am_make=${MAKE-make}
     
    25442533AM_BACKSLASH='\'
    25452534
    2546 
    2547 
    2548 
    2549 
    2550 
    2551 
    2552 
    2553 
    2554 # http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_check_compile_flag.m4
    2555 
    2556 
    2557 # don't use the default CFLAGS as they unconditonnaly add -O2
    2558 : ${CFLAGS=""}
    25592535
    25602536am__api_version='1.15'
     
    30993075
    31003076
     3077{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
     3078$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
     3079    # Check whether --enable-maintainer-mode was given.
     3080if test "${enable_maintainer_mode+set}" = set; then :
     3081  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
     3082else
     3083  USE_MAINTAINER_MODE=yes
     3084fi
     3085
     3086  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
     3087$as_echo "$USE_MAINTAINER_MODE" >&6; }
     3088   if test $USE_MAINTAINER_MODE = yes; then
     3089  MAINTAINER_MODE_TRUE=
     3090  MAINTAINER_MODE_FALSE='#'
     3091else
     3092  MAINTAINER_MODE_TRUE='#'
     3093  MAINTAINER_MODE_FALSE=
     3094fi
     3095
     3096  MAINT=$MAINTAINER_MODE_TRUE
     3097
     3098                        # may require auto* software to be installed
     3099
    31013100# Allow program name tansformation
    31023101# will fill program_transform_name with appropriate sed regex
    31033102
    31043103
    3105 #==============================================================================
    31063104#Trasforming cc1 will break compilation
    3107 
    3108         if test "${program_transform_name}" = ""; then
    3109         as_fn_error $? "Program transform not supported.
    3110                         Use --with-cfa-name='[Desired name here]' instead" "$LINENO" 5
    3111         fi
    3112 
    3113         #Define the new name of the installed command
     3105if test "${program_transform_name}" = ""; then
     3106    as_fn_error $? "Program transform not supported.
     3107                Use --with-cfa-name='[Desired name here]' instead" "$LINENO" 5
     3108fi
     3109
    31143110
    31153111# Check whether --with-cfa-name was given.
     
    31213117
    31223118
    3123         CFA_NAME=${cfa_name}
    3124 
    3125 
    3126 
    3127 #==============================================================================
    3128 # version information
     3119#Define the new name of the installed command
     3120CFA_NAME=${cfa_name}
     3121
    31293122
    31303123rm -f version
     
    31783171
    31793172
    3180 #==============================================================================
    3181 # HACK to be able to use conditionnals inside makefiles
     3173# Installation paths
     3174
     3175
     3176# Check whether --with-backend-compiler was given.
     3177if test "${with_backend_compiler+set}" = set; then :
     3178  withval=$with_backend_compiler; backendcompiler=$withval
     3179else
     3180  backendcompiler=""
     3181fi
     3182
     3183if test "x$backendcompiler" != "x"; then
     3184        BACKEND_CC=${backendcompiler}
     3185else
     3186        # Extract the first word of "gcc", so it can be a program name with args.
     3187set dummy gcc; ac_word=$2
     3188{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
     3189$as_echo_n "checking for $ac_word... " >&6; }
     3190if ${ac_cv_path_BACKEND_CC+:} false; then :
     3191  $as_echo_n "(cached) " >&6
     3192else
     3193  case $BACKEND_CC in
     3194  [\\/]* | ?:[\\/]*)
     3195  ac_cv_path_BACKEND_CC="$BACKEND_CC" # Let the user override the test with a path.
     3196  ;;
     3197  *)
     3198  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     3199for as_dir in $PATH
     3200do
     3201  IFS=$as_save_IFS
     3202  test -z "$as_dir" && as_dir=.
     3203    for ac_exec_ext in '' $ac_executable_extensions; do
     3204  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     3205    ac_cv_path_BACKEND_CC="$as_dir/$ac_word$ac_exec_ext"
     3206    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     3207    break 2
     3208  fi
     3209done
     3210  done
     3211IFS=$as_save_IFS
     3212
     3213  ;;
     3214esac
     3215fi
     3216BACKEND_CC=$ac_cv_path_BACKEND_CC
     3217if test -n "$BACKEND_CC"; then
     3218  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BACKEND_CC" >&5
     3219$as_echo "$BACKEND_CC" >&6; }
     3220else
     3221  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     3222$as_echo "no" >&6; }
     3223fi
     3224
     3225        # check gcc installed
     3226        if test "x$BACKEND_CC" = "x"; then
     3227                as_fn_error $? "some version of gcc is needed. Get it at ftp://ftp.gnu.org" "$LINENO" 5
     3228                exit 1
     3229        fi
     3230fi
     3231
     3232cat >>confdefs.h <<_ACEOF
     3233#define CFA_BACKEND_CC "${BACKEND_CC}"
     3234_ACEOF
     3235
     3236
     3237
     3238
     3239
     3240# Check whether --enable-target-release was given.
     3241if test "${enable_target_release+set}" = set; then :
     3242  enableval=$enable_target_release;
     3243fi
     3244
     3245# Check whether --enable-target-debug was given.
     3246if test "${enable_target_debug+set}" = set; then :
     3247  enableval=$enable_target_debug;
     3248fi
     3249
     3250# Check whether --enable-threading was given.
     3251if test "${enable_threading+set}" = set; then :
     3252  enableval=$enable_threading; case "${enableval}" in
     3253  yes) build_threading="yes" ;;
     3254  no)  build_threading="no" ;;
     3255  *) as_fn_error $? "bad value ${enableval} for --enable-debug" "$LINENO" 5 ;;
     3256esac
     3257else
     3258  build_threading="yes"
     3259fi
     3260
     3261
     3262case "$enable_target_release" in
     3263        yes)
     3264                case "$enable_target_debug" in
     3265                        yes)
     3266                                build_release="yes"
     3267                                build_debug="yes"
     3268                                ;;
     3269                        no)
     3270                                build_release="yes"
     3271                                build_debug="no"
     3272                                ;;
     3273                        *)
     3274                                build_release="yes"
     3275                                build_debug="no"
     3276                                ;;
     3277                esac
     3278                ;;
     3279        no)
     3280                case "$enable_target_debug" in
     3281                        yes)
     3282                                build_release="no"
     3283                                build_debug="yes"
     3284                                ;;
     3285                        no)
     3286                                build_release="no"
     3287                                build_debug="no"
     3288                                ;;
     3289                        *)
     3290                                build_release="no"
     3291                                build_debug="yes"
     3292                                ;;
     3293                esac
     3294                ;;
     3295        *)
     3296                case "$enable_target_debug" in
     3297                        yes)
     3298                                build_release="no"
     3299                                build_debug="yes"
     3300                                ;;
     3301                        no)
     3302                                build_release="yes"
     3303                                build_debug="no"
     3304                                ;;
     3305                        *)
     3306                                build_release="yes"
     3307                                build_debug="yes"
     3308                                ;;
     3309                esac
     3310                ;;
     3311esac
     3312
     3313 if test "x$build_release" = "xyes"; then
     3314  BUILD_RELEASE_TRUE=
     3315  BUILD_RELEASE_FALSE='#'
     3316else
     3317  BUILD_RELEASE_TRUE='#'
     3318  BUILD_RELEASE_FALSE=
     3319fi
     3320
     3321 if test "x$build_debug" = "xyes"; then
     3322  BUILD_DEBUG_TRUE=
     3323  BUILD_DEBUG_FALSE='#'
     3324else
     3325  BUILD_DEBUG_TRUE='#'
     3326  BUILD_DEBUG_FALSE=
     3327fi
     3328
     3329 if test "x$build_release$build_debug" = "xnono"; then
     3330  BUILD_NO_LIB_TRUE=
     3331  BUILD_NO_LIB_FALSE='#'
     3332else
     3333  BUILD_NO_LIB_TRUE='#'
     3334  BUILD_NO_LIB_FALSE=
     3335fi
     3336
     3337 if test "x$build_threading" = "xyes"; then
     3338  BUILD_CONCURRENCY_TRUE=
     3339  BUILD_CONCURRENCY_FALSE='#'
     3340else
     3341  BUILD_CONCURRENCY_TRUE='#'
     3342  BUILD_CONCURRENCY_FALSE=
     3343fi
     3344
     3345
    31823346DOifskipcompile='ifeq ($(skipcompile),yes)
    31833347else'
     
    31893353
    31903354
    3191 #==============================================================================
    3192 # distcc support
    3193 
    3194 # Check whether --enable-distcc was given.
    3195 if test "${enable_distcc+set}" = set; then :
    3196   enableval=$enable_distcc; enable_distcc=$enableval
    3197 else
    3198   enable_distcc=no
    3199 fi
    3200 
    3201 
    3202  if test x$enable_distcc = xyes; then
    3203   ENABLE_DISTCC_TRUE=
    3204   ENABLE_DISTCC_FALSE='#'
    3205 else
    3206   ENABLE_DISTCC_TRUE='#'
    3207   ENABLE_DISTCC_FALSE=
    3208 fi
    3209 
    3210 HAS_DISTCC="False"
    3211 
    3212 if test x$enable_distcc = xyes; then
    3213         CXX="distcc ${CXX}"
    3214         LD="distcc ${LD} -lstdc++"
    3215         HAS_DISTCC="True"
    3216         echo "Enabling distributed builds"
    3217 fi
    3218 
    3219 
    3220 
    3221 
    3222 
    3223 #==============================================================================
    3224 # Installation paths
    3225 
    3226         if test "x$prefix" = "xNONE"; then
    3227                 cfa_prefix=${ac_default_prefix}
    3228         else
    3229                 cfa_prefix=${prefix}
    3230         fi
    3231         cfa_prefix="$(readlink -m ${cfa_prefix})/"
     3355if test "x$prefix" = "xNONE"; then
     3356        cfa_prefix=${ac_default_prefix}
     3357else
     3358        cfa_prefix=${prefix}
     3359fi
    32323360
    32333361cat >>confdefs.h <<_ACEOF
     
    32353363_ACEOF
    32363364
    3237         CFA_PREFIX=${cfa_prefix}
    3238 
    3239 
    3240         if test "$includedir" = '${prefix}/include'; then
    3241                 cfa_incdir="${cfa_prefix}include/${cfa_name}"
    3242         else
    3243                 cfa_incdir=${includedir}
    3244         fi
    3245         cfa_incdir="$(readlink -m ${cfa_incdir})/"
     3365CFA_PREFIX=${cfa_prefix}
     3366
     3367
     3368if test "$includedir" = '${prefix}/include'; then
     3369        cfa_incdir="${cfa_prefix}/include/${cfa_name}"
     3370else
     3371        cfa_incdir=${includedir}
     3372fi
    32463373
    32473374cat >>confdefs.h <<_ACEOF
     
    32493376_ACEOF
    32503377
    3251         CFA_INCDIR=${cfa_incdir}
    3252 
    3253 
    3254         if test "$bindir" = '${exec_prefix}/bin'; then
    3255                 cfa_bindir="${cfa_prefix}bin"
    3256         else
    3257                 cfa_bindir=${bindir}
    3258         fi
    3259         cfa_bindir="$(readlink -m ${cfa_bindir})/"
     3378CFA_INCDIR=${cfa_incdir}
     3379
     3380
     3381if test "$bindir" = '${exec_prefix}/bin'; then
     3382        cfa_bindir="${cfa_prefix}/bin"
     3383else
     3384        cfa_bindir=${bindir}
     3385fi
    32603386
    32613387cat >>confdefs.h <<_ACEOF
     
    32633389_ACEOF
    32643390
    3265         CFA_BINDIR=${cfa_bindir}
    3266 
    3267 
    3268         if test "$libdir" = '${exec_prefix}/lib'; then
    3269                 if test "${ARCHITECTURE}" != ""; then
    3270                         cfa_libdir="${cfa_prefix}lib/${cfa_name}/${ARCHITECTURE}-${CONFIGURATION}/"
    3271                 else
    3272                         cfa_libdir="${cfa_prefix}lib/${cfa_name}/"
    3273                 fi
    3274         else
    3275                 cfa_libdir="${libdir}/${ARCHITECTURE}${CONFIGURATION}"
    3276         fi
    3277         cfa_libdir="$(readlink -m ${cfa_libdir})/"
     3391CFA_BINDIR=${cfa_bindir}
     3392
     3393
     3394if test "$libdir" = '${exec_prefix}/lib'; then
     3395        cfa_libdir="${cfa_prefix}/lib/${cfa_name}"
     3396else
     3397        cfa_libdir=${libdir}
     3398fi
    32783399
    32793400cat >>confdefs.h <<_ACEOF
     
    32813402_ACEOF
    32823403
    3283         CFA_LIBDIR=${cfa_libdir}
    3284 
    3285 
    3286 
    3287 #==============================================================================
    3288 # Create variables for commonly used targets
    3289 
    3290 TOP_SRCDIR="$(readlink -m $ac_confdir/)/"
    3291 TOP_BUILDDIR="$(readlink -m $ac_pwd/)/"
    3292 
    3293 
    3294 cat >>confdefs.h <<_ACEOF
    3295 #define TOP_SRCDIR "$TOP_SRCDIR"
    3296 _ACEOF
    3297 
    3298 
    3299 cat >>confdefs.h <<_ACEOF
    3300 #define TOP_BUILDDIR "$TOP_BUILDDIR"
    3301 _ACEOF
    3302 
    3303 
    3304 DRIVER_DIR=${TOP_BUILDDIR}driver/
    3305 CFACC=${DRIVER_DIR}cfa
    3306 CFACC_INSTALL=${CFA_BINDIR}${CFA_NAME}
    3307 CFACPP=${DRIVER_DIR}cfa-cpp
    3308 
    3309 
    3310 
    3311 
    3312 
    3313 #==============================================================================
    3314 # Flag variables needed to build in tree
    3315 LIBCFA_SRC='${TOP_SRCDIR}/libcfa/src'
    3316 BUILD_IN_TREE_FLAGS="-XCFA -t -B${DRIVER_DIR}"
    3317 
    3318 
    3319 #==============================================================================
    3320 # handle the list of hosts to build for
    3321 for var in $ac_configure_args
    3322 do
    3323         #strip quotes surrouding values
    3324         case $var in
    3325                 # skip cross compilation related arguments
    3326                 \'--host=*) ;; \'host_alias=*) ;; \'--build=*) ;; \'build_alias=*) ;; \'--target=*) ;; \'target_alias=*) ;;
    3327 
    3328                 # skip the target hosts
    3329                 \'--with-target-hosts=*) ;;
    3330 
    3331                 # skip gprofiler for libcfa
    3332                 \'--enable-gprofiler=*) ;;
    3333                 \'--disable-gprofiler) ;;
    3334 
    3335                 # append all other arguments to the sub configure arguments
    3336                 *) LIBCFA_GENERAL_ARGS="${LIBCFA_GENERAL_ARGS} $var";;
    3337         esac
    3338 done
    3339 
    3340 #==============================================================================
    3341 # handle the list of hosts to build for
     3404CFA_LIBDIR=${cfa_libdir}
     3405
     3406
    33423407# Make sure we can run config.sub.
    33433408$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
     
    34113476
    34123477
     3478MACHINE_TYPE=$host_cpu
     3479
    34133480
    34143481if ! test "$host_cpu" = "$build_cpu"; then
    34153482        case $host_cpu in
    34163483                i386)
    3417                         HOST_FLAGS="-m32"
     3484                        CFLAGS+=" -m32 "
     3485                        CXXFLAGS+=" -m32 "
     3486                        CFAFLAGS+=" -m32 "
     3487                        LDFLAGS+=" -m32 "
    34183488                        ;;
    34193489                i686)
    3420                         HOST_FLAGS="-m32"
     3490                        CFLAGS+=" -m32 "
     3491                  CXXFLAGS+=" -m32 "
     3492                  CFAFLAGS+=" -m32 "
     3493                  LDFLAGS+=" -m32 "
    34213494                        ;;
    34223495                x86_64)
    3423                         HOST_FLAGS="-m64"
     3496                        CFLAGS+=" -m64 "
     3497                        CXXFLAGS+=" -m64 "
     3498                        CFAFLAGS+=" -m64 "
     3499                        LDFLAGS+=" -m64 "
    34243500                        ;;
    34253501        esac
     
    34273503
    34283504
    3429 default_target="${host_cpu}:debug, ${host_cpu}:nodebug"
    3430 
    3431 # Check whether --with-target-hosts was given.
    3432 if test "${with_target_hosts+set}" = set; then :
    3433   withval=$with_target_hosts; target_hosts=$withval
    3434 else
    3435   target_hosts=${default_target}
    3436 fi
    3437 
    3438 
    3439 # Check whether --enable-gprofiler was given.
    3440 if test "${enable_gprofiler+set}" = set; then :
    3441   enableval=$enable_gprofiler; enable_gprofiler=$enableval
    3442 else
    3443   enable_gprofiler=yes
    3444 fi
    3445 
    3446 
    3447 # Check whether --enable-demangler was given.
    3448 if test "${enable_demangler+set}" = set; then :
    3449   enableval=$enable_demangler; enable_demangler=$enableval
    3450 else
    3451   enable_demangler=yes
    3452 fi
    3453 
    3454 
    3455 TARGET_HOSTS=${target_hosts}
    3456 
    3457 
    3458 LIBCFA_PATHS="DRIVER_DIR=${DRIVER_DIR}"
    3459 
    3460 for i in $(echo $target_hosts | sed "s/,/ /g")
    3461 do
    3462         # call your procedure/other scripts here below
    3463         arch_name=$(echo $i | sed -r "s/:(.*)//g")
    3464         lib_config=$(echo $i | sed -r "s/(.*)://g")
    3465 
    3466         case $lib_config in
    3467                 "nodebug") ;;
    3468                 "debug") ;;
    3469                 "nolib") ;;
    3470                 "profile") ;;
    3471                 *)
    3472                         >&2 echo "Configuration must be 'debug', 'nodebug' or 'nolib'"
    3473                         exit 1
    3474                 ;;
    3475         esac
    3476 
    3477 
    3478         case ${arch_name} in
    3479                 "host") arch_name=${host_cpu};;
    3480                 *) arch_name=${arch_name};;
    3481         esac
    3482 
    3483         case $arch_name in
    3484                 "x64"        ) cannon_arch_name="x64";;
    3485                 "x86-64"     ) cannon_arch_name="x64";;
    3486                 "x86_64"     ) cannon_arch_name="x64";;
    3487                 "aarch64"    ) cannon_arch_name="arm";;
    3488                 "x86"        ) cannon_arch_name="x86";;
    3489                 "i386"       ) cannon_arch_name="x86";;
    3490                 "i486"       ) cannon_arch_name="x86";;
    3491                 "i686"       ) cannon_arch_name="x86";;
    3492                 "Intel 80386") cannon_arch_name="x86";;
    3493                 "arm"        ) cannon_arch_name="arm";;
    3494                 "ARM"        ) cannon_arch_name="arm";;
    3495                 "armv7l"     ) cannon_arch_name="arm";;
    3496                 *)
    3497                 >&2 echo "Unknown architecture " $arch_name;
    3498                 exit 1
    3499                 ;;
    3500         esac
    3501 
    3502         lib_arch=${cannon_arch_name}
    3503         lib_dir="libcfa/${lib_arch}-${lib_config}"
    3504 
    3505         LIBCFA_TARGET_DIRS="${LIBCFA_TARGET_DIRS} ${lib_dir}"
    3506         LIBCFA_TARGET_MAKEFILES="${LIBCFA_TARGET_MAKEFILES} ${lib_dir}/Makefile"
    3507 
    3508         mkdir -p ${lib_dir}
    3509         echo -n "${LIBCFA_GENERAL_ARGS} " > ${lib_dir}/config.data
    3510         echo -n "${LIBCFA_PATHS} " >> ${lib_dir}/config.data
    3511         echo -n "ARCHITECTURE=${lib_arch} " >> ${lib_dir}/config.data
    3512         echo -n "CONFIGURATION=${lib_config} " >> ${lib_dir}/config.data
    3513         echo -n "CFA_VERSION=${ver_major}:${ver_minor}:${ver_patch}" >> ${lib_dir}/config.data
    3514 done
    3515 
    3516 
    3517 
    3518 
    3519 
    3520         case ${host_cpu} in
    3521                 "host") arch_name=${host_cpu};;
    3522                 *) arch_name=${host_cpu};;
    3523         esac
    3524 
    3525         case $arch_name in
    3526                 "x64"        ) cannon_arch_name="x64";;
    3527                 "x86-64"     ) cannon_arch_name="x64";;
    3528                 "x86_64"     ) cannon_arch_name="x64";;
    3529                 "aarch64"    ) cannon_arch_name="arm";;
    3530                 "x86"        ) cannon_arch_name="x86";;
    3531                 "i386"       ) cannon_arch_name="x86";;
    3532                 "i486"       ) cannon_arch_name="x86";;
    3533                 "i686"       ) cannon_arch_name="x86";;
    3534                 "Intel 80386") cannon_arch_name="x86";;
    3535                 "arm"        ) cannon_arch_name="arm";;
    3536                 "ARM"        ) cannon_arch_name="arm";;
    3537                 "armv7l"     ) cannon_arch_name="arm";;
    3538                 *)
    3539                 >&2 echo "Unknown architecture " $arch_name;
    3540                 exit 1
    3541                 ;;
    3542         esac
    3543 
    3544 
    3545 cat >>confdefs.h <<_ACEOF
    3546 #define CFA_DEFAULT_CPU "$cannon_arch_name"
    3547 _ACEOF
    3548 
    3549 
    3550 cat >>confdefs.h <<_ACEOF
    3551 #define CFA_64_CPU "x64"
    3552 _ACEOF
    3553 
    3554 
    3555 cat >>confdefs.h <<_ACEOF
    3556 #define CFA_32_CPU "x86"
    3557 _ACEOF
    3558 
    3559 
    3560 #==============================================================================
    3561 # CAFLAGS
    3562 
    35633505cat >>confdefs.h <<_ACEOF
    35643506#define CFA_FLAGS "${CFAFLAGS}"
     
    35683510
    35693511
    3570 #==============================================================================
    35713512# Checks for programs.
    35723513ac_ext=cpp
     
    51275068
    51285069
     5070        # deprecated
    51295071# These are often not installed and people miss seeing the "no", so stop the configure.
    51305072for ac_prog in 'bison -y' byacc
     
    53335275fi
    53345276if test "${LEX}" = "lex" ; then echo "Error: flex required." ; exit 1 ; fi
    5335 case `pwd` in
    5336   *\ * | *\     *)
    5337     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
    5338 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
     5277
     5278{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
     5279$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
     5280set x ${MAKE-make}
     5281ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
     5282if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
     5283  $as_echo_n "(cached) " >&6
     5284else
     5285  cat >conftest.make <<\_ACEOF
     5286SHELL = /bin/sh
     5287all:
     5288        @echo '@@@%%%=$(MAKE)=@@@%%%'
     5289_ACEOF
     5290# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
     5291case `${MAKE-make} -f conftest.make 2>/dev/null` in
     5292  *@@@%%%=?*=@@@%%%*)
     5293    eval ac_cv_prog_make_${ac_make}_set=yes;;
     5294  *)
     5295    eval ac_cv_prog_make_${ac_make}_set=no;;
    53395296esac
    5340 
    5341 
    5342 
    5343 macro_version='2.4.6'
    5344 macro_revision='2.4.6'
    5345 
    5346 
    5347 
    5348 
    5349 
    5350 
    5351 
    5352 
    5353 
    5354 
    5355 
    5356 
    5357 
    5358 ltmain=$ac_aux_dir/ltmain.sh
    5359 
    5360 # Backslashify metacharacters that are still active within
    5361 # double-quoted strings.
    5362 sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
    5363 
    5364 # Same as above, but do not quote variable references.
    5365 double_quote_subst='s/\(["`\\]\)/\\\1/g'
    5366 
    5367 # Sed substitution to delay expansion of an escaped shell variable in a
    5368 # double_quote_subst'ed string.
    5369 delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
    5370 
    5371 # Sed substitution to delay expansion of an escaped single quote.
    5372 delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
    5373 
    5374 # Sed substitution to avoid accidental globbing in evaled expressions
    5375 no_glob_subst='s/\*/\\\*/g'
    5376 
    5377 ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
    5378 ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
    5379 ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
    5380 
    5381 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
    5382 $as_echo_n "checking how to print strings... " >&6; }
    5383 # Test print first, because it will be a builtin if present.
    5384 if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
    5385    test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
    5386   ECHO='print -r --'
    5387 elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
    5388   ECHO='printf %s\n'
    5389 else
    5390   # Use this function as a fallback that always works.
    5391   func_fallback_echo ()
    5392   {
    5393     eval 'cat <<_LTECHO_EOF
    5394 $1
    5395 _LTECHO_EOF'
    5396   }
    5397   ECHO='func_fallback_echo'
    5398 fi
    5399 
    5400 # func_echo_all arg...
    5401 # Invoke $ECHO with all args, space-separated.
    5402 func_echo_all ()
    5403 {
    5404     $ECHO ""
    5405 }
    5406 
    5407 case $ECHO in
    5408   printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
    5409 $as_echo "printf" >&6; } ;;
    5410   print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
    5411 $as_echo "print -r" >&6; } ;;
    5412   *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
    5413 $as_echo "cat" >&6; } ;;
    5414 esac
    5415 
    5416 
    5417 
    5418 
    5419 
    5420 
    5421 
    5422 
    5423 
    5424 
    5425 
    5426 
    5427 
    5428 
    5429 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
    5430 $as_echo_n "checking for a sed that does not truncate output... " >&6; }
    5431 if ${ac_cv_path_SED+:} false; then :
     5297rm -f conftest.make
     5298fi
     5299if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
     5300  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
     5301$as_echo "yes" >&6; }
     5302  SET_MAKE=
     5303else
     5304  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5305$as_echo "no" >&6; }
     5306  SET_MAKE="MAKE=${MAKE-make}"
     5307fi
     5308
     5309if test -n "$ac_tool_prefix"; then
     5310  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
     5311set dummy ${ac_tool_prefix}ranlib; ac_word=$2
     5312{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
     5313$as_echo_n "checking for $ac_word... " >&6; }
     5314if ${ac_cv_prog_RANLIB+:} false; then :
    54325315  $as_echo_n "(cached) " >&6
    54335316else
    5434             ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
    5435      for ac_i in 1 2 3 4 5 6 7; do
    5436        ac_script="$ac_script$as_nl$ac_script"
    5437      done
    5438      echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
    5439      { ac_script=; unset ac_script;}
    5440      if test -z "$SED"; then
    5441   ac_path_SED_found=false
    5442   # Loop through the user's path and test for each of PROGNAME-LIST
    5443   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     5317  if test -n "$RANLIB"; then
     5318  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
     5319else
     5320as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    54445321for as_dir in $PATH
    54455322do
    54465323  IFS=$as_save_IFS
    54475324  test -z "$as_dir" && as_dir=.
    5448     for ac_prog in sed gsed; do
    54495325    for ac_exec_ext in '' $ac_executable_extensions; do
    5450       ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
    5451       as_fn_executable_p "$ac_path_SED" || continue
    5452 # Check for GNU ac_path_SED and select it if it is found.
    5453   # Check for GNU $ac_path_SED
    5454 case `"$ac_path_SED" --version 2>&1` in
    5455 *GNU*)
    5456   ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
    5457 *)
    5458   ac_count=0
    5459   $as_echo_n 0123456789 >"conftest.in"
    5460   while :
    5461   do
    5462     cat "conftest.in" "conftest.in" >"conftest.tmp"
    5463     mv "conftest.tmp" "conftest.in"
    5464     cp "conftest.in" "conftest.nl"
    5465     $as_echo '' >> "conftest.nl"
    5466     "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
    5467     diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    5468     as_fn_arith $ac_count + 1 && ac_count=$as_val
    5469     if test $ac_count -gt ${ac_path_SED_max-0}; then
    5470       # Best one so far, save it but keep looking for a better one
    5471       ac_cv_path_SED="$ac_path_SED"
    5472       ac_path_SED_max=$ac_count
    5473     fi
    5474     # 10*(2^10) chars as input seems more than enough
    5475     test $ac_count -gt 10 && break
    5476   done
    5477   rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
    5478 esac
    5479 
    5480       $ac_path_SED_found && break 3
    5481     done
    5482   done
     5326  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     5327    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     5328    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     5329    break 2
     5330  fi
     5331done
    54835332  done
    54845333IFS=$as_save_IFS
    5485   if test -z "$ac_cv_path_SED"; then
    5486     as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
     5334
     5335fi
     5336fi
     5337RANLIB=$ac_cv_prog_RANLIB
     5338if test -n "$RANLIB"; then
     5339  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
     5340$as_echo "$RANLIB" >&6; }
     5341else
     5342  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5343$as_echo "no" >&6; }
     5344fi
     5345
     5346
     5347fi
     5348if test -z "$ac_cv_prog_RANLIB"; then
     5349  ac_ct_RANLIB=$RANLIB
     5350  # Extract the first word of "ranlib", so it can be a program name with args.
     5351set dummy ranlib; ac_word=$2
     5352{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
     5353$as_echo_n "checking for $ac_word... " >&6; }
     5354if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
     5355  $as_echo_n "(cached) " >&6
     5356else
     5357  if test -n "$ac_ct_RANLIB"; then
     5358  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
     5359else
     5360as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     5361for as_dir in $PATH
     5362do
     5363  IFS=$as_save_IFS
     5364  test -z "$as_dir" && as_dir=.
     5365    for ac_exec_ext in '' $ac_executable_extensions; do
     5366  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     5367    ac_cv_prog_ac_ct_RANLIB="ranlib"
     5368    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     5369    break 2
    54875370  fi
    5488 else
    5489   ac_cv_path_SED=$SED
    5490 fi
    5491 
    5492 fi
    5493 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
    5494 $as_echo "$ac_cv_path_SED" >&6; }
    5495  SED="$ac_cv_path_SED"
    5496   rm -f conftest.sed
    5497 
    5498 test -z "$SED" && SED=sed
    5499 Xsed="$SED -e 1s/^X//"
    5500 
    5501 
    5502 
    5503 
    5504 
    5505 
    5506 
    5507 
    5508 
     5371done
     5372  done
     5373IFS=$as_save_IFS
     5374
     5375fi
     5376fi
     5377ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
     5378if test -n "$ac_ct_RANLIB"; then
     5379  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
     5380$as_echo "$ac_ct_RANLIB" >&6; }
     5381else
     5382  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5383$as_echo "no" >&6; }
     5384fi
     5385
     5386  if test "x$ac_ct_RANLIB" = x; then
     5387    RANLIB=":"
     5388  else
     5389    case $cross_compiling:$ac_tool_warned in
     5390yes:)
     5391{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
     5392$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
     5393ac_tool_warned=yes ;;
     5394esac
     5395    RANLIB=$ac_ct_RANLIB
     5396  fi
     5397else
     5398  RANLIB="$ac_cv_prog_RANLIB"
     5399fi
     5400
     5401
     5402# Checks for libraries.
     5403
     5404# Checks for header files.
     5405ac_ext=c
     5406ac_cpp='$CPP $CPPFLAGS'
     5407ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     5408ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     5409ac_compiler_gnu=$ac_cv_c_compiler_gnu
     5410{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
     5411$as_echo_n "checking how to run the C preprocessor... " >&6; }
     5412# On Suns, sometimes $CPP names a directory.
     5413if test -n "$CPP" && test -d "$CPP"; then
     5414  CPP=
     5415fi
     5416if test -z "$CPP"; then
     5417  if ${ac_cv_prog_CPP+:} false; then :
     5418  $as_echo_n "(cached) " >&6
     5419else
     5420      # Double quotes because CPP needs to be expanded
     5421    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
     5422    do
     5423      ac_preproc_ok=false
     5424for ac_c_preproc_warn_flag in '' yes
     5425do
     5426  # Use a header file that comes with gcc, so configuring glibc
     5427  # with a fresh cross-compiler works.
     5428  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
     5429  # <limits.h> exists even on freestanding compilers.
     5430  # On the NeXT, cc -E runs the code through the compiler's parser,
     5431  # not just through cpp. "Syntax error" is here to catch this case.
     5432  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     5433/* end confdefs.h.  */
     5434#ifdef __STDC__
     5435# include <limits.h>
     5436#else
     5437# include <assert.h>
     5438#endif
     5439                     Syntax error
     5440_ACEOF
     5441if ac_fn_c_try_cpp "$LINENO"; then :
     5442
     5443else
     5444  # Broken: fails on valid input.
     5445continue
     5446fi
     5447rm -f conftest.err conftest.i conftest.$ac_ext
     5448
     5449  # OK, works on sane cases.  Now check whether nonexistent headers
     5450  # can be detected and how.
     5451  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     5452/* end confdefs.h.  */
     5453#include <ac_nonexistent.h>
     5454_ACEOF
     5455if ac_fn_c_try_cpp "$LINENO"; then :
     5456  # Broken: success on invalid input.
     5457continue
     5458else
     5459  # Passes both tests.
     5460ac_preproc_ok=:
     5461break
     5462fi
     5463rm -f conftest.err conftest.i conftest.$ac_ext
     5464
     5465done
     5466# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
     5467rm -f conftest.i conftest.err conftest.$ac_ext
     5468if $ac_preproc_ok; then :
     5469  break
     5470fi
     5471
     5472    done
     5473    ac_cv_prog_CPP=$CPP
     5474
     5475fi
     5476  CPP=$ac_cv_prog_CPP
     5477else
     5478  ac_cv_prog_CPP=$CPP
     5479fi
     5480{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
     5481$as_echo "$CPP" >&6; }
     5482ac_preproc_ok=false
     5483for ac_c_preproc_warn_flag in '' yes
     5484do
     5485  # Use a header file that comes with gcc, so configuring glibc
     5486  # with a fresh cross-compiler works.
     5487  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
     5488  # <limits.h> exists even on freestanding compilers.
     5489  # On the NeXT, cc -E runs the code through the compiler's parser,
     5490  # not just through cpp. "Syntax error" is here to catch this case.
     5491  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     5492/* end confdefs.h.  */
     5493#ifdef __STDC__
     5494# include <limits.h>
     5495#else
     5496# include <assert.h>
     5497#endif
     5498                     Syntax error
     5499_ACEOF
     5500if ac_fn_c_try_cpp "$LINENO"; then :
     5501
     5502else
     5503  # Broken: fails on valid input.
     5504continue
     5505fi
     5506rm -f conftest.err conftest.i conftest.$ac_ext
     5507
     5508  # OK, works on sane cases.  Now check whether nonexistent headers
     5509  # can be detected and how.
     5510  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     5511/* end confdefs.h.  */
     5512#include <ac_nonexistent.h>
     5513_ACEOF
     5514if ac_fn_c_try_cpp "$LINENO"; then :
     5515  # Broken: success on invalid input.
     5516continue
     5517else
     5518  # Passes both tests.
     5519ac_preproc_ok=:
     5520break
     5521fi
     5522rm -f conftest.err conftest.i conftest.$ac_ext
     5523
     5524done
     5525# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
     5526rm -f conftest.i conftest.err conftest.$ac_ext
     5527if $ac_preproc_ok; then :
     5528
     5529else
     5530  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
     5531$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
     5532as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
     5533See \`config.log' for more details" "$LINENO" 5; }
     5534fi
     5535
     5536ac_ext=c
     5537ac_cpp='$CPP $CPPFLAGS'
     5538ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     5539ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     5540ac_compiler_gnu=$ac_cv_c_compiler_gnu
    55095541
    55105542
     
    56395671
    56405672
    5641 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
    5642 $as_echo_n "checking for fgrep... " >&6; }
    5643 if ${ac_cv_path_FGREP+:} false; then :
    5644   $as_echo_n "(cached) " >&6
    5645 else
    5646   if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
    5647    then ac_cv_path_FGREP="$GREP -F"
    5648    else
    5649      if test -z "$FGREP"; then
    5650   ac_path_FGREP_found=false
    5651   # Loop through the user's path and test for each of PROGNAME-LIST
    5652   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    5653 for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
    5654 do
    5655   IFS=$as_save_IFS
    5656   test -z "$as_dir" && as_dir=.
    5657     for ac_prog in fgrep; do
    5658     for ac_exec_ext in '' $ac_executable_extensions; do
    5659       ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
    5660       as_fn_executable_p "$ac_path_FGREP" || continue
    5661 # Check for GNU ac_path_FGREP and select it if it is found.
    5662   # Check for GNU $ac_path_FGREP
    5663 case `"$ac_path_FGREP" --version 2>&1` in
    5664 *GNU*)
    5665   ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
    5666 *)
    5667   ac_count=0
    5668   $as_echo_n 0123456789 >"conftest.in"
    5669   while :
    5670   do
    5671     cat "conftest.in" "conftest.in" >"conftest.tmp"
    5672     mv "conftest.tmp" "conftest.in"
    5673     cp "conftest.in" "conftest.nl"
    5674     $as_echo 'FGREP' >> "conftest.nl"
    5675     "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
    5676     diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
    5677     as_fn_arith $ac_count + 1 && ac_count=$as_val
    5678     if test $ac_count -gt ${ac_path_FGREP_max-0}; then
    5679       # Best one so far, save it but keep looking for a better one
    5680       ac_cv_path_FGREP="$ac_path_FGREP"
    5681       ac_path_FGREP_max=$ac_count
    5682     fi
    5683     # 10*(2^10) chars as input seems more than enough
    5684     test $ac_count -gt 10 && break
    5685   done
    5686   rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
    5687 esac
    5688 
    5689       $ac_path_FGREP_found && break 3
    5690     done
    5691   done
    5692   done
    5693 IFS=$as_save_IFS
    5694   if test -z "$ac_cv_path_FGREP"; then
    5695     as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
    5696   fi
    5697 else
    5698   ac_cv_path_FGREP=$FGREP
    5699 fi
    5700 
    5701    fi
    5702 fi
    5703 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
    5704 $as_echo "$ac_cv_path_FGREP" >&6; }
    5705  FGREP="$ac_cv_path_FGREP"
    5706 
    5707 
    5708 test -z "$GREP" && GREP=grep
    5709 
    5710 
    5711 
    5712 
    5713 
    5714 
    5715 
    5716 
    5717 
    5718 
    5719 
    5720 
    5721 
    5722 
    5723 
    5724 
    5725 
    5726 
    5727 
    5728 # Check whether --with-gnu-ld was given.
    5729 if test "${with_gnu_ld+set}" = set; then :
    5730   withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
    5731 else
    5732   with_gnu_ld=no
    5733 fi
    5734 
    5735 ac_prog=ld
    5736 if test yes = "$GCC"; then
    5737   # Check if gcc -print-prog-name=ld gives a path.
    5738   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
    5739 $as_echo_n "checking for ld used by $CC... " >&6; }
    5740   case $host in
    5741   *-*-mingw*)
    5742     # gcc leaves a trailing carriage return, which upsets mingw
    5743     ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
    5744   *)
    5745     ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
    5746   esac
    5747   case $ac_prog in
    5748     # Accept absolute paths.
    5749     [\\/]* | ?:[\\/]*)
    5750       re_direlt='/[^/][^/]*/\.\./'
    5751       # Canonicalize the pathname of ld
    5752       ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
    5753       while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
    5754         ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
    5755       done
    5756       test -z "$LD" && LD=$ac_prog
    5757       ;;
    5758   "")
    5759     # If it fails, then pretend we aren't using GCC.
    5760     ac_prog=ld
    5761     ;;
    5762   *)
    5763     # If it is relative, then search for the first ld in PATH.
    5764     with_gnu_ld=unknown
    5765     ;;
    5766   esac
    5767 elif test yes = "$with_gnu_ld"; then
    5768   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
    5769 $as_echo_n "checking for GNU ld... " >&6; }
    5770 else
    5771   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
    5772 $as_echo_n "checking for non-GNU ld... " >&6; }
    5773 fi
    5774 if ${lt_cv_path_LD+:} false; then :
    5775   $as_echo_n "(cached) " >&6
    5776 else
    5777   if test -z "$LD"; then
    5778   lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
    5779   for ac_dir in $PATH; do
    5780     IFS=$lt_save_ifs
    5781     test -z "$ac_dir" && ac_dir=.
    5782     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
    5783       lt_cv_path_LD=$ac_dir/$ac_prog
    5784       # Check to see if the program is GNU ld.  I'd rather use --version,
    5785       # but apparently some variants of GNU ld only accept -v.
    5786       # Break only if it was the GNU/non-GNU ld that we prefer.
    5787       case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
    5788       *GNU* | *'with BFD'*)
    5789         test no != "$with_gnu_ld" && break
    5790         ;;
    5791       *)
    5792         test yes != "$with_gnu_ld" && break
    5793         ;;
    5794       esac
    5795     fi
    5796   done
    5797   IFS=$lt_save_ifs
    5798 else
    5799   lt_cv_path_LD=$LD # Let the user override the test with a path.
    5800 fi
    5801 fi
    5802 
    5803 LD=$lt_cv_path_LD
    5804 if test -n "$LD"; then
    5805   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
    5806 $as_echo "$LD" >&6; }
    5807 else
    5808   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    5809 $as_echo "no" >&6; }
    5810 fi
    5811 test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
    5812 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
    5813 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
    5814 if ${lt_cv_prog_gnu_ld+:} false; then :
    5815   $as_echo_n "(cached) " >&6
    5816 else
    5817   # I'd rather use --version here, but apparently some GNU lds only accept -v.
    5818 case `$LD -v 2>&1 </dev/null` in
    5819 *GNU* | *'with BFD'*)
    5820   lt_cv_prog_gnu_ld=yes
    5821   ;;
    5822 *)
    5823   lt_cv_prog_gnu_ld=no
    5824   ;;
    5825 esac
    5826 fi
    5827 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
    5828 $as_echo "$lt_cv_prog_gnu_ld" >&6; }
    5829 with_gnu_ld=$lt_cv_prog_gnu_ld
    5830 
    5831 
    5832 
    5833 
    5834 
    5835 
    5836 
    5837 
    5838 
    5839 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
    5840 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
    5841 if ${lt_cv_path_NM+:} false; then :
    5842   $as_echo_n "(cached) " >&6
    5843 else
    5844   if test -n "$NM"; then
    5845   # Let the user override the test.
    5846   lt_cv_path_NM=$NM
    5847 else
    5848   lt_nm_to_check=${ac_tool_prefix}nm
    5849   if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
    5850     lt_nm_to_check="$lt_nm_to_check nm"
    5851   fi
    5852   for lt_tmp_nm in $lt_nm_to_check; do
    5853     lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
    5854     for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
    5855       IFS=$lt_save_ifs
    5856       test -z "$ac_dir" && ac_dir=.
    5857       tmp_nm=$ac_dir/$lt_tmp_nm
    5858       if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
    5859         # Check to see if the nm accepts a BSD-compat flag.
    5860         # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
    5861         #   nm: unknown option "B" ignored
    5862         # Tru64's nm complains that /dev/null is an invalid object file
    5863         # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
    5864         case $build_os in
    5865         mingw*) lt_bad_file=conftest.nm/nofile ;;
    5866         *) lt_bad_file=/dev/null ;;
    5867         esac
    5868         case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
    5869         *$lt_bad_file* | *'Invalid file or object type'*)
    5870           lt_cv_path_NM="$tmp_nm -B"
    5871           break 2
    5872           ;;
    5873         *)
    5874           case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
    5875           */dev/null*)
    5876             lt_cv_path_NM="$tmp_nm -p"
    5877             break 2
    5878             ;;
    5879           *)
    5880             lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
    5881             continue # so that we can try to find one that supports BSD flags
    5882             ;;
    5883           esac
    5884           ;;
    5885         esac
    5886       fi
    5887     done
    5888     IFS=$lt_save_ifs
    5889   done
    5890   : ${lt_cv_path_NM=no}
    5891 fi
    5892 fi
    5893 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
    5894 $as_echo "$lt_cv_path_NM" >&6; }
    5895 if test no != "$lt_cv_path_NM"; then
    5896   NM=$lt_cv_path_NM
    5897 else
    5898   # Didn't find any BSD compatible name lister, look for dumpbin.
    5899   if test -n "$DUMPBIN"; then :
    5900     # Let the user override the test.
    5901   else
    5902     if test -n "$ac_tool_prefix"; then
    5903   for ac_prog in dumpbin "link -dump"
    5904   do
    5905     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
    5906 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
    5907 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    5908 $as_echo_n "checking for $ac_word... " >&6; }
    5909 if ${ac_cv_prog_DUMPBIN+:} false; then :
    5910   $as_echo_n "(cached) " >&6
    5911 else
    5912   if test -n "$DUMPBIN"; then
    5913   ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
    5914 else
    5915 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    5916 for as_dir in $PATH
    5917 do
    5918   IFS=$as_save_IFS
    5919   test -z "$as_dir" && as_dir=.
    5920     for ac_exec_ext in '' $ac_executable_extensions; do
    5921   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    5922     ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
    5923     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    5924     break 2
    5925   fi
    5926 done
    5927   done
    5928 IFS=$as_save_IFS
    5929 
    5930 fi
    5931 fi
    5932 DUMPBIN=$ac_cv_prog_DUMPBIN
    5933 if test -n "$DUMPBIN"; then
    5934   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
    5935 $as_echo "$DUMPBIN" >&6; }
    5936 else
    5937   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    5938 $as_echo "no" >&6; }
    5939 fi
    5940 
    5941 
    5942     test -n "$DUMPBIN" && break
    5943   done
    5944 fi
    5945 if test -z "$DUMPBIN"; then
    5946   ac_ct_DUMPBIN=$DUMPBIN
    5947   for ac_prog in dumpbin "link -dump"
    5948 do
    5949   # Extract the first word of "$ac_prog", so it can be a program name with args.
    5950 set dummy $ac_prog; ac_word=$2
    5951 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    5952 $as_echo_n "checking for $ac_word... " >&6; }
    5953 if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
    5954   $as_echo_n "(cached) " >&6
    5955 else
    5956   if test -n "$ac_ct_DUMPBIN"; then
    5957   ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
    5958 else
    5959 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    5960 for as_dir in $PATH
    5961 do
    5962   IFS=$as_save_IFS
    5963   test -z "$as_dir" && as_dir=.
    5964     for ac_exec_ext in '' $ac_executable_extensions; do
    5965   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    5966     ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
    5967     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    5968     break 2
    5969   fi
    5970 done
    5971   done
    5972 IFS=$as_save_IFS
    5973 
    5974 fi
    5975 fi
    5976 ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
    5977 if test -n "$ac_ct_DUMPBIN"; then
    5978   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
    5979 $as_echo "$ac_ct_DUMPBIN" >&6; }
    5980 else
    5981   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    5982 $as_echo "no" >&6; }
    5983 fi
    5984 
    5985 
    5986   test -n "$ac_ct_DUMPBIN" && break
    5987 done
    5988 
    5989   if test "x$ac_ct_DUMPBIN" = x; then
    5990     DUMPBIN=":"
    5991   else
    5992     case $cross_compiling:$ac_tool_warned in
    5993 yes:)
    5994 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    5995 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    5996 ac_tool_warned=yes ;;
    5997 esac
    5998     DUMPBIN=$ac_ct_DUMPBIN
    5999   fi
    6000 fi
    6001 
    6002     case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
    6003     *COFF*)
    6004       DUMPBIN="$DUMPBIN -symbols -headers"
    6005       ;;
    6006     *)
    6007       DUMPBIN=:
    6008       ;;
    6009     esac
    6010   fi
    6011 
    6012   if test : != "$DUMPBIN"; then
    6013     NM=$DUMPBIN
    6014   fi
    6015 fi
    6016 test -z "$NM" && NM=nm
    6017 
    6018 
    6019 
    6020 
    6021 
    6022 
    6023 { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
    6024 $as_echo_n "checking the name lister ($NM) interface... " >&6; }
    6025 if ${lt_cv_nm_interface+:} false; then :
    6026   $as_echo_n "(cached) " >&6
    6027 else
    6028   lt_cv_nm_interface="BSD nm"
    6029   echo "int some_variable = 0;" > conftest.$ac_ext
    6030   (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
    6031   (eval "$ac_compile" 2>conftest.err)
    6032   cat conftest.err >&5
    6033   (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
    6034   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
    6035   cat conftest.err >&5
    6036   (eval echo "\"\$as_me:$LINENO: output\"" >&5)
    6037   cat conftest.out >&5
    6038   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
    6039     lt_cv_nm_interface="MS dumpbin"
    6040   fi
    6041   rm -f conftest*
    6042 fi
    6043 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
    6044 $as_echo "$lt_cv_nm_interface" >&6; }
    6045 
    6046 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
    6047 $as_echo_n "checking whether ln -s works... " >&6; }
    6048 LN_S=$as_ln_s
    6049 if test "$LN_S" = "ln -s"; then
    6050   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
    6051 $as_echo "yes" >&6; }
    6052 else
    6053   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
    6054 $as_echo "no, using $LN_S" >&6; }
    6055 fi
    6056 
    6057 # find the maximum length of command line arguments
    6058 { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
    6059 $as_echo_n "checking the maximum length of command line arguments... " >&6; }
    6060 if ${lt_cv_sys_max_cmd_len+:} false; then :
    6061   $as_echo_n "(cached) " >&6
    6062 else
    6063     i=0
    6064   teststring=ABCD
    6065 
    6066   case $build_os in
    6067   msdosdjgpp*)
    6068     # On DJGPP, this test can blow up pretty badly due to problems in libc
    6069     # (any single argument exceeding 2000 bytes causes a buffer overrun
    6070     # during glob expansion).  Even if it were fixed, the result of this
    6071     # check would be larger than it should be.
    6072     lt_cv_sys_max_cmd_len=12288;    # 12K is about right
    6073     ;;
    6074 
    6075   gnu*)
    6076     # Under GNU Hurd, this test is not required because there is
    6077     # no limit to the length of command line arguments.
    6078     # Libtool will interpret -1 as no limit whatsoever
    6079     lt_cv_sys_max_cmd_len=-1;
    6080     ;;
    6081 
    6082   cygwin* | mingw* | cegcc*)
    6083     # On Win9x/ME, this test blows up -- it succeeds, but takes
    6084     # about 5 minutes as the teststring grows exponentially.
    6085     # Worse, since 9x/ME are not pre-emptively multitasking,
    6086     # you end up with a "frozen" computer, even though with patience
    6087     # the test eventually succeeds (with a max line length of 256k).
    6088     # Instead, let's just punt: use the minimum linelength reported by
    6089     # all of the supported platforms: 8192 (on NT/2K/XP).
    6090     lt_cv_sys_max_cmd_len=8192;
    6091     ;;
    6092 
    6093   mint*)
    6094     # On MiNT this can take a long time and run out of memory.
    6095     lt_cv_sys_max_cmd_len=8192;
    6096     ;;
    6097 
    6098   amigaos*)
    6099     # On AmigaOS with pdksh, this test takes hours, literally.
    6100     # So we just punt and use a minimum line length of 8192.
    6101     lt_cv_sys_max_cmd_len=8192;
    6102     ;;
    6103 
    6104   bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
    6105     # This has been around since 386BSD, at least.  Likely further.
    6106     if test -x /sbin/sysctl; then
    6107       lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
    6108     elif test -x /usr/sbin/sysctl; then
    6109       lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
    6110     else
    6111       lt_cv_sys_max_cmd_len=65536       # usable default for all BSDs
    6112     fi
    6113     # And add a safety zone
    6114     lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
    6115     lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
    6116     ;;
    6117 
    6118   interix*)
    6119     # We know the value 262144 and hardcode it with a safety zone (like BSD)
    6120     lt_cv_sys_max_cmd_len=196608
    6121     ;;
    6122 
    6123   os2*)
    6124     # The test takes a long time on OS/2.
    6125     lt_cv_sys_max_cmd_len=8192
    6126     ;;
    6127 
    6128   osf*)
    6129     # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
    6130     # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
    6131     # nice to cause kernel panics so lets avoid the loop below.
    6132     # First set a reasonable default.
    6133     lt_cv_sys_max_cmd_len=16384
    6134     #
    6135     if test -x /sbin/sysconfig; then
    6136       case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
    6137         *1*) lt_cv_sys_max_cmd_len=-1 ;;
    6138       esac
    6139     fi
    6140     ;;
    6141   sco3.2v5*)
    6142     lt_cv_sys_max_cmd_len=102400
    6143     ;;
    6144   sysv5* | sco5v6* | sysv4.2uw2*)
    6145     kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
    6146     if test -n "$kargmax"; then
    6147       lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[  ]//'`
    6148     else
    6149       lt_cv_sys_max_cmd_len=32768
    6150     fi
    6151     ;;
    6152   *)
    6153     lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
    6154     if test -n "$lt_cv_sys_max_cmd_len" && \
    6155        test undefined != "$lt_cv_sys_max_cmd_len"; then
    6156       lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
    6157       lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
    6158     else
    6159       # Make teststring a little bigger before we do anything with it.
    6160       # a 1K string should be a reasonable start.
    6161       for i in 1 2 3 4 5 6 7 8; do
    6162         teststring=$teststring$teststring
    6163       done
    6164       SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
    6165       # If test is not a shell built-in, we'll probably end up computing a
    6166       # maximum length that is only half of the actual maximum length, but
    6167       # we can't tell.
    6168       while { test X`env echo "$teststring$teststring" 2>/dev/null` \
    6169                  = "X$teststring$teststring"; } >/dev/null 2>&1 &&
    6170               test 17 != "$i" # 1/2 MB should be enough
    6171       do
    6172         i=`expr $i + 1`
    6173         teststring=$teststring$teststring
    6174       done
    6175       # Only check the string length outside the loop.
    6176       lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
    6177       teststring=
    6178       # Add a significant safety factor because C++ compilers can tack on
    6179       # massive amounts of additional arguments before passing them to the
    6180       # linker.  It appears as though 1/2 is a usable value.
    6181       lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
    6182     fi
    6183     ;;
    6184   esac
    6185 
    6186 fi
    6187 
    6188 if test -n "$lt_cv_sys_max_cmd_len"; then
    6189   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
    6190 $as_echo "$lt_cv_sys_max_cmd_len" >&6; }
    6191 else
    6192   { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
    6193 $as_echo "none" >&6; }
    6194 fi
    6195 max_cmd_len=$lt_cv_sys_max_cmd_len
    6196 
    6197 
    6198 
    6199 
    6200 
    6201 
    6202 : ${CP="cp -f"}
    6203 : ${MV="mv -f"}
    6204 : ${RM="rm -f"}
    6205 
    6206 if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
    6207   lt_unset=unset
    6208 else
    6209   lt_unset=false
    6210 fi
    6211 
    6212 
    6213 
    6214 
    6215 
    6216 # test EBCDIC or ASCII
    6217 case `echo X|tr X '\101'` in
    6218  A) # ASCII based system
    6219     # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
    6220   lt_SP2NL='tr \040 \012'
    6221   lt_NL2SP='tr \015\012 \040\040'
    6222   ;;
    6223  *) # EBCDIC based system
    6224   lt_SP2NL='tr \100 \n'
    6225   lt_NL2SP='tr \r\n \100\100'
    6226   ;;
    6227 esac
    6228 
    6229 
    6230 
    6231 
    6232 
    6233 
    6234 
    6235 
    6236 
    6237 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
    6238 $as_echo_n "checking how to convert $build file names to $host format... " >&6; }
    6239 if ${lt_cv_to_host_file_cmd+:} false; then :
    6240   $as_echo_n "(cached) " >&6
    6241 else
    6242   case $host in
    6243   *-*-mingw* )
    6244     case $build in
    6245       *-*-mingw* ) # actually msys
    6246         lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
    6247         ;;
    6248       *-*-cygwin* )
    6249         lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
    6250         ;;
    6251       * ) # otherwise, assume *nix
    6252         lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
    6253         ;;
    6254     esac
    6255     ;;
    6256   *-*-cygwin* )
    6257     case $build in
    6258       *-*-mingw* ) # actually msys
    6259         lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
    6260         ;;
    6261       *-*-cygwin* )
    6262         lt_cv_to_host_file_cmd=func_convert_file_noop
    6263         ;;
    6264       * ) # otherwise, assume *nix
    6265         lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
    6266         ;;
    6267     esac
    6268     ;;
    6269   * ) # unhandled hosts (and "normal" native builds)
    6270     lt_cv_to_host_file_cmd=func_convert_file_noop
    6271     ;;
    6272 esac
    6273 
    6274 fi
    6275 
    6276 to_host_file_cmd=$lt_cv_to_host_file_cmd
    6277 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
    6278 $as_echo "$lt_cv_to_host_file_cmd" >&6; }
    6279 
    6280 
    6281 
    6282 
    6283 
    6284 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
    6285 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
    6286 if ${lt_cv_to_tool_file_cmd+:} false; then :
    6287   $as_echo_n "(cached) " >&6
    6288 else
    6289   #assume ordinary cross tools, or native build.
    6290 lt_cv_to_tool_file_cmd=func_convert_file_noop
    6291 case $host in
    6292   *-*-mingw* )
    6293     case $build in
    6294       *-*-mingw* ) # actually msys
    6295         lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
    6296         ;;
    6297     esac
    6298     ;;
    6299 esac
    6300 
    6301 fi
    6302 
    6303 to_tool_file_cmd=$lt_cv_to_tool_file_cmd
    6304 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
    6305 $as_echo "$lt_cv_to_tool_file_cmd" >&6; }
    6306 
    6307 
    6308 
    6309 
    6310 
    6311 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
    6312 $as_echo_n "checking for $LD option to reload object files... " >&6; }
    6313 if ${lt_cv_ld_reload_flag+:} false; then :
    6314   $as_echo_n "(cached) " >&6
    6315 else
    6316   lt_cv_ld_reload_flag='-r'
    6317 fi
    6318 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
    6319 $as_echo "$lt_cv_ld_reload_flag" >&6; }
    6320 reload_flag=$lt_cv_ld_reload_flag
    6321 case $reload_flag in
    6322 "" | " "*) ;;
    6323 *) reload_flag=" $reload_flag" ;;
    6324 esac
    6325 reload_cmds='$LD$reload_flag -o $output$reload_objs'
    6326 case $host_os in
    6327   cygwin* | mingw* | pw32* | cegcc*)
    6328     if test yes != "$GCC"; then
    6329       reload_cmds=false
    6330     fi
    6331     ;;
    6332   darwin*)
    6333     if test yes = "$GCC"; then
    6334       reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
    6335     else
    6336       reload_cmds='$LD$reload_flag -o $output$reload_objs'
    6337     fi
    6338     ;;
    6339 esac
    6340 
    6341 
    6342 
    6343 
    6344 
    6345 
    6346 
    6347 
    6348 
    6349 if test -n "$ac_tool_prefix"; then
    6350   # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
    6351 set dummy ${ac_tool_prefix}objdump; ac_word=$2
    6352 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    6353 $as_echo_n "checking for $ac_word... " >&6; }
    6354 if ${ac_cv_prog_OBJDUMP+:} false; then :
    6355   $as_echo_n "(cached) " >&6
    6356 else
    6357   if test -n "$OBJDUMP"; then
    6358   ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
    6359 else
    6360 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    6361 for as_dir in $PATH
    6362 do
    6363   IFS=$as_save_IFS
    6364   test -z "$as_dir" && as_dir=.
    6365     for ac_exec_ext in '' $ac_executable_extensions; do
    6366   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    6367     ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
    6368     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    6369     break 2
    6370   fi
    6371 done
    6372   done
    6373 IFS=$as_save_IFS
    6374 
    6375 fi
    6376 fi
    6377 OBJDUMP=$ac_cv_prog_OBJDUMP
    6378 if test -n "$OBJDUMP"; then
    6379   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
    6380 $as_echo "$OBJDUMP" >&6; }
    6381 else
    6382   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    6383 $as_echo "no" >&6; }
    6384 fi
    6385 
    6386 
    6387 fi
    6388 if test -z "$ac_cv_prog_OBJDUMP"; then
    6389   ac_ct_OBJDUMP=$OBJDUMP
    6390   # Extract the first word of "objdump", so it can be a program name with args.
    6391 set dummy objdump; ac_word=$2
    6392 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    6393 $as_echo_n "checking for $ac_word... " >&6; }
    6394 if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
    6395   $as_echo_n "(cached) " >&6
    6396 else
    6397   if test -n "$ac_ct_OBJDUMP"; then
    6398   ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
    6399 else
    6400 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    6401 for as_dir in $PATH
    6402 do
    6403   IFS=$as_save_IFS
    6404   test -z "$as_dir" && as_dir=.
    6405     for ac_exec_ext in '' $ac_executable_extensions; do
    6406   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    6407     ac_cv_prog_ac_ct_OBJDUMP="objdump"
    6408     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    6409     break 2
    6410   fi
    6411 done
    6412   done
    6413 IFS=$as_save_IFS
    6414 
    6415 fi
    6416 fi
    6417 ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
    6418 if test -n "$ac_ct_OBJDUMP"; then
    6419   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
    6420 $as_echo "$ac_ct_OBJDUMP" >&6; }
    6421 else
    6422   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    6423 $as_echo "no" >&6; }
    6424 fi
    6425 
    6426   if test "x$ac_ct_OBJDUMP" = x; then
    6427     OBJDUMP="false"
    6428   else
    6429     case $cross_compiling:$ac_tool_warned in
    6430 yes:)
    6431 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    6432 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    6433 ac_tool_warned=yes ;;
    6434 esac
    6435     OBJDUMP=$ac_ct_OBJDUMP
    6436   fi
    6437 else
    6438   OBJDUMP="$ac_cv_prog_OBJDUMP"
    6439 fi
    6440 
    6441 test -z "$OBJDUMP" && OBJDUMP=objdump
    6442 
    6443 
    6444 
    6445 
    6446 
    6447 
    6448 
    6449 
    6450 
    6451 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
    6452 $as_echo_n "checking how to recognize dependent libraries... " >&6; }
    6453 if ${lt_cv_deplibs_check_method+:} false; then :
    6454   $as_echo_n "(cached) " >&6
    6455 else
    6456   lt_cv_file_magic_cmd='$MAGIC_CMD'
    6457 lt_cv_file_magic_test_file=
    6458 lt_cv_deplibs_check_method='unknown'
    6459 # Need to set the preceding variable on all platforms that support
    6460 # interlibrary dependencies.
    6461 # 'none' -- dependencies not supported.
    6462 # 'unknown' -- same as none, but documents that we really don't know.
    6463 # 'pass_all' -- all dependencies passed with no checks.
    6464 # 'test_compile' -- check by making test program.
    6465 # 'file_magic [[regex]]' -- check by looking for files in library path
    6466 # that responds to the $file_magic_cmd with a given extended regex.
    6467 # If you have 'file' or equivalent on your system and you're not sure
    6468 # whether 'pass_all' will *always* work, you probably want this one.
    6469 
    6470 case $host_os in
    6471 aix[4-9]*)
    6472   lt_cv_deplibs_check_method=pass_all
    6473   ;;
    6474 
    6475 beos*)
    6476   lt_cv_deplibs_check_method=pass_all
    6477   ;;
    6478 
    6479 bsdi[45]*)
    6480   lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
    6481   lt_cv_file_magic_cmd='/usr/bin/file -L'
    6482   lt_cv_file_magic_test_file=/shlib/libc.so
    6483   ;;
    6484 
    6485 cygwin*)
    6486   # func_win32_libid is a shell function defined in ltmain.sh
    6487   lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
    6488   lt_cv_file_magic_cmd='func_win32_libid'
    6489   ;;
    6490 
    6491 mingw* | pw32*)
    6492   # Base MSYS/MinGW do not provide the 'file' command needed by
    6493   # func_win32_libid shell function, so use a weaker test based on 'objdump',
    6494   # unless we find 'file', for example because we are cross-compiling.
    6495   if ( file / ) >/dev/null 2>&1; then
    6496     lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
    6497     lt_cv_file_magic_cmd='func_win32_libid'
    6498   else
    6499     # Keep this pattern in sync with the one in func_win32_libid.
    6500     lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
    6501     lt_cv_file_magic_cmd='$OBJDUMP -f'
    6502   fi
    6503   ;;
    6504 
    6505 cegcc*)
    6506   # use the weaker test based on 'objdump'. See mingw*.
    6507   lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
    6508   lt_cv_file_magic_cmd='$OBJDUMP -f'
    6509   ;;
    6510 
    6511 darwin* | rhapsody*)
    6512   lt_cv_deplibs_check_method=pass_all
    6513   ;;
    6514 
    6515 freebsd* | dragonfly*)
    6516   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
    6517     case $host_cpu in
    6518     i*86 )
    6519       # Not sure whether the presence of OpenBSD here was a mistake.
    6520       # Let's accept both of them until this is cleared up.
    6521       lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
    6522       lt_cv_file_magic_cmd=/usr/bin/file
    6523       lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
    6524       ;;
    6525     esac
    6526   else
    6527     lt_cv_deplibs_check_method=pass_all
    6528   fi
    6529   ;;
    6530 
    6531 haiku*)
    6532   lt_cv_deplibs_check_method=pass_all
    6533   ;;
    6534 
    6535 hpux10.20* | hpux11*)
    6536   lt_cv_file_magic_cmd=/usr/bin/file
    6537   case $host_cpu in
    6538   ia64*)
    6539     lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
    6540     lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
    6541     ;;
    6542   hppa*64*)
    6543     lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
    6544     lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
    6545     ;;
    6546   *)
    6547     lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
    6548     lt_cv_file_magic_test_file=/usr/lib/libc.sl
    6549     ;;
    6550   esac
    6551   ;;
    6552 
    6553 interix[3-9]*)
    6554   # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
    6555   lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
    6556   ;;
    6557 
    6558 irix5* | irix6* | nonstopux*)
    6559   case $LD in
    6560   *-32|*"-32 ") libmagic=32-bit;;
    6561   *-n32|*"-n32 ") libmagic=N32;;
    6562   *-64|*"-64 ") libmagic=64-bit;;
    6563   *) libmagic=never-match;;
    6564   esac
    6565   lt_cv_deplibs_check_method=pass_all
    6566   ;;
    6567 
    6568 # This must be glibc/ELF.
    6569 linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    6570   lt_cv_deplibs_check_method=pass_all
    6571   ;;
    6572 
    6573 netbsd* | netbsdelf*-gnu)
    6574   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
    6575     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
    6576   else
    6577     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
    6578   fi
    6579   ;;
    6580 
    6581 newos6*)
    6582   lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
    6583   lt_cv_file_magic_cmd=/usr/bin/file
    6584   lt_cv_file_magic_test_file=/usr/lib/libnls.so
    6585   ;;
    6586 
    6587 *nto* | *qnx*)
    6588   lt_cv_deplibs_check_method=pass_all
    6589   ;;
    6590 
    6591 openbsd* | bitrig*)
    6592   if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
    6593     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
    6594   else
    6595     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
    6596   fi
    6597   ;;
    6598 
    6599 osf3* | osf4* | osf5*)
    6600   lt_cv_deplibs_check_method=pass_all
    6601   ;;
    6602 
    6603 rdos*)
    6604   lt_cv_deplibs_check_method=pass_all
    6605   ;;
    6606 
    6607 solaris*)
    6608   lt_cv_deplibs_check_method=pass_all
    6609   ;;
    6610 
    6611 sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
    6612   lt_cv_deplibs_check_method=pass_all
    6613   ;;
    6614 
    6615 sysv4 | sysv4.3*)
    6616   case $host_vendor in
    6617   motorola)
    6618     lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
    6619     lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
    6620     ;;
    6621   ncr)
    6622     lt_cv_deplibs_check_method=pass_all
    6623     ;;
    6624   sequent)
    6625     lt_cv_file_magic_cmd='/bin/file'
    6626     lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
    6627     ;;
    6628   sni)
    6629     lt_cv_file_magic_cmd='/bin/file'
    6630     lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
    6631     lt_cv_file_magic_test_file=/lib/libc.so
    6632     ;;
    6633   siemens)
    6634     lt_cv_deplibs_check_method=pass_all
    6635     ;;
    6636   pc)
    6637     lt_cv_deplibs_check_method=pass_all
    6638     ;;
    6639   esac
    6640   ;;
    6641 
    6642 tpf*)
    6643   lt_cv_deplibs_check_method=pass_all
    6644   ;;
    6645 os2*)
    6646   lt_cv_deplibs_check_method=pass_all
    6647   ;;
    6648 esac
    6649 
    6650 fi
    6651 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
    6652 $as_echo "$lt_cv_deplibs_check_method" >&6; }
    6653 
    6654 file_magic_glob=
    6655 want_nocaseglob=no
    6656 if test "$build" = "$host"; then
    6657   case $host_os in
    6658   mingw* | pw32*)
    6659     if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
    6660       want_nocaseglob=yes
    6661     else
    6662       file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
    6663     fi
    6664     ;;
    6665   esac
    6666 fi
    6667 
    6668 file_magic_cmd=$lt_cv_file_magic_cmd
    6669 deplibs_check_method=$lt_cv_deplibs_check_method
    6670 test -z "$deplibs_check_method" && deplibs_check_method=unknown
    6671 
    6672 
    6673 
    6674 
    6675 
    6676 
    6677 
    6678 
    6679 
    6680 
    6681 
    6682 
    6683 
    6684 
    6685 
    6686 
    6687 
    6688 
    6689 
    6690 
    6691 
    6692 
    6693 if test -n "$ac_tool_prefix"; then
    6694   # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
    6695 set dummy ${ac_tool_prefix}dlltool; ac_word=$2
    6696 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    6697 $as_echo_n "checking for $ac_word... " >&6; }
    6698 if ${ac_cv_prog_DLLTOOL+:} false; then :
    6699   $as_echo_n "(cached) " >&6
    6700 else
    6701   if test -n "$DLLTOOL"; then
    6702   ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
    6703 else
    6704 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    6705 for as_dir in $PATH
    6706 do
    6707   IFS=$as_save_IFS
    6708   test -z "$as_dir" && as_dir=.
    6709     for ac_exec_ext in '' $ac_executable_extensions; do
    6710   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    6711     ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
    6712     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    6713     break 2
    6714   fi
    6715 done
    6716   done
    6717 IFS=$as_save_IFS
    6718 
    6719 fi
    6720 fi
    6721 DLLTOOL=$ac_cv_prog_DLLTOOL
    6722 if test -n "$DLLTOOL"; then
    6723   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
    6724 $as_echo "$DLLTOOL" >&6; }
    6725 else
    6726   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    6727 $as_echo "no" >&6; }
    6728 fi
    6729 
    6730 
    6731 fi
    6732 if test -z "$ac_cv_prog_DLLTOOL"; then
    6733   ac_ct_DLLTOOL=$DLLTOOL
    6734   # Extract the first word of "dlltool", so it can be a program name with args.
    6735 set dummy dlltool; ac_word=$2
    6736 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    6737 $as_echo_n "checking for $ac_word... " >&6; }
    6738 if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
    6739   $as_echo_n "(cached) " >&6
    6740 else
    6741   if test -n "$ac_ct_DLLTOOL"; then
    6742   ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
    6743 else
    6744 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    6745 for as_dir in $PATH
    6746 do
    6747   IFS=$as_save_IFS
    6748   test -z "$as_dir" && as_dir=.
    6749     for ac_exec_ext in '' $ac_executable_extensions; do
    6750   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    6751     ac_cv_prog_ac_ct_DLLTOOL="dlltool"
    6752     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    6753     break 2
    6754   fi
    6755 done
    6756   done
    6757 IFS=$as_save_IFS
    6758 
    6759 fi
    6760 fi
    6761 ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
    6762 if test -n "$ac_ct_DLLTOOL"; then
    6763   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
    6764 $as_echo "$ac_ct_DLLTOOL" >&6; }
    6765 else
    6766   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    6767 $as_echo "no" >&6; }
    6768 fi
    6769 
    6770   if test "x$ac_ct_DLLTOOL" = x; then
    6771     DLLTOOL="false"
    6772   else
    6773     case $cross_compiling:$ac_tool_warned in
    6774 yes:)
    6775 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    6776 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    6777 ac_tool_warned=yes ;;
    6778 esac
    6779     DLLTOOL=$ac_ct_DLLTOOL
    6780   fi
    6781 else
    6782   DLLTOOL="$ac_cv_prog_DLLTOOL"
    6783 fi
    6784 
    6785 test -z "$DLLTOOL" && DLLTOOL=dlltool
    6786 
    6787 
    6788 
    6789 
    6790 
    6791 
    6792 
    6793 
    6794 
    6795 
    6796 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
    6797 $as_echo_n "checking how to associate runtime and link libraries... " >&6; }
    6798 if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
    6799   $as_echo_n "(cached) " >&6
    6800 else
    6801   lt_cv_sharedlib_from_linklib_cmd='unknown'
    6802 
    6803 case $host_os in
    6804 cygwin* | mingw* | pw32* | cegcc*)
    6805   # two different shell functions defined in ltmain.sh;
    6806   # decide which one to use based on capabilities of $DLLTOOL
    6807   case `$DLLTOOL --help 2>&1` in
    6808   *--identify-strict*)
    6809     lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
    6810     ;;
    6811   *)
    6812     lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
    6813     ;;
    6814   esac
    6815   ;;
    6816 *)
    6817   # fallback: assume linklib IS sharedlib
    6818   lt_cv_sharedlib_from_linklib_cmd=$ECHO
    6819   ;;
    6820 esac
    6821 
    6822 fi
    6823 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
    6824 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
    6825 sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
    6826 test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
    6827 
    6828 
    6829 
    6830 
    6831 
    6832 
    6833 
    6834 if test -n "$ac_tool_prefix"; then
    6835   for ac_prog in ar
    6836   do
    6837     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
    6838 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
    6839 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    6840 $as_echo_n "checking for $ac_word... " >&6; }
    6841 if ${ac_cv_prog_AR+:} false; then :
    6842   $as_echo_n "(cached) " >&6
    6843 else
    6844   if test -n "$AR"; then
    6845   ac_cv_prog_AR="$AR" # Let the user override the test.
    6846 else
    6847 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    6848 for as_dir in $PATH
    6849 do
    6850   IFS=$as_save_IFS
    6851   test -z "$as_dir" && as_dir=.
    6852     for ac_exec_ext in '' $ac_executable_extensions; do
    6853   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    6854     ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
    6855     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    6856     break 2
    6857   fi
    6858 done
    6859   done
    6860 IFS=$as_save_IFS
    6861 
    6862 fi
    6863 fi
    6864 AR=$ac_cv_prog_AR
    6865 if test -n "$AR"; then
    6866   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
    6867 $as_echo "$AR" >&6; }
    6868 else
    6869   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    6870 $as_echo "no" >&6; }
    6871 fi
    6872 
    6873 
    6874     test -n "$AR" && break
    6875   done
    6876 fi
    6877 if test -z "$AR"; then
    6878   ac_ct_AR=$AR
    6879   for ac_prog in ar
    6880 do
    6881   # Extract the first word of "$ac_prog", so it can be a program name with args.
    6882 set dummy $ac_prog; ac_word=$2
    6883 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    6884 $as_echo_n "checking for $ac_word... " >&6; }
    6885 if ${ac_cv_prog_ac_ct_AR+:} false; then :
    6886   $as_echo_n "(cached) " >&6
    6887 else
    6888   if test -n "$ac_ct_AR"; then
    6889   ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
    6890 else
    6891 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    6892 for as_dir in $PATH
    6893 do
    6894   IFS=$as_save_IFS
    6895   test -z "$as_dir" && as_dir=.
    6896     for ac_exec_ext in '' $ac_executable_extensions; do
    6897   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    6898     ac_cv_prog_ac_ct_AR="$ac_prog"
    6899     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    6900     break 2
    6901   fi
    6902 done
    6903   done
    6904 IFS=$as_save_IFS
    6905 
    6906 fi
    6907 fi
    6908 ac_ct_AR=$ac_cv_prog_ac_ct_AR
    6909 if test -n "$ac_ct_AR"; then
    6910   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
    6911 $as_echo "$ac_ct_AR" >&6; }
    6912 else
    6913   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    6914 $as_echo "no" >&6; }
    6915 fi
    6916 
    6917 
    6918   test -n "$ac_ct_AR" && break
    6919 done
    6920 
    6921   if test "x$ac_ct_AR" = x; then
    6922     AR="false"
    6923   else
    6924     case $cross_compiling:$ac_tool_warned in
    6925 yes:)
    6926 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    6927 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    6928 ac_tool_warned=yes ;;
    6929 esac
    6930     AR=$ac_ct_AR
    6931   fi
    6932 fi
    6933 
    6934 : ${AR=ar}
    6935 : ${AR_FLAGS=cru}
    6936 
    6937 
    6938 
    6939 
    6940 
    6941 
    6942 
    6943 
    6944 
    6945 
    6946 
    6947 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
    6948 $as_echo_n "checking for archiver @FILE support... " >&6; }
    6949 if ${lt_cv_ar_at_file+:} false; then :
    6950   $as_echo_n "(cached) " >&6
    6951 else
    6952   lt_cv_ar_at_file=no
    6953    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    6954 /* end confdefs.h.  */
    6955 
    6956 int
    6957 main ()
    6958 {
    6959 
    6960   ;
    6961   return 0;
    6962 }
    6963 _ACEOF
    6964 if ac_fn_c_try_compile "$LINENO"; then :
    6965   echo conftest.$ac_objext > conftest.lst
    6966       lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
    6967       { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
    6968   (eval $lt_ar_try) 2>&5
    6969   ac_status=$?
    6970   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    6971   test $ac_status = 0; }
    6972       if test 0 -eq "$ac_status"; then
    6973         # Ensure the archiver fails upon bogus file names.
    6974         rm -f conftest.$ac_objext libconftest.a
    6975         { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
    6976   (eval $lt_ar_try) 2>&5
    6977   ac_status=$?
    6978   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    6979   test $ac_status = 0; }
    6980         if test 0 -ne "$ac_status"; then
    6981           lt_cv_ar_at_file=@
    6982         fi
    6983       fi
    6984       rm -f conftest.* libconftest.a
    6985 
    6986 fi
    6987 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    6988 
    6989 fi
    6990 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
    6991 $as_echo "$lt_cv_ar_at_file" >&6; }
    6992 
    6993 if test no = "$lt_cv_ar_at_file"; then
    6994   archiver_list_spec=
    6995 else
    6996   archiver_list_spec=$lt_cv_ar_at_file
    6997 fi
    6998 
    6999 
    7000 
    7001 
    7002 
    7003 
    7004 
    7005 if test -n "$ac_tool_prefix"; then
    7006   # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
    7007 set dummy ${ac_tool_prefix}strip; ac_word=$2
    7008 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    7009 $as_echo_n "checking for $ac_word... " >&6; }
    7010 if ${ac_cv_prog_STRIP+:} false; then :
    7011   $as_echo_n "(cached) " >&6
    7012 else
    7013   if test -n "$STRIP"; then
    7014   ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
    7015 else
    7016 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    7017 for as_dir in $PATH
    7018 do
    7019   IFS=$as_save_IFS
    7020   test -z "$as_dir" && as_dir=.
    7021     for ac_exec_ext in '' $ac_executable_extensions; do
    7022   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    7023     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
    7024     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    7025     break 2
    7026   fi
    7027 done
    7028   done
    7029 IFS=$as_save_IFS
    7030 
    7031 fi
    7032 fi
    7033 STRIP=$ac_cv_prog_STRIP
    7034 if test -n "$STRIP"; then
    7035   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
    7036 $as_echo "$STRIP" >&6; }
    7037 else
    7038   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    7039 $as_echo "no" >&6; }
    7040 fi
    7041 
    7042 
    7043 fi
    7044 if test -z "$ac_cv_prog_STRIP"; then
    7045   ac_ct_STRIP=$STRIP
    7046   # Extract the first word of "strip", so it can be a program name with args.
    7047 set dummy strip; ac_word=$2
    7048 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    7049 $as_echo_n "checking for $ac_word... " >&6; }
    7050 if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
    7051   $as_echo_n "(cached) " >&6
    7052 else
    7053   if test -n "$ac_ct_STRIP"; then
    7054   ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
    7055 else
    7056 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    7057 for as_dir in $PATH
    7058 do
    7059   IFS=$as_save_IFS
    7060   test -z "$as_dir" && as_dir=.
    7061     for ac_exec_ext in '' $ac_executable_extensions; do
    7062   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    7063     ac_cv_prog_ac_ct_STRIP="strip"
    7064     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    7065     break 2
    7066   fi
    7067 done
    7068   done
    7069 IFS=$as_save_IFS
    7070 
    7071 fi
    7072 fi
    7073 ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
    7074 if test -n "$ac_ct_STRIP"; then
    7075   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
    7076 $as_echo "$ac_ct_STRIP" >&6; }
    7077 else
    7078   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    7079 $as_echo "no" >&6; }
    7080 fi
    7081 
    7082   if test "x$ac_ct_STRIP" = x; then
    7083     STRIP=":"
    7084   else
    7085     case $cross_compiling:$ac_tool_warned in
    7086 yes:)
    7087 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    7088 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    7089 ac_tool_warned=yes ;;
    7090 esac
    7091     STRIP=$ac_ct_STRIP
    7092   fi
    7093 else
    7094   STRIP="$ac_cv_prog_STRIP"
    7095 fi
    7096 
    7097 test -z "$STRIP" && STRIP=:
    7098 
    7099 
    7100 
    7101 
    7102 
    7103 
    7104 if test -n "$ac_tool_prefix"; then
    7105   # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
    7106 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
    7107 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    7108 $as_echo_n "checking for $ac_word... " >&6; }
    7109 if ${ac_cv_prog_RANLIB+:} false; then :
    7110   $as_echo_n "(cached) " >&6
    7111 else
    7112   if test -n "$RANLIB"; then
    7113   ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
    7114 else
    7115 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    7116 for as_dir in $PATH
    7117 do
    7118   IFS=$as_save_IFS
    7119   test -z "$as_dir" && as_dir=.
    7120     for ac_exec_ext in '' $ac_executable_extensions; do
    7121   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    7122     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
    7123     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    7124     break 2
    7125   fi
    7126 done
    7127   done
    7128 IFS=$as_save_IFS
    7129 
    7130 fi
    7131 fi
    7132 RANLIB=$ac_cv_prog_RANLIB
    7133 if test -n "$RANLIB"; then
    7134   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
    7135 $as_echo "$RANLIB" >&6; }
    7136 else
    7137   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    7138 $as_echo "no" >&6; }
    7139 fi
    7140 
    7141 
    7142 fi
    7143 if test -z "$ac_cv_prog_RANLIB"; then
    7144   ac_ct_RANLIB=$RANLIB
    7145   # Extract the first word of "ranlib", so it can be a program name with args.
    7146 set dummy ranlib; ac_word=$2
    7147 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    7148 $as_echo_n "checking for $ac_word... " >&6; }
    7149 if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
    7150   $as_echo_n "(cached) " >&6
    7151 else
    7152   if test -n "$ac_ct_RANLIB"; then
    7153   ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
    7154 else
    7155 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    7156 for as_dir in $PATH
    7157 do
    7158   IFS=$as_save_IFS
    7159   test -z "$as_dir" && as_dir=.
    7160     for ac_exec_ext in '' $ac_executable_extensions; do
    7161   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    7162     ac_cv_prog_ac_ct_RANLIB="ranlib"
    7163     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    7164     break 2
    7165   fi
    7166 done
    7167   done
    7168 IFS=$as_save_IFS
    7169 
    7170 fi
    7171 fi
    7172 ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
    7173 if test -n "$ac_ct_RANLIB"; then
    7174   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
    7175 $as_echo "$ac_ct_RANLIB" >&6; }
    7176 else
    7177   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    7178 $as_echo "no" >&6; }
    7179 fi
    7180 
    7181   if test "x$ac_ct_RANLIB" = x; then
    7182     RANLIB=":"
    7183   else
    7184     case $cross_compiling:$ac_tool_warned in
    7185 yes:)
    7186 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    7187 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    7188 ac_tool_warned=yes ;;
    7189 esac
    7190     RANLIB=$ac_ct_RANLIB
    7191   fi
    7192 else
    7193   RANLIB="$ac_cv_prog_RANLIB"
    7194 fi
    7195 
    7196 test -z "$RANLIB" && RANLIB=:
    7197 
    7198 
    7199 
    7200 
    7201 
    7202 
    7203 # Determine commands to create old-style static archives.
    7204 old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
    7205 old_postinstall_cmds='chmod 644 $oldlib'
    7206 old_postuninstall_cmds=
    7207 
    7208 if test -n "$RANLIB"; then
    7209   case $host_os in
    7210   bitrig* | openbsd*)
    7211     old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
    7212     ;;
    7213   *)
    7214     old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
    7215     ;;
    7216   esac
    7217   old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
    7218 fi
    7219 
    7220 case $host_os in
    7221   darwin*)
    7222     lock_old_archive_extraction=yes ;;
    7223   *)
    7224     lock_old_archive_extraction=no ;;
    7225 esac
    7226 
    7227 
    7228 
    7229 
    7230 
    7231 
    7232 
    7233 
    7234 
    7235 
    7236 
    7237 
    7238 
    7239 
    7240 
    7241 
    7242 
    7243 
    7244 
    7245 
    7246 
    7247 
    7248 
    7249 
    7250 
    7251 
    7252 
    7253 
    7254 
    7255 
    7256 
    7257 
    7258 
    7259 
    7260 
    7261 
    7262 
    7263 
    7264 
    7265 # If no C compiler was specified, use CC.
    7266 LTCC=${LTCC-"$CC"}
    7267 
    7268 # If no C compiler flags were specified, use CFLAGS.
    7269 LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
    7270 
    7271 # Allow CC to be a program name with arguments.
    7272 compiler=$CC
    7273 
    7274 
    7275 # Check for command to grab the raw symbol name followed by C symbol from nm.
    7276 { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
    7277 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
    7278 if ${lt_cv_sys_global_symbol_pipe+:} false; then :
    7279   $as_echo_n "(cached) " >&6
    7280 else
    7281 
    7282 # These are sane defaults that work on at least a few old systems.
    7283 # [They come from Ultrix.  What could be older than Ultrix?!! ;)]
    7284 
    7285 # Character class describing NM global symbol codes.
    7286 symcode='[BCDEGRST]'
    7287 
    7288 # Regexp to match symbols that can be accessed directly from C.
    7289 sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
    7290 
    7291 # Define system-specific variables.
    7292 case $host_os in
    7293 aix*)
    7294   symcode='[BCDT]'
    7295   ;;
    7296 cygwin* | mingw* | pw32* | cegcc*)
    7297   symcode='[ABCDGISTW]'
    7298   ;;
    7299 hpux*)
    7300   if test ia64 = "$host_cpu"; then
    7301     symcode='[ABCDEGRST]'
    7302   fi
    7303   ;;
    7304 irix* | nonstopux*)
    7305   symcode='[BCDEGRST]'
    7306   ;;
    7307 osf*)
    7308   symcode='[BCDEGQRST]'
    7309   ;;
    7310 solaris*)
    7311   symcode='[BDRT]'
    7312   ;;
    7313 sco3.2v5*)
    7314   symcode='[DT]'
    7315   ;;
    7316 sysv4.2uw2*)
    7317   symcode='[DT]'
    7318   ;;
    7319 sysv5* | sco5v6* | unixware* | OpenUNIX*)
    7320   symcode='[ABDT]'
    7321   ;;
    7322 sysv4)
    7323   symcode='[DFNSTU]'
    7324   ;;
    7325 esac
    7326 
    7327 # If we're using GNU nm, then use its standard symbol codes.
    7328 case `$NM -V 2>&1` in
    7329 *GNU* | *'with BFD'*)
    7330   symcode='[ABCDGIRSTW]' ;;
    7331 esac
    7332 
    7333 if test "$lt_cv_nm_interface" = "MS dumpbin"; then
    7334   # Gets list of data symbols to import.
    7335   lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
    7336   # Adjust the below global symbol transforms to fixup imported variables.
    7337   lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
    7338   lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
    7339   lt_c_name_lib_hook="\
    7340   -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
    7341   -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
    7342 else
    7343   # Disable hooks by default.
    7344   lt_cv_sys_global_symbol_to_import=
    7345   lt_cdecl_hook=
    7346   lt_c_name_hook=
    7347   lt_c_name_lib_hook=
    7348 fi
    7349 
    7350 # Transform an extracted symbol line into a proper C declaration.
    7351 # Some systems (esp. on ia64) link data and code symbols differently,
    7352 # so use this general approach.
    7353 lt_cv_sys_global_symbol_to_cdecl="sed -n"\
    7354 $lt_cdecl_hook\
    7355 " -e 's/^T .* \(.*\)$/extern int \1();/p'"\
    7356 " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
    7357 
    7358 # Transform an extracted symbol line into symbol name and symbol address
    7359 lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
    7360 $lt_c_name_hook\
    7361 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
    7362 " -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
    7363 
    7364 # Transform an extracted symbol line into symbol name with lib prefix and
    7365 # symbol address.
    7366 lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
    7367 $lt_c_name_lib_hook\
    7368 " -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
    7369 " -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
    7370 " -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
    7371 
    7372 # Handle CRLF in mingw tool chain
    7373 opt_cr=
    7374 case $build_os in
    7375 mingw*)
    7376   opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
    7377   ;;
    7378 esac
    7379 
    7380 # Try without a prefix underscore, then with it.
    7381 for ac_symprfx in "" "_"; do
    7382 
    7383   # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
    7384   symxfrm="\\1 $ac_symprfx\\2 \\2"
    7385 
    7386   # Write the raw and C identifiers.
    7387   if test "$lt_cv_nm_interface" = "MS dumpbin"; then
    7388     # Fake it for dumpbin and say T for any non-static function,
    7389     # D for any global variable and I for any imported variable.
    7390     # Also find C++ and __fastcall symbols from MSVC++,
    7391     # which start with @ or ?.
    7392     lt_cv_sys_global_symbol_pipe="$AWK '"\
    7393 "     {last_section=section; section=\$ 3};"\
    7394 "     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
    7395 "     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
    7396 "     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
    7397 "     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
    7398 "     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
    7399 "     \$ 0!~/External *\|/{next};"\
    7400 "     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
    7401 "     {if(hide[section]) next};"\
    7402 "     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
    7403 "     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
    7404 "     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
    7405 "     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
    7406 "     ' prfx=^$ac_symprfx"
    7407   else
    7408     lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[      ]\($symcode$symcode*\)[         ][      ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
    7409   fi
    7410   lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
    7411 
    7412   # Check to see that the pipe works correctly.
    7413   pipe_works=no
    7414 
    7415   rm -f conftest*
    7416   cat > conftest.$ac_ext <<_LT_EOF
    7417 #ifdef __cplusplus
    7418 extern "C" {
    7419 #endif
    7420 char nm_test_var;
    7421 void nm_test_func(void);
    7422 void nm_test_func(void){}
    7423 #ifdef __cplusplus
    7424 }
    7425 #endif
    7426 int main(){nm_test_var='a';nm_test_func();return(0);}
    7427 _LT_EOF
    7428 
    7429   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    7430   (eval $ac_compile) 2>&5
    7431   ac_status=$?
    7432   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7433   test $ac_status = 0; }; then
    7434     # Now try to grab the symbols.
    7435     nlist=conftest.nm
    7436     if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
    7437   (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
    7438   ac_status=$?
    7439   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7440   test $ac_status = 0; } && test -s "$nlist"; then
    7441       # Try sorting and uniquifying the output.
    7442       if sort "$nlist" | uniq > "$nlist"T; then
    7443         mv -f "$nlist"T "$nlist"
    7444       else
    7445         rm -f "$nlist"T
    7446       fi
    7447 
    7448       # Make sure that we snagged all the symbols we need.
    7449       if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
    7450         if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
    7451           cat <<_LT_EOF > conftest.$ac_ext
    7452 /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
    7453 #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
    7454 /* DATA imports from DLLs on WIN32 can't be const, because runtime
    7455    relocations are performed -- see ld's documentation on pseudo-relocs.  */
    7456 # define LT_DLSYM_CONST
    7457 #elif defined __osf__
    7458 /* This system does not cope well with relocations in const data.  */
    7459 # define LT_DLSYM_CONST
    7460 #else
    7461 # define LT_DLSYM_CONST const
    7462 #endif
    7463 
    7464 #ifdef __cplusplus
    7465 extern "C" {
    7466 #endif
    7467 
    7468 _LT_EOF
    7469           # Now generate the symbol file.
    7470           eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
    7471 
    7472           cat <<_LT_EOF >> conftest.$ac_ext
    7473 
    7474 /* The mapping between symbol names and symbols.  */
    7475 LT_DLSYM_CONST struct {
    7476   const char *name;
    7477   void       *address;
    7478 }
    7479 lt__PROGRAM__LTX_preloaded_symbols[] =
    7480 {
    7481   { "@PROGRAM@", (void *) 0 },
    7482 _LT_EOF
    7483           $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
    7484           cat <<\_LT_EOF >> conftest.$ac_ext
    7485   {0, (void *) 0}
    7486 };
    7487 
    7488 /* This works around a problem in FreeBSD linker */
    7489 #ifdef FREEBSD_WORKAROUND
    7490 static const void *lt_preloaded_setup() {
    7491   return lt__PROGRAM__LTX_preloaded_symbols;
    7492 }
    7493 #endif
    7494 
    7495 #ifdef __cplusplus
    7496 }
    7497 #endif
    7498 _LT_EOF
    7499           # Now try linking the two files.
    7500           mv conftest.$ac_objext conftstm.$ac_objext
    7501           lt_globsym_save_LIBS=$LIBS
    7502           lt_globsym_save_CFLAGS=$CFLAGS
    7503           LIBS=conftstm.$ac_objext
    7504           CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
    7505           if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
    7506   (eval $ac_link) 2>&5
    7507   ac_status=$?
    7508   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7509   test $ac_status = 0; } && test -s conftest$ac_exeext; then
    7510             pipe_works=yes
    7511           fi
    7512           LIBS=$lt_globsym_save_LIBS
    7513           CFLAGS=$lt_globsym_save_CFLAGS
    7514         else
    7515           echo "cannot find nm_test_func in $nlist" >&5
    7516         fi
    7517       else
    7518         echo "cannot find nm_test_var in $nlist" >&5
    7519       fi
    7520     else
    7521       echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
    7522     fi
    7523   else
    7524     echo "$progname: failed program was:" >&5
    7525     cat conftest.$ac_ext >&5
    7526   fi
    7527   rm -rf conftest* conftst*
    7528 
    7529   # Do not use the global_symbol_pipe unless it works.
    7530   if test yes = "$pipe_works"; then
    7531     break
    7532   else
    7533     lt_cv_sys_global_symbol_pipe=
    7534   fi
    7535 done
    7536 
    7537 fi
    7538 
    7539 if test -z "$lt_cv_sys_global_symbol_pipe"; then
    7540   lt_cv_sys_global_symbol_to_cdecl=
    7541 fi
    7542 if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
    7543   { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
    7544 $as_echo "failed" >&6; }
    7545 else
    7546   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
    7547 $as_echo "ok" >&6; }
    7548 fi
    7549 
    7550 # Response file support.
    7551 if test "$lt_cv_nm_interface" = "MS dumpbin"; then
    7552   nm_file_list_spec='@'
    7553 elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
    7554   nm_file_list_spec='@'
    7555 fi
    7556 
    7557 
    7558 
    7559 
    7560 
    7561 
    7562 
    7563 
    7564 
    7565 
    7566 
    7567 
    7568 
    7569 
    7570 
    7571 
    7572 
    7573 
    7574 
    7575 
    7576 
    7577 
    7578 
    7579 
    7580 
    7581 
    7582 
    7583 
    7584 
    7585 
    7586 
    7587 
    7588 
    7589 
    7590 
    7591 
    7592 
    7593 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
    7594 $as_echo_n "checking for sysroot... " >&6; }
    7595 
    7596 # Check whether --with-sysroot was given.
    7597 if test "${with_sysroot+set}" = set; then :
    7598   withval=$with_sysroot;
    7599 else
    7600   with_sysroot=no
    7601 fi
    7602 
    7603 
    7604 lt_sysroot=
    7605 case $with_sysroot in #(
    7606  yes)
    7607    if test yes = "$GCC"; then
    7608      lt_sysroot=`$CC --print-sysroot 2>/dev/null`
    7609    fi
    7610    ;; #(
    7611  /*)
    7612    lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
    7613    ;; #(
    7614  no|'')
    7615    ;; #(
    7616  *)
    7617    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
    7618 $as_echo "$with_sysroot" >&6; }
    7619    as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
    7620    ;;
    7621 esac
    7622 
    7623  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
    7624 $as_echo "${lt_sysroot:-no}" >&6; }
    7625 
    7626 
    7627 
    7628 
    7629 
    7630 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
    7631 $as_echo_n "checking for a working dd... " >&6; }
    7632 if ${ac_cv_path_lt_DD+:} false; then :
    7633   $as_echo_n "(cached) " >&6
    7634 else
    7635   printf 0123456789abcdef0123456789abcdef >conftest.i
    7636 cat conftest.i conftest.i >conftest2.i
    7637 : ${lt_DD:=$DD}
    7638 if test -z "$lt_DD"; then
    7639   ac_path_lt_DD_found=false
    7640   # Loop through the user's path and test for each of PROGNAME-LIST
    7641   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    7642 for as_dir in $PATH
    7643 do
    7644   IFS=$as_save_IFS
    7645   test -z "$as_dir" && as_dir=.
    7646     for ac_prog in dd; do
    7647     for ac_exec_ext in '' $ac_executable_extensions; do
    7648       ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext"
    7649       as_fn_executable_p "$ac_path_lt_DD" || continue
    7650 if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
    7651   cmp -s conftest.i conftest.out \
    7652   && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
    7653 fi
    7654       $ac_path_lt_DD_found && break 3
    7655     done
    7656   done
    7657   done
    7658 IFS=$as_save_IFS
    7659   if test -z "$ac_cv_path_lt_DD"; then
    7660     :
    7661   fi
    7662 else
    7663   ac_cv_path_lt_DD=$lt_DD
    7664 fi
    7665 
    7666 rm -f conftest.i conftest2.i conftest.out
    7667 fi
    7668 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
    7669 $as_echo "$ac_cv_path_lt_DD" >&6; }
    7670 
    7671 
    7672 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
    7673 $as_echo_n "checking how to truncate binary pipes... " >&6; }
    7674 if ${lt_cv_truncate_bin+:} false; then :
    7675   $as_echo_n "(cached) " >&6
    7676 else
    7677   printf 0123456789abcdef0123456789abcdef >conftest.i
    7678 cat conftest.i conftest.i >conftest2.i
    7679 lt_cv_truncate_bin=
    7680 if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
    7681   cmp -s conftest.i conftest.out \
    7682   && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
    7683 fi
    7684 rm -f conftest.i conftest2.i conftest.out
    7685 test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
    7686 fi
    7687 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
    7688 $as_echo "$lt_cv_truncate_bin" >&6; }
    7689 
    7690 
    7691 
    7692 
    7693 
    7694 
    7695 
    7696 # Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
    7697 func_cc_basename ()
    7698 {
    7699     for cc_temp in $*""; do
    7700       case $cc_temp in
    7701         compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
    7702         distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
    7703         \-*) ;;
    7704         *) break;;
    7705       esac
    7706     done
    7707     func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
    7708 }
    7709 
    7710 # Check whether --enable-libtool-lock was given.
    7711 if test "${enable_libtool_lock+set}" = set; then :
    7712   enableval=$enable_libtool_lock;
    7713 fi
    7714 
    7715 test no = "$enable_libtool_lock" || enable_libtool_lock=yes
    7716 
    7717 # Some flags need to be propagated to the compiler or linker for good
    7718 # libtool support.
    7719 case $host in
    7720 ia64-*-hpux*)
    7721   # Find out what ABI is being produced by ac_compile, and set mode
    7722   # options accordingly.
    7723   echo 'int i;' > conftest.$ac_ext
    7724   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    7725   (eval $ac_compile) 2>&5
    7726   ac_status=$?
    7727   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7728   test $ac_status = 0; }; then
    7729     case `/usr/bin/file conftest.$ac_objext` in
    7730       *ELF-32*)
    7731         HPUX_IA64_MODE=32
    7732         ;;
    7733       *ELF-64*)
    7734         HPUX_IA64_MODE=64
    7735         ;;
    7736     esac
    7737   fi
    7738   rm -rf conftest*
    7739   ;;
    7740 *-*-irix6*)
    7741   # Find out what ABI is being produced by ac_compile, and set linker
    7742   # options accordingly.
    7743   echo '#line '$LINENO' "configure"' > conftest.$ac_ext
    7744   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    7745   (eval $ac_compile) 2>&5
    7746   ac_status=$?
    7747   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7748   test $ac_status = 0; }; then
    7749     if test yes = "$lt_cv_prog_gnu_ld"; then
    7750       case `/usr/bin/file conftest.$ac_objext` in
    7751         *32-bit*)
    7752           LD="${LD-ld} -melf32bsmip"
    7753           ;;
    7754         *N32*)
    7755           LD="${LD-ld} -melf32bmipn32"
    7756           ;;
    7757         *64-bit*)
    7758           LD="${LD-ld} -melf64bmip"
    7759         ;;
    7760       esac
    7761     else
    7762       case `/usr/bin/file conftest.$ac_objext` in
    7763         *32-bit*)
    7764           LD="${LD-ld} -32"
    7765           ;;
    7766         *N32*)
    7767           LD="${LD-ld} -n32"
    7768           ;;
    7769         *64-bit*)
    7770           LD="${LD-ld} -64"
    7771           ;;
    7772       esac
    7773     fi
    7774   fi
    7775   rm -rf conftest*
    7776   ;;
    7777 
    7778 mips64*-*linux*)
    7779   # Find out what ABI is being produced by ac_compile, and set linker
    7780   # options accordingly.
    7781   echo '#line '$LINENO' "configure"' > conftest.$ac_ext
    7782   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    7783   (eval $ac_compile) 2>&5
    7784   ac_status=$?
    7785   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7786   test $ac_status = 0; }; then
    7787     emul=elf
    7788     case `/usr/bin/file conftest.$ac_objext` in
    7789       *32-bit*)
    7790         emul="${emul}32"
    7791         ;;
    7792       *64-bit*)
    7793         emul="${emul}64"
    7794         ;;
    7795     esac
    7796     case `/usr/bin/file conftest.$ac_objext` in
    7797       *MSB*)
    7798         emul="${emul}btsmip"
    7799         ;;
    7800       *LSB*)
    7801         emul="${emul}ltsmip"
    7802         ;;
    7803     esac
    7804     case `/usr/bin/file conftest.$ac_objext` in
    7805       *N32*)
    7806         emul="${emul}n32"
    7807         ;;
    7808     esac
    7809     LD="${LD-ld} -m $emul"
    7810   fi
    7811   rm -rf conftest*
    7812   ;;
    7813 
    7814 x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
    7815 s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
    7816   # Find out what ABI is being produced by ac_compile, and set linker
    7817   # options accordingly.  Note that the listed cases only cover the
    7818   # situations where additional linker options are needed (such as when
    7819   # doing 32-bit compilation for a host where ld defaults to 64-bit, or
    7820   # vice versa); the common cases where no linker options are needed do
    7821   # not appear in the list.
    7822   echo 'int i;' > conftest.$ac_ext
    7823   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    7824   (eval $ac_compile) 2>&5
    7825   ac_status=$?
    7826   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7827   test $ac_status = 0; }; then
    7828     case `/usr/bin/file conftest.o` in
    7829       *32-bit*)
    7830         case $host in
    7831           x86_64-*kfreebsd*-gnu)
    7832             LD="${LD-ld} -m elf_i386_fbsd"
    7833             ;;
    7834           x86_64-*linux*)
    7835             case `/usr/bin/file conftest.o` in
    7836               *x86-64*)
    7837                 LD="${LD-ld} -m elf32_x86_64"
    7838                 ;;
    7839               *)
    7840                 LD="${LD-ld} -m elf_i386"
    7841                 ;;
    7842             esac
    7843             ;;
    7844           powerpc64le-*linux*)
    7845             LD="${LD-ld} -m elf32lppclinux"
    7846             ;;
    7847           powerpc64-*linux*)
    7848             LD="${LD-ld} -m elf32ppclinux"
    7849             ;;
    7850           s390x-*linux*)
    7851             LD="${LD-ld} -m elf_s390"
    7852             ;;
    7853           sparc64-*linux*)
    7854             LD="${LD-ld} -m elf32_sparc"
    7855             ;;
    7856         esac
    7857         ;;
    7858       *64-bit*)
    7859         case $host in
    7860           x86_64-*kfreebsd*-gnu)
    7861             LD="${LD-ld} -m elf_x86_64_fbsd"
    7862             ;;
    7863           x86_64-*linux*)
    7864             LD="${LD-ld} -m elf_x86_64"
    7865             ;;
    7866           powerpcle-*linux*)
    7867             LD="${LD-ld} -m elf64lppc"
    7868             ;;
    7869           powerpc-*linux*)
    7870             LD="${LD-ld} -m elf64ppc"
    7871             ;;
    7872           s390*-*linux*|s390*-*tpf*)
    7873             LD="${LD-ld} -m elf64_s390"
    7874             ;;
    7875           sparc*-*linux*)
    7876             LD="${LD-ld} -m elf64_sparc"
    7877             ;;
    7878         esac
    7879         ;;
    7880     esac
    7881   fi
    7882   rm -rf conftest*
    7883   ;;
    7884 
    7885 *-*-sco3.2v5*)
    7886   # On SCO OpenServer 5, we need -belf to get full-featured binaries.
    7887   SAVE_CFLAGS=$CFLAGS
    7888   CFLAGS="$CFLAGS -belf"
    7889   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
    7890 $as_echo_n "checking whether the C compiler needs -belf... " >&6; }
    7891 if ${lt_cv_cc_needs_belf+:} false; then :
    7892   $as_echo_n "(cached) " >&6
    7893 else
    7894   ac_ext=c
    7895 ac_cpp='$CPP $CPPFLAGS'
    7896 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    7897 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    7898 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    7899 
    7900      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    7901 /* end confdefs.h.  */
    7902 
    7903 int
    7904 main ()
    7905 {
    7906 
    7907   ;
    7908   return 0;
    7909 }
    7910 _ACEOF
    7911 if ac_fn_c_try_link "$LINENO"; then :
    7912   lt_cv_cc_needs_belf=yes
    7913 else
    7914   lt_cv_cc_needs_belf=no
    7915 fi
    7916 rm -f core conftest.err conftest.$ac_objext \
    7917     conftest$ac_exeext conftest.$ac_ext
    7918      ac_ext=c
    7919 ac_cpp='$CPP $CPPFLAGS'
    7920 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    7921 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    7922 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    7923 
    7924 fi
    7925 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
    7926 $as_echo "$lt_cv_cc_needs_belf" >&6; }
    7927   if test yes != "$lt_cv_cc_needs_belf"; then
    7928     # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
    7929     CFLAGS=$SAVE_CFLAGS
    7930   fi
    7931   ;;
    7932 *-*solaris*)
    7933   # Find out what ABI is being produced by ac_compile, and set linker
    7934   # options accordingly.
    7935   echo 'int i;' > conftest.$ac_ext
    7936   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    7937   (eval $ac_compile) 2>&5
    7938   ac_status=$?
    7939   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    7940   test $ac_status = 0; }; then
    7941     case `/usr/bin/file conftest.o` in
    7942     *64-bit*)
    7943       case $lt_cv_prog_gnu_ld in
    7944       yes*)
    7945         case $host in
    7946         i?86-*-solaris*|x86_64-*-solaris*)
    7947           LD="${LD-ld} -m elf_x86_64"
    7948           ;;
    7949         sparc*-*-solaris*)
    7950           LD="${LD-ld} -m elf64_sparc"
    7951           ;;
    7952         esac
    7953         # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
    7954         if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
    7955           LD=${LD-ld}_sol2
    7956         fi
    7957         ;;
    7958       *)
    7959         if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
    7960           LD="${LD-ld} -64"
    7961         fi
    7962         ;;
    7963       esac
    7964       ;;
    7965     esac
    7966   fi
    7967   rm -rf conftest*
    7968   ;;
    7969 esac
    7970 
    7971 need_locks=$enable_libtool_lock
    7972 
    7973 if test -n "$ac_tool_prefix"; then
    7974   # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
    7975 set dummy ${ac_tool_prefix}mt; ac_word=$2
    7976 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    7977 $as_echo_n "checking for $ac_word... " >&6; }
    7978 if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
    7979   $as_echo_n "(cached) " >&6
    7980 else
    7981   if test -n "$MANIFEST_TOOL"; then
    7982   ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
    7983 else
    7984 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    7985 for as_dir in $PATH
    7986 do
    7987   IFS=$as_save_IFS
    7988   test -z "$as_dir" && as_dir=.
    7989     for ac_exec_ext in '' $ac_executable_extensions; do
    7990   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    7991     ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
    7992     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    7993     break 2
    7994   fi
    7995 done
    7996   done
    7997 IFS=$as_save_IFS
    7998 
    7999 fi
    8000 fi
    8001 MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
    8002 if test -n "$MANIFEST_TOOL"; then
    8003   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
    8004 $as_echo "$MANIFEST_TOOL" >&6; }
    8005 else
    8006   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8007 $as_echo "no" >&6; }
    8008 fi
    8009 
    8010 
    8011 fi
    8012 if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
    8013   ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
    8014   # Extract the first word of "mt", so it can be a program name with args.
    8015 set dummy mt; ac_word=$2
    8016 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8017 $as_echo_n "checking for $ac_word... " >&6; }
    8018 if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
    8019   $as_echo_n "(cached) " >&6
    8020 else
    8021   if test -n "$ac_ct_MANIFEST_TOOL"; then
    8022   ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
    8023 else
    8024 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8025 for as_dir in $PATH
    8026 do
    8027   IFS=$as_save_IFS
    8028   test -z "$as_dir" && as_dir=.
    8029     for ac_exec_ext in '' $ac_executable_extensions; do
    8030   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8031     ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
    8032     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8033     break 2
    8034   fi
    8035 done
    8036   done
    8037 IFS=$as_save_IFS
    8038 
    8039 fi
    8040 fi
    8041 ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
    8042 if test -n "$ac_ct_MANIFEST_TOOL"; then
    8043   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
    8044 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
    8045 else
    8046   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8047 $as_echo "no" >&6; }
    8048 fi
    8049 
    8050   if test "x$ac_ct_MANIFEST_TOOL" = x; then
    8051     MANIFEST_TOOL=":"
    8052   else
    8053     case $cross_compiling:$ac_tool_warned in
    8054 yes:)
    8055 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    8056 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    8057 ac_tool_warned=yes ;;
    8058 esac
    8059     MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
    8060   fi
    8061 else
    8062   MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
    8063 fi
    8064 
    8065 test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
    8066 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
    8067 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
    8068 if ${lt_cv_path_mainfest_tool+:} false; then :
    8069   $as_echo_n "(cached) " >&6
    8070 else
    8071   lt_cv_path_mainfest_tool=no
    8072   echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
    8073   $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
    8074   cat conftest.err >&5
    8075   if $GREP 'Manifest Tool' conftest.out > /dev/null; then
    8076     lt_cv_path_mainfest_tool=yes
    8077   fi
    8078   rm -f conftest*
    8079 fi
    8080 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
    8081 $as_echo "$lt_cv_path_mainfest_tool" >&6; }
    8082 if test yes != "$lt_cv_path_mainfest_tool"; then
    8083   MANIFEST_TOOL=:
    8084 fi
    8085 
    8086 
    8087 
    8088 
    8089 
    8090 
    8091   case $host_os in
    8092     rhapsody* | darwin*)
    8093     if test -n "$ac_tool_prefix"; then
    8094   # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
    8095 set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
    8096 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8097 $as_echo_n "checking for $ac_word... " >&6; }
    8098 if ${ac_cv_prog_DSYMUTIL+:} false; then :
    8099   $as_echo_n "(cached) " >&6
    8100 else
    8101   if test -n "$DSYMUTIL"; then
    8102   ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
    8103 else
    8104 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8105 for as_dir in $PATH
    8106 do
    8107   IFS=$as_save_IFS
    8108   test -z "$as_dir" && as_dir=.
    8109     for ac_exec_ext in '' $ac_executable_extensions; do
    8110   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8111     ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
    8112     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8113     break 2
    8114   fi
    8115 done
    8116   done
    8117 IFS=$as_save_IFS
    8118 
    8119 fi
    8120 fi
    8121 DSYMUTIL=$ac_cv_prog_DSYMUTIL
    8122 if test -n "$DSYMUTIL"; then
    8123   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
    8124 $as_echo "$DSYMUTIL" >&6; }
    8125 else
    8126   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8127 $as_echo "no" >&6; }
    8128 fi
    8129 
    8130 
    8131 fi
    8132 if test -z "$ac_cv_prog_DSYMUTIL"; then
    8133   ac_ct_DSYMUTIL=$DSYMUTIL
    8134   # Extract the first word of "dsymutil", so it can be a program name with args.
    8135 set dummy dsymutil; ac_word=$2
    8136 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8137 $as_echo_n "checking for $ac_word... " >&6; }
    8138 if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
    8139   $as_echo_n "(cached) " >&6
    8140 else
    8141   if test -n "$ac_ct_DSYMUTIL"; then
    8142   ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
    8143 else
    8144 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8145 for as_dir in $PATH
    8146 do
    8147   IFS=$as_save_IFS
    8148   test -z "$as_dir" && as_dir=.
    8149     for ac_exec_ext in '' $ac_executable_extensions; do
    8150   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8151     ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
    8152     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8153     break 2
    8154   fi
    8155 done
    8156   done
    8157 IFS=$as_save_IFS
    8158 
    8159 fi
    8160 fi
    8161 ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
    8162 if test -n "$ac_ct_DSYMUTIL"; then
    8163   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
    8164 $as_echo "$ac_ct_DSYMUTIL" >&6; }
    8165 else
    8166   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8167 $as_echo "no" >&6; }
    8168 fi
    8169 
    8170   if test "x$ac_ct_DSYMUTIL" = x; then
    8171     DSYMUTIL=":"
    8172   else
    8173     case $cross_compiling:$ac_tool_warned in
    8174 yes:)
    8175 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    8176 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    8177 ac_tool_warned=yes ;;
    8178 esac
    8179     DSYMUTIL=$ac_ct_DSYMUTIL
    8180   fi
    8181 else
    8182   DSYMUTIL="$ac_cv_prog_DSYMUTIL"
    8183 fi
    8184 
    8185     if test -n "$ac_tool_prefix"; then
    8186   # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
    8187 set dummy ${ac_tool_prefix}nmedit; ac_word=$2
    8188 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8189 $as_echo_n "checking for $ac_word... " >&6; }
    8190 if ${ac_cv_prog_NMEDIT+:} false; then :
    8191   $as_echo_n "(cached) " >&6
    8192 else
    8193   if test -n "$NMEDIT"; then
    8194   ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
    8195 else
    8196 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8197 for as_dir in $PATH
    8198 do
    8199   IFS=$as_save_IFS
    8200   test -z "$as_dir" && as_dir=.
    8201     for ac_exec_ext in '' $ac_executable_extensions; do
    8202   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8203     ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
    8204     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8205     break 2
    8206   fi
    8207 done
    8208   done
    8209 IFS=$as_save_IFS
    8210 
    8211 fi
    8212 fi
    8213 NMEDIT=$ac_cv_prog_NMEDIT
    8214 if test -n "$NMEDIT"; then
    8215   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
    8216 $as_echo "$NMEDIT" >&6; }
    8217 else
    8218   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8219 $as_echo "no" >&6; }
    8220 fi
    8221 
    8222 
    8223 fi
    8224 if test -z "$ac_cv_prog_NMEDIT"; then
    8225   ac_ct_NMEDIT=$NMEDIT
    8226   # Extract the first word of "nmedit", so it can be a program name with args.
    8227 set dummy nmedit; ac_word=$2
    8228 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8229 $as_echo_n "checking for $ac_word... " >&6; }
    8230 if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
    8231   $as_echo_n "(cached) " >&6
    8232 else
    8233   if test -n "$ac_ct_NMEDIT"; then
    8234   ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
    8235 else
    8236 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8237 for as_dir in $PATH
    8238 do
    8239   IFS=$as_save_IFS
    8240   test -z "$as_dir" && as_dir=.
    8241     for ac_exec_ext in '' $ac_executable_extensions; do
    8242   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8243     ac_cv_prog_ac_ct_NMEDIT="nmedit"
    8244     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8245     break 2
    8246   fi
    8247 done
    8248   done
    8249 IFS=$as_save_IFS
    8250 
    8251 fi
    8252 fi
    8253 ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
    8254 if test -n "$ac_ct_NMEDIT"; then
    8255   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
    8256 $as_echo "$ac_ct_NMEDIT" >&6; }
    8257 else
    8258   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8259 $as_echo "no" >&6; }
    8260 fi
    8261 
    8262   if test "x$ac_ct_NMEDIT" = x; then
    8263     NMEDIT=":"
    8264   else
    8265     case $cross_compiling:$ac_tool_warned in
    8266 yes:)
    8267 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    8268 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    8269 ac_tool_warned=yes ;;
    8270 esac
    8271     NMEDIT=$ac_ct_NMEDIT
    8272   fi
    8273 else
    8274   NMEDIT="$ac_cv_prog_NMEDIT"
    8275 fi
    8276 
    8277     if test -n "$ac_tool_prefix"; then
    8278   # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
    8279 set dummy ${ac_tool_prefix}lipo; ac_word=$2
    8280 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8281 $as_echo_n "checking for $ac_word... " >&6; }
    8282 if ${ac_cv_prog_LIPO+:} false; then :
    8283   $as_echo_n "(cached) " >&6
    8284 else
    8285   if test -n "$LIPO"; then
    8286   ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
    8287 else
    8288 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8289 for as_dir in $PATH
    8290 do
    8291   IFS=$as_save_IFS
    8292   test -z "$as_dir" && as_dir=.
    8293     for ac_exec_ext in '' $ac_executable_extensions; do
    8294   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8295     ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
    8296     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8297     break 2
    8298   fi
    8299 done
    8300   done
    8301 IFS=$as_save_IFS
    8302 
    8303 fi
    8304 fi
    8305 LIPO=$ac_cv_prog_LIPO
    8306 if test -n "$LIPO"; then
    8307   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
    8308 $as_echo "$LIPO" >&6; }
    8309 else
    8310   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8311 $as_echo "no" >&6; }
    8312 fi
    8313 
    8314 
    8315 fi
    8316 if test -z "$ac_cv_prog_LIPO"; then
    8317   ac_ct_LIPO=$LIPO
    8318   # Extract the first word of "lipo", so it can be a program name with args.
    8319 set dummy lipo; ac_word=$2
    8320 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8321 $as_echo_n "checking for $ac_word... " >&6; }
    8322 if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
    8323   $as_echo_n "(cached) " >&6
    8324 else
    8325   if test -n "$ac_ct_LIPO"; then
    8326   ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
    8327 else
    8328 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8329 for as_dir in $PATH
    8330 do
    8331   IFS=$as_save_IFS
    8332   test -z "$as_dir" && as_dir=.
    8333     for ac_exec_ext in '' $ac_executable_extensions; do
    8334   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8335     ac_cv_prog_ac_ct_LIPO="lipo"
    8336     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8337     break 2
    8338   fi
    8339 done
    8340   done
    8341 IFS=$as_save_IFS
    8342 
    8343 fi
    8344 fi
    8345 ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
    8346 if test -n "$ac_ct_LIPO"; then
    8347   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
    8348 $as_echo "$ac_ct_LIPO" >&6; }
    8349 else
    8350   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8351 $as_echo "no" >&6; }
    8352 fi
    8353 
    8354   if test "x$ac_ct_LIPO" = x; then
    8355     LIPO=":"
    8356   else
    8357     case $cross_compiling:$ac_tool_warned in
    8358 yes:)
    8359 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    8360 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    8361 ac_tool_warned=yes ;;
    8362 esac
    8363     LIPO=$ac_ct_LIPO
    8364   fi
    8365 else
    8366   LIPO="$ac_cv_prog_LIPO"
    8367 fi
    8368 
    8369     if test -n "$ac_tool_prefix"; then
    8370   # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
    8371 set dummy ${ac_tool_prefix}otool; ac_word=$2
    8372 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8373 $as_echo_n "checking for $ac_word... " >&6; }
    8374 if ${ac_cv_prog_OTOOL+:} false; then :
    8375   $as_echo_n "(cached) " >&6
    8376 else
    8377   if test -n "$OTOOL"; then
    8378   ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
    8379 else
    8380 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8381 for as_dir in $PATH
    8382 do
    8383   IFS=$as_save_IFS
    8384   test -z "$as_dir" && as_dir=.
    8385     for ac_exec_ext in '' $ac_executable_extensions; do
    8386   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8387     ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
    8388     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8389     break 2
    8390   fi
    8391 done
    8392   done
    8393 IFS=$as_save_IFS
    8394 
    8395 fi
    8396 fi
    8397 OTOOL=$ac_cv_prog_OTOOL
    8398 if test -n "$OTOOL"; then
    8399   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
    8400 $as_echo "$OTOOL" >&6; }
    8401 else
    8402   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8403 $as_echo "no" >&6; }
    8404 fi
    8405 
    8406 
    8407 fi
    8408 if test -z "$ac_cv_prog_OTOOL"; then
    8409   ac_ct_OTOOL=$OTOOL
    8410   # Extract the first word of "otool", so it can be a program name with args.
    8411 set dummy otool; ac_word=$2
    8412 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8413 $as_echo_n "checking for $ac_word... " >&6; }
    8414 if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
    8415   $as_echo_n "(cached) " >&6
    8416 else
    8417   if test -n "$ac_ct_OTOOL"; then
    8418   ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
    8419 else
    8420 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8421 for as_dir in $PATH
    8422 do
    8423   IFS=$as_save_IFS
    8424   test -z "$as_dir" && as_dir=.
    8425     for ac_exec_ext in '' $ac_executable_extensions; do
    8426   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8427     ac_cv_prog_ac_ct_OTOOL="otool"
    8428     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8429     break 2
    8430   fi
    8431 done
    8432   done
    8433 IFS=$as_save_IFS
    8434 
    8435 fi
    8436 fi
    8437 ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
    8438 if test -n "$ac_ct_OTOOL"; then
    8439   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
    8440 $as_echo "$ac_ct_OTOOL" >&6; }
    8441 else
    8442   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8443 $as_echo "no" >&6; }
    8444 fi
    8445 
    8446   if test "x$ac_ct_OTOOL" = x; then
    8447     OTOOL=":"
    8448   else
    8449     case $cross_compiling:$ac_tool_warned in
    8450 yes:)
    8451 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    8452 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    8453 ac_tool_warned=yes ;;
    8454 esac
    8455     OTOOL=$ac_ct_OTOOL
    8456   fi
    8457 else
    8458   OTOOL="$ac_cv_prog_OTOOL"
    8459 fi
    8460 
    8461     if test -n "$ac_tool_prefix"; then
    8462   # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
    8463 set dummy ${ac_tool_prefix}otool64; ac_word=$2
    8464 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8465 $as_echo_n "checking for $ac_word... " >&6; }
    8466 if ${ac_cv_prog_OTOOL64+:} false; then :
    8467   $as_echo_n "(cached) " >&6
    8468 else
    8469   if test -n "$OTOOL64"; then
    8470   ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
    8471 else
    8472 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8473 for as_dir in $PATH
    8474 do
    8475   IFS=$as_save_IFS
    8476   test -z "$as_dir" && as_dir=.
    8477     for ac_exec_ext in '' $ac_executable_extensions; do
    8478   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8479     ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
    8480     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8481     break 2
    8482   fi
    8483 done
    8484   done
    8485 IFS=$as_save_IFS
    8486 
    8487 fi
    8488 fi
    8489 OTOOL64=$ac_cv_prog_OTOOL64
    8490 if test -n "$OTOOL64"; then
    8491   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
    8492 $as_echo "$OTOOL64" >&6; }
    8493 else
    8494   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8495 $as_echo "no" >&6; }
    8496 fi
    8497 
    8498 
    8499 fi
    8500 if test -z "$ac_cv_prog_OTOOL64"; then
    8501   ac_ct_OTOOL64=$OTOOL64
    8502   # Extract the first word of "otool64", so it can be a program name with args.
    8503 set dummy otool64; ac_word=$2
    8504 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
    8505 $as_echo_n "checking for $ac_word... " >&6; }
    8506 if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
    8507   $as_echo_n "(cached) " >&6
    8508 else
    8509   if test -n "$ac_ct_OTOOL64"; then
    8510   ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
    8511 else
    8512 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    8513 for as_dir in $PATH
    8514 do
    8515   IFS=$as_save_IFS
    8516   test -z "$as_dir" && as_dir=.
    8517     for ac_exec_ext in '' $ac_executable_extensions; do
    8518   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
    8519     ac_cv_prog_ac_ct_OTOOL64="otool64"
    8520     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
    8521     break 2
    8522   fi
    8523 done
    8524   done
    8525 IFS=$as_save_IFS
    8526 
    8527 fi
    8528 fi
    8529 ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
    8530 if test -n "$ac_ct_OTOOL64"; then
    8531   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
    8532 $as_echo "$ac_ct_OTOOL64" >&6; }
    8533 else
    8534   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    8535 $as_echo "no" >&6; }
    8536 fi
    8537 
    8538   if test "x$ac_ct_OTOOL64" = x; then
    8539     OTOOL64=":"
    8540   else
    8541     case $cross_compiling:$ac_tool_warned in
    8542 yes:)
    8543 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
    8544 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
    8545 ac_tool_warned=yes ;;
    8546 esac
    8547     OTOOL64=$ac_ct_OTOOL64
    8548   fi
    8549 else
    8550   OTOOL64="$ac_cv_prog_OTOOL64"
    8551 fi
    8552 
    8553 
    8554 
    8555 
    8556 
    8557 
    8558 
    8559 
    8560 
    8561 
    8562 
    8563 
    8564 
    8565 
    8566 
    8567 
    8568 
    8569 
    8570 
    8571 
    8572 
    8573 
    8574 
    8575 
    8576 
    8577 
    8578 
    8579     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
    8580 $as_echo_n "checking for -single_module linker flag... " >&6; }
    8581 if ${lt_cv_apple_cc_single_mod+:} false; then :
    8582   $as_echo_n "(cached) " >&6
    8583 else
    8584   lt_cv_apple_cc_single_mod=no
    8585       if test -z "$LT_MULTI_MODULE"; then
    8586         # By default we will add the -single_module flag. You can override
    8587         # by either setting the environment variable LT_MULTI_MODULE
    8588         # non-empty at configure time, or by adding -multi_module to the
    8589         # link flags.
    8590         rm -rf libconftest.dylib*
    8591         echo "int foo(void){return 1;}" > conftest.c
    8592         echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
    8593 -dynamiclib -Wl,-single_module conftest.c" >&5
    8594         $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
    8595           -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
    8596         _lt_result=$?
    8597         # If there is a non-empty error log, and "single_module"
    8598         # appears in it, assume the flag caused a linker warning
    8599         if test -s conftest.err && $GREP single_module conftest.err; then
    8600           cat conftest.err >&5
    8601         # Otherwise, if the output was created with a 0 exit code from
    8602         # the compiler, it worked.
    8603         elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
    8604           lt_cv_apple_cc_single_mod=yes
    8605         else
    8606           cat conftest.err >&5
    8607         fi
    8608         rm -rf libconftest.dylib*
    8609         rm -f conftest.*
    8610       fi
    8611 fi
    8612 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
    8613 $as_echo "$lt_cv_apple_cc_single_mod" >&6; }
    8614 
    8615     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
    8616 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
    8617 if ${lt_cv_ld_exported_symbols_list+:} false; then :
    8618   $as_echo_n "(cached) " >&6
    8619 else
    8620   lt_cv_ld_exported_symbols_list=no
    8621       save_LDFLAGS=$LDFLAGS
    8622       echo "_main" > conftest.sym
    8623       LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
    8624       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    8625 /* end confdefs.h.  */
    8626 
    8627 int
    8628 main ()
    8629 {
    8630 
    8631   ;
    8632   return 0;
    8633 }
    8634 _ACEOF
    8635 if ac_fn_c_try_link "$LINENO"; then :
    8636   lt_cv_ld_exported_symbols_list=yes
    8637 else
    8638   lt_cv_ld_exported_symbols_list=no
    8639 fi
    8640 rm -f core conftest.err conftest.$ac_objext \
    8641     conftest$ac_exeext conftest.$ac_ext
    8642         LDFLAGS=$save_LDFLAGS
    8643 
    8644 fi
    8645 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
    8646 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
    8647 
    8648     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
    8649 $as_echo_n "checking for -force_load linker flag... " >&6; }
    8650 if ${lt_cv_ld_force_load+:} false; then :
    8651   $as_echo_n "(cached) " >&6
    8652 else
    8653   lt_cv_ld_force_load=no
    8654       cat > conftest.c << _LT_EOF
    8655 int forced_loaded() { return 2;}
    8656 _LT_EOF
    8657       echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
    8658       $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
    8659       echo "$AR cru libconftest.a conftest.o" >&5
    8660       $AR cru libconftest.a conftest.o 2>&5
    8661       echo "$RANLIB libconftest.a" >&5
    8662       $RANLIB libconftest.a 2>&5
    8663       cat > conftest.c << _LT_EOF
    8664 int main() { return 0;}
    8665 _LT_EOF
    8666       echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
    8667       $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
    8668       _lt_result=$?
    8669       if test -s conftest.err && $GREP force_load conftest.err; then
    8670         cat conftest.err >&5
    8671       elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
    8672         lt_cv_ld_force_load=yes
    8673       else
    8674         cat conftest.err >&5
    8675       fi
    8676         rm -f conftest.err libconftest.a conftest conftest.c
    8677         rm -rf conftest.dSYM
    8678 
    8679 fi
    8680 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
    8681 $as_echo "$lt_cv_ld_force_load" >&6; }
    8682     case $host_os in
    8683     rhapsody* | darwin1.[012])
    8684       _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
    8685     darwin1.*)
    8686       _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
    8687     darwin*) # darwin 5.x on
    8688       # if running on 10.5 or later, the deployment target defaults
    8689       # to the OS version, if on x86, and 10.4, the deployment
    8690       # target defaults to 10.4. Don't you love it?
    8691       case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
    8692         10.0,*86*-darwin8*|10.0,*-darwin[91]*)
    8693           _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
    8694         10.[012][,.]*)
    8695           _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
    8696         10.*)
    8697           _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
    8698       esac
    8699     ;;
    8700   esac
    8701     if test yes = "$lt_cv_apple_cc_single_mod"; then
    8702       _lt_dar_single_mod='$single_module'
    8703     fi
    8704     if test yes = "$lt_cv_ld_exported_symbols_list"; then
    8705       _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
    8706     else
    8707       _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
    8708     fi
    8709     if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
    8710       _lt_dsymutil='~$DSYMUTIL $lib || :'
    8711     else
    8712       _lt_dsymutil=
    8713     fi
    8714     ;;
    8715   esac
    8716 
    8717 # func_munge_path_list VARIABLE PATH
    8718 # -----------------------------------
    8719 # VARIABLE is name of variable containing _space_ separated list of
    8720 # directories to be munged by the contents of PATH, which is string
    8721 # having a format:
    8722 # "DIR[:DIR]:"
    8723 #       string "DIR[ DIR]" will be prepended to VARIABLE
    8724 # ":DIR[:DIR]"
    8725 #       string "DIR[ DIR]" will be appended to VARIABLE
    8726 # "DIRP[:DIRP]::[DIRA:]DIRA"
    8727 #       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
    8728 #       "DIRA[ DIRA]" will be appended to VARIABLE
    8729 # "DIR[:DIR]"
    8730 #       VARIABLE will be replaced by "DIR[ DIR]"
    8731 func_munge_path_list ()
    8732 {
    8733     case x$2 in
    8734     x)
    8735         ;;
    8736     *:)
    8737         eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
    8738         ;;
    8739     x:*)
    8740         eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
    8741         ;;
    8742     *::*)
    8743         eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
    8744         eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
    8745         ;;
    8746     *)
    8747         eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
    8748         ;;
    8749     esac
    8750 }
    8751 
    8752 ac_ext=c
    8753 ac_cpp='$CPP $CPPFLAGS'
    8754 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    8755 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    8756 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    8757 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
    8758 $as_echo_n "checking how to run the C preprocessor... " >&6; }
    8759 # On Suns, sometimes $CPP names a directory.
    8760 if test -n "$CPP" && test -d "$CPP"; then
    8761   CPP=
    8762 fi
    8763 if test -z "$CPP"; then
    8764   if ${ac_cv_prog_CPP+:} false; then :
    8765   $as_echo_n "(cached) " >&6
    8766 else
    8767       # Double quotes because CPP needs to be expanded
    8768     for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
    8769     do
    8770       ac_preproc_ok=false
    8771 for ac_c_preproc_warn_flag in '' yes
    8772 do
    8773   # Use a header file that comes with gcc, so configuring glibc
    8774   # with a fresh cross-compiler works.
    8775   # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    8776   # <limits.h> exists even on freestanding compilers.
    8777   # On the NeXT, cc -E runs the code through the compiler's parser,
    8778   # not just through cpp. "Syntax error" is here to catch this case.
    8779   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    8780 /* end confdefs.h.  */
    8781 #ifdef __STDC__
    8782 # include <limits.h>
    8783 #else
    8784 # include <assert.h>
    8785 #endif
    8786                      Syntax error
    8787 _ACEOF
    8788 if ac_fn_c_try_cpp "$LINENO"; then :
    8789 
    8790 else
    8791   # Broken: fails on valid input.
    8792 continue
    8793 fi
    8794 rm -f conftest.err conftest.i conftest.$ac_ext
    8795 
    8796   # OK, works on sane cases.  Now check whether nonexistent headers
    8797   # can be detected and how.
    8798   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    8799 /* end confdefs.h.  */
    8800 #include <ac_nonexistent.h>
    8801 _ACEOF
    8802 if ac_fn_c_try_cpp "$LINENO"; then :
    8803   # Broken: success on invalid input.
    8804 continue
    8805 else
    8806   # Passes both tests.
    8807 ac_preproc_ok=:
    8808 break
    8809 fi
    8810 rm -f conftest.err conftest.i conftest.$ac_ext
    8811 
    8812 done
    8813 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
    8814 rm -f conftest.i conftest.err conftest.$ac_ext
    8815 if $ac_preproc_ok; then :
    8816   break
    8817 fi
    8818 
    8819     done
    8820     ac_cv_prog_CPP=$CPP
    8821 
    8822 fi
    8823   CPP=$ac_cv_prog_CPP
    8824 else
    8825   ac_cv_prog_CPP=$CPP
    8826 fi
    8827 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
    8828 $as_echo "$CPP" >&6; }
    8829 ac_preproc_ok=false
    8830 for ac_c_preproc_warn_flag in '' yes
    8831 do
    8832   # Use a header file that comes with gcc, so configuring glibc
    8833   # with a fresh cross-compiler works.
    8834   # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    8835   # <limits.h> exists even on freestanding compilers.
    8836   # On the NeXT, cc -E runs the code through the compiler's parser,
    8837   # not just through cpp. "Syntax error" is here to catch this case.
    8838   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    8839 /* end confdefs.h.  */
    8840 #ifdef __STDC__
    8841 # include <limits.h>
    8842 #else
    8843 # include <assert.h>
    8844 #endif
    8845                      Syntax error
    8846 _ACEOF
    8847 if ac_fn_c_try_cpp "$LINENO"; then :
    8848 
    8849 else
    8850   # Broken: fails on valid input.
    8851 continue
    8852 fi
    8853 rm -f conftest.err conftest.i conftest.$ac_ext
    8854 
    8855   # OK, works on sane cases.  Now check whether nonexistent headers
    8856   # can be detected and how.
    8857   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    8858 /* end confdefs.h.  */
    8859 #include <ac_nonexistent.h>
    8860 _ACEOF
    8861 if ac_fn_c_try_cpp "$LINENO"; then :
    8862   # Broken: success on invalid input.
    8863 continue
    8864 else
    8865   # Passes both tests.
    8866 ac_preproc_ok=:
    8867 break
    8868 fi
    8869 rm -f conftest.err conftest.i conftest.$ac_ext
    8870 
    8871 done
    8872 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
    8873 rm -f conftest.i conftest.err conftest.$ac_ext
    8874 if $ac_preproc_ok; then :
    8875 
    8876 else
    8877   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
    8878 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
    8879 as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
    8880 See \`config.log' for more details" "$LINENO" 5; }
    8881 fi
    8882 
    8883 ac_ext=c
    8884 ac_cpp='$CPP $CPPFLAGS'
    8885 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    8886 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    8887 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    8888 
    8889 
    88905673{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
    88915674$as_echo_n "checking for ANSI C header files... " >&6; }
     
    90175800
    90185801
    9019 for ac_header in dlfcn.h
    9020 do :
    9021   ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
    9022 "
    9023 if test "x$ac_cv_header_dlfcn_h" = xyes; then :
    9024   cat >>confdefs.h <<_ACEOF
    9025 #define HAVE_DLFCN_H 1
    9026 _ACEOF
    9027 
    9028 fi
    9029 
    9030 done
    9031 
    9032 
    9033 
    9034 
    9035 func_stripname_cnf ()
    9036 {
    9037   case $2 in
    9038   .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;;
    9039   *)  func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;;
    9040   esac
    9041 } # func_stripname_cnf
    9042 
    9043 
    9044 
    9045 
    9046 
    9047 # Set options
    9048 
    9049 
    9050 
    9051         enable_dlopen=no
    9052 
    9053 
    9054   enable_win32_dll=no
    9055 
    9056 
    9057             # Check whether --enable-shared was given.
    9058 if test "${enable_shared+set}" = set; then :
    9059   enableval=$enable_shared; p=${PACKAGE-default}
    9060     case $enableval in
    9061     yes) enable_shared=yes ;;
    9062     no) enable_shared=no ;;
    9063     *)
    9064       enable_shared=no
    9065       # Look at the argument we got.  We use all the common list separators.
    9066       lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
    9067       for pkg in $enableval; do
    9068         IFS=$lt_save_ifs
    9069         if test "X$pkg" = "X$p"; then
    9070           enable_shared=yes
    9071         fi
    9072       done
    9073       IFS=$lt_save_ifs
    9074       ;;
    9075     esac
    9076 else
    9077   enable_shared=yes
    9078 fi
    9079 
    9080 
    9081 
    9082 
    9083 
    9084 
    9085 
    9086 
    9087 
    9088   # Check whether --enable-static was given.
    9089 if test "${enable_static+set}" = set; then :
    9090   enableval=$enable_static; p=${PACKAGE-default}
    9091     case $enableval in
    9092     yes) enable_static=yes ;;
    9093     no) enable_static=no ;;
    9094     *)
    9095      enable_static=no
    9096       # Look at the argument we got.  We use all the common list separators.
    9097       lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
    9098       for pkg in $enableval; do
    9099         IFS=$lt_save_ifs
    9100         if test "X$pkg" = "X$p"; then
    9101           enable_static=yes
    9102         fi
    9103       done
    9104       IFS=$lt_save_ifs
    9105       ;;
    9106     esac
    9107 else
    9108   enable_static=yes
    9109 fi
    9110 
    9111 
    9112 
    9113 
    9114 
    9115 
    9116 
    9117 
    9118 
    9119 
    9120 # Check whether --with-pic was given.
    9121 if test "${with_pic+set}" = set; then :
    9122   withval=$with_pic; lt_p=${PACKAGE-default}
    9123     case $withval in
    9124     yes|no) pic_mode=$withval ;;
    9125     *)
    9126       pic_mode=default
    9127       # Look at the argument we got.  We use all the common list separators.
    9128       lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
    9129       for lt_pkg in $withval; do
    9130         IFS=$lt_save_ifs
    9131         if test "X$lt_pkg" = "X$lt_p"; then
    9132           pic_mode=yes
    9133         fi
    9134       done
    9135       IFS=$lt_save_ifs
    9136       ;;
    9137     esac
    9138 else
    9139   pic_mode=default
    9140 fi
    9141 
    9142 
    9143 
    9144 
    9145 
    9146 
    9147 
    9148 
    9149   # Check whether --enable-fast-install was given.
    9150 if test "${enable_fast_install+set}" = set; then :
    9151   enableval=$enable_fast_install; p=${PACKAGE-default}
    9152     case $enableval in
    9153     yes) enable_fast_install=yes ;;
    9154     no) enable_fast_install=no ;;
    9155     *)
    9156       enable_fast_install=no
    9157       # Look at the argument we got.  We use all the common list separators.
    9158       lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
    9159       for pkg in $enableval; do
    9160         IFS=$lt_save_ifs
    9161         if test "X$pkg" = "X$p"; then
    9162           enable_fast_install=yes
    9163         fi
    9164       done
    9165       IFS=$lt_save_ifs
    9166       ;;
    9167     esac
    9168 else
    9169   enable_fast_install=yes
    9170 fi
    9171 
    9172 
    9173 
    9174 
    9175 
    9176 
    9177 
    9178 
    9179   shared_archive_member_spec=
    9180 case $host,$enable_shared in
    9181 power*-*-aix[5-9]*,yes)
    9182   { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
    9183 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; }
    9184 
    9185 # Check whether --with-aix-soname was given.
    9186 if test "${with_aix_soname+set}" = set; then :
    9187   withval=$with_aix_soname; case $withval in
    9188     aix|svr4|both)
    9189       ;;
    9190     *)
    9191       as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
    9192       ;;
    9193     esac
    9194     lt_cv_with_aix_soname=$with_aix_soname
    9195 else
    9196   if ${lt_cv_with_aix_soname+:} false; then :
    9197   $as_echo_n "(cached) " >&6
    9198 else
    9199   lt_cv_with_aix_soname=aix
    9200 fi
    9201 
    9202     with_aix_soname=$lt_cv_with_aix_soname
    9203 fi
    9204 
    9205   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
    9206 $as_echo "$with_aix_soname" >&6; }
    9207   if test aix != "$with_aix_soname"; then
    9208     # For the AIX way of multilib, we name the shared archive member
    9209     # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
    9210     # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
    9211     # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
    9212     # the AIX toolchain works better with OBJECT_MODE set (default 32).
    9213     if test 64 = "${OBJECT_MODE-32}"; then
    9214       shared_archive_member_spec=shr_64
    9215     else
    9216       shared_archive_member_spec=shr
    9217     fi
    9218   fi
    9219   ;;
    9220 *)
    9221   with_aix_soname=aix
    9222   ;;
    9223 esac
    9224 
    9225 
    9226 
    9227 
    9228 
    9229 
    9230 
    9231 
    9232 
    9233 
    9234 # This can be used to rebuild libtool when needed
    9235 LIBTOOL_DEPS=$ltmain
    9236 
    9237 # Always use our own libtool.
    9238 LIBTOOL='$(SHELL) $(top_builddir)/libtool'
    9239 
    9240 
    9241 
    9242 
    9243 
    9244 
    9245 
    9246 
    9247 
    9248 
    9249 
    9250 
    9251 
    9252 
    9253 
    9254 
    9255 
    9256 
    9257 
    9258 
    9259 
    9260 
    9261 
    9262 
    9263 
    9264 
    9265 
    9266 
    9267 
    9268 
    9269 test -z "$LN_S" && LN_S="ln -s"
    9270 
    9271 
    9272 
    9273 
    9274 
    9275 
    9276 
    9277 
    9278 
    9279 
    9280 
    9281 
    9282 
    9283 
    9284 if test -n "${ZSH_VERSION+set}"; then
    9285    setopt NO_GLOB_SUBST
    9286 fi
    9287 
    9288 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
    9289 $as_echo_n "checking for objdir... " >&6; }
    9290 if ${lt_cv_objdir+:} false; then :
    9291   $as_echo_n "(cached) " >&6
    9292 else
    9293   rm -f .libs 2>/dev/null
    9294 mkdir .libs 2>/dev/null
    9295 if test -d .libs; then
    9296   lt_cv_objdir=.libs
    9297 else
    9298   # MS-DOS does not allow filenames that begin with a dot.
    9299   lt_cv_objdir=_libs
    9300 fi
    9301 rmdir .libs 2>/dev/null
    9302 fi
    9303 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
    9304 $as_echo "$lt_cv_objdir" >&6; }
    9305 objdir=$lt_cv_objdir
    9306 
    9307 
    9308 
    9309 
     5802ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
     5803if test "x$ac_cv_type_size_t" = xyes; then :
     5804
     5805else
    93105806
    93115807cat >>confdefs.h <<_ACEOF
    9312 #define LT_OBJDIR "$lt_cv_objdir/"
    9313 _ACEOF
    9314 
    9315 
    9316 
    9317 
    9318 case $host_os in
    9319 aix3*)
    9320   # AIX sometimes has problems with the GCC collect2 program.  For some
    9321   # reason, if we set the COLLECT_NAMES environment variable, the problems
    9322   # vanish in a puff of smoke.
    9323   if test set != "${COLLECT_NAMES+set}"; then
    9324     COLLECT_NAMES=
    9325     export COLLECT_NAMES
    9326   fi
    9327   ;;
    9328 esac
    9329 
    9330 # Global variables:
    9331 ofile=libtool
    9332 can_build_shared=yes
    9333 
    9334 # All known linkers require a '.a' archive for static linking (except MSVC,
    9335 # which needs '.lib').
    9336 libext=a
    9337 
    9338 with_gnu_ld=$lt_cv_prog_gnu_ld
    9339 
    9340 old_CC=$CC
    9341 old_CFLAGS=$CFLAGS
    9342 
    9343 # Set sane defaults for various variables
    9344 test -z "$CC" && CC=cc
    9345 test -z "$LTCC" && LTCC=$CC
    9346 test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
    9347 test -z "$LD" && LD=ld
    9348 test -z "$ac_objext" && ac_objext=o
    9349 
    9350 func_cc_basename $compiler
    9351 cc_basename=$func_cc_basename_result
    9352 
    9353 
    9354 # Only perform the check for file, if the check method requires it
    9355 test -z "$MAGIC_CMD" && MAGIC_CMD=file
    9356 case $deplibs_check_method in
    9357 file_magic*)
    9358   if test "$file_magic_cmd" = '$MAGIC_CMD'; then
    9359     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
    9360 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
    9361 if ${lt_cv_path_MAGIC_CMD+:} false; then :
    9362   $as_echo_n "(cached) " >&6
    9363 else
    9364   case $MAGIC_CMD in
    9365 [\\/*] |  ?:[\\/]*)
    9366   lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
    9367   ;;
    9368 *)
    9369   lt_save_MAGIC_CMD=$MAGIC_CMD
    9370   lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
    9371   ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
    9372   for ac_dir in $ac_dummy; do
    9373     IFS=$lt_save_ifs
    9374     test -z "$ac_dir" && ac_dir=.
    9375     if test -f "$ac_dir/${ac_tool_prefix}file"; then
    9376       lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
    9377       if test -n "$file_magic_test_file"; then
    9378         case $deplibs_check_method in
    9379         "file_magic "*)
    9380           file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
    9381           MAGIC_CMD=$lt_cv_path_MAGIC_CMD
    9382           if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
    9383             $EGREP "$file_magic_regex" > /dev/null; then
    9384             :
    9385           else
    9386             cat <<_LT_EOF 1>&2
    9387 
    9388 *** Warning: the command libtool uses to detect shared libraries,
    9389 *** $file_magic_cmd, produces output that libtool cannot recognize.
    9390 *** The result is that libtool may fail to recognize shared libraries
    9391 *** as such.  This will affect the creation of libtool libraries that
    9392 *** depend on shared libraries, but programs linked with such libtool
    9393 *** libraries will work regardless of this problem.  Nevertheless, you
    9394 *** may want to report the problem to your system manager and/or to
    9395 *** bug-libtool@gnu.org
    9396 
    9397 _LT_EOF
    9398           fi ;;
    9399         esac
    9400       fi
    9401       break
    9402     fi
    9403   done
    9404   IFS=$lt_save_ifs
    9405   MAGIC_CMD=$lt_save_MAGIC_CMD
    9406   ;;
    9407 esac
    9408 fi
    9409 
    9410 MAGIC_CMD=$lt_cv_path_MAGIC_CMD
    9411 if test -n "$MAGIC_CMD"; then
    9412   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
    9413 $as_echo "$MAGIC_CMD" >&6; }
    9414 else
    9415   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    9416 $as_echo "no" >&6; }
    9417 fi
    9418 
    9419 
    9420 
    9421 
    9422 
    9423 if test -z "$lt_cv_path_MAGIC_CMD"; then
    9424   if test -n "$ac_tool_prefix"; then
    9425     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
    9426 $as_echo_n "checking for file... " >&6; }
    9427 if ${lt_cv_path_MAGIC_CMD+:} false; then :
    9428   $as_echo_n "(cached) " >&6
    9429 else
    9430   case $MAGIC_CMD in
    9431 [\\/*] |  ?:[\\/]*)
    9432   lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
    9433   ;;
    9434 *)
    9435   lt_save_MAGIC_CMD=$MAGIC_CMD
    9436   lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
    9437   ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
    9438   for ac_dir in $ac_dummy; do
    9439     IFS=$lt_save_ifs
    9440     test -z "$ac_dir" && ac_dir=.
    9441     if test -f "$ac_dir/file"; then
    9442       lt_cv_path_MAGIC_CMD=$ac_dir/"file"
    9443       if test -n "$file_magic_test_file"; then
    9444         case $deplibs_check_method in
    9445         "file_magic "*)
    9446           file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
    9447           MAGIC_CMD=$lt_cv_path_MAGIC_CMD
    9448           if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
    9449             $EGREP "$file_magic_regex" > /dev/null; then
    9450             :
    9451           else
    9452             cat <<_LT_EOF 1>&2
    9453 
    9454 *** Warning: the command libtool uses to detect shared libraries,
    9455 *** $file_magic_cmd, produces output that libtool cannot recognize.
    9456 *** The result is that libtool may fail to recognize shared libraries
    9457 *** as such.  This will affect the creation of libtool libraries that
    9458 *** depend on shared libraries, but programs linked with such libtool
    9459 *** libraries will work regardless of this problem.  Nevertheless, you
    9460 *** may want to report the problem to your system manager and/or to
    9461 *** bug-libtool@gnu.org
    9462 
    9463 _LT_EOF
    9464           fi ;;
    9465         esac
    9466       fi
    9467       break
    9468     fi
    9469   done
    9470   IFS=$lt_save_ifs
    9471   MAGIC_CMD=$lt_save_MAGIC_CMD
    9472   ;;
    9473 esac
    9474 fi
    9475 
    9476 MAGIC_CMD=$lt_cv_path_MAGIC_CMD
    9477 if test -n "$MAGIC_CMD"; then
    9478   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
    9479 $as_echo "$MAGIC_CMD" >&6; }
    9480 else
    9481   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    9482 $as_echo "no" >&6; }
    9483 fi
    9484 
    9485 
    9486   else
    9487     MAGIC_CMD=:
    9488   fi
    9489 fi
    9490 
    9491   fi
    9492   ;;
    9493 esac
    9494 
    9495 # Use C for the default configuration in the libtool script
    9496 
    9497 lt_save_CC=$CC
    9498 ac_ext=c
    9499 ac_cpp='$CPP $CPPFLAGS'
    9500 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    9501 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    9502 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    9503 
    9504 
    9505 # Source file extension for C test sources.
    9506 ac_ext=c
    9507 
    9508 # Object file extension for compiled C test sources.
    9509 objext=o
    9510 objext=$objext
    9511 
    9512 # Code to be used in simple compile tests
    9513 lt_simple_compile_test_code="int some_variable = 0;"
    9514 
    9515 # Code to be used in simple link tests
    9516 lt_simple_link_test_code='int main(){return(0);}'
    9517 
    9518 
    9519 
    9520 
    9521 
    9522 
    9523 
    9524 # If no C compiler was specified, use CC.
    9525 LTCC=${LTCC-"$CC"}
    9526 
    9527 # If no C compiler flags were specified, use CFLAGS.
    9528 LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
    9529 
    9530 # Allow CC to be a program name with arguments.
    9531 compiler=$CC
    9532 
    9533 # Save the default compiler, since it gets overwritten when the other
    9534 # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
    9535 compiler_DEFAULT=$CC
    9536 
    9537 # save warnings/boilerplate of simple test code
    9538 ac_outfile=conftest.$ac_objext
    9539 echo "$lt_simple_compile_test_code" >conftest.$ac_ext
    9540 eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
    9541 _lt_compiler_boilerplate=`cat conftest.err`
    9542 $RM conftest*
    9543 
    9544 ac_outfile=conftest.$ac_objext
    9545 echo "$lt_simple_link_test_code" >conftest.$ac_ext
    9546 eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
    9547 _lt_linker_boilerplate=`cat conftest.err`
    9548 $RM -r conftest*
    9549 
    9550 
    9551 ## CAVEAT EMPTOR:
    9552 ## There is no encapsulation within the following macros, do not change
    9553 ## the running order or otherwise move them around unless you know exactly
    9554 ## what you are doing...
    9555 if test -n "$compiler"; then
    9556 
    9557 lt_prog_compiler_no_builtin_flag=
    9558 
    9559 if test yes = "$GCC"; then
    9560   case $cc_basename in
    9561   nvcc*)
    9562     lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
    9563   *)
    9564     lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
    9565   esac
    9566 
    9567   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
    9568 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
    9569 if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
    9570   $as_echo_n "(cached) " >&6
    9571 else
    9572   lt_cv_prog_compiler_rtti_exceptions=no
    9573    ac_outfile=conftest.$ac_objext
    9574    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    9575    lt_compiler_flag="-fno-rtti -fno-exceptions"  ## exclude from sc_useless_quotes_in_assignment
    9576    # Insert the option either (1) after the last *FLAGS variable, or
    9577    # (2) before a word containing "conftest.", or (3) at the end.
    9578    # Note that $ac_compile itself does not contain backslashes and begins
    9579    # with a dollar sign (not a hyphen), so the echo should work correctly.
    9580    # The option is referenced via a variable to avoid confusing sed.
    9581    lt_compile=`echo "$ac_compile" | $SED \
    9582    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    9583    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    9584    -e 's:$: $lt_compiler_flag:'`
    9585    (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    9586    (eval "$lt_compile" 2>conftest.err)
    9587    ac_status=$?
    9588    cat conftest.err >&5
    9589    echo "$as_me:$LINENO: \$? = $ac_status" >&5
    9590    if (exit $ac_status) && test -s "$ac_outfile"; then
    9591      # The compiler can only warn and ignore the option if not recognized
    9592      # So say no if there are warnings other than the usual output.
    9593      $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
    9594      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
    9595      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
    9596        lt_cv_prog_compiler_rtti_exceptions=yes
    9597      fi
    9598    fi
    9599    $RM conftest*
    9600 
    9601 fi
    9602 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
    9603 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
    9604 
    9605 if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
    9606     lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
    9607 else
    9608     :
    9609 fi
    9610 
    9611 fi
    9612 
    9613 
    9614 
    9615 
    9616 
    9617 
    9618   lt_prog_compiler_wl=
    9619 lt_prog_compiler_pic=
    9620 lt_prog_compiler_static=
    9621 
    9622 
    9623   if test yes = "$GCC"; then
    9624     lt_prog_compiler_wl='-Wl,'
    9625     lt_prog_compiler_static='-static'
    9626 
    9627     case $host_os in
    9628       aix*)
    9629       # All AIX code is PIC.
    9630       if test ia64 = "$host_cpu"; then
    9631         # AIX 5 now supports IA64 processor
    9632         lt_prog_compiler_static='-Bstatic'
    9633       fi
    9634       lt_prog_compiler_pic='-fPIC'
    9635       ;;
    9636 
    9637     amigaos*)
    9638       case $host_cpu in
    9639       powerpc)
    9640             # see comment about AmigaOS4 .so support
    9641             lt_prog_compiler_pic='-fPIC'
    9642         ;;
    9643       m68k)
    9644             # FIXME: we need at least 68020 code to build shared libraries, but
    9645             # adding the '-m68020' flag to GCC prevents building anything better,
    9646             # like '-m68040'.
    9647             lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
    9648         ;;
    9649       esac
    9650       ;;
    9651 
    9652     beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
    9653       # PIC is the default for these OSes.
    9654       ;;
    9655 
    9656     mingw* | cygwin* | pw32* | os2* | cegcc*)
    9657       # This hack is so that the source file can tell whether it is being
    9658       # built for inclusion in a dll (and should export symbols for example).
    9659       # Although the cygwin gcc ignores -fPIC, still need this for old-style
    9660       # (--disable-auto-import) libraries
    9661       lt_prog_compiler_pic='-DDLL_EXPORT'
    9662       case $host_os in
    9663       os2*)
    9664         lt_prog_compiler_static='$wl-static'
    9665         ;;
    9666       esac
    9667       ;;
    9668 
    9669     darwin* | rhapsody*)
    9670       # PIC is the default on this platform
    9671       # Common symbols not allowed in MH_DYLIB files
    9672       lt_prog_compiler_pic='-fno-common'
    9673       ;;
    9674 
    9675     haiku*)
    9676       # PIC is the default for Haiku.
    9677       # The "-static" flag exists, but is broken.
    9678       lt_prog_compiler_static=
    9679       ;;
    9680 
    9681     hpux*)
    9682       # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
    9683       # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
    9684       # sets the default TLS model and affects inlining.
    9685       case $host_cpu in
    9686       hppa*64*)
    9687         # +Z the default
    9688         ;;
    9689       *)
    9690         lt_prog_compiler_pic='-fPIC'
    9691         ;;
    9692       esac
    9693       ;;
    9694 
    9695     interix[3-9]*)
    9696       # Interix 3.x gcc -fpic/-fPIC options generate broken code.
    9697       # Instead, we relocate shared libraries at runtime.
    9698       ;;
    9699 
    9700     msdosdjgpp*)
    9701       # Just because we use GCC doesn't mean we suddenly get shared libraries
    9702       # on systems that don't support them.
    9703       lt_prog_compiler_can_build_shared=no
    9704       enable_shared=no
    9705       ;;
    9706 
    9707     *nto* | *qnx*)
    9708       # QNX uses GNU C++, but need to define -shared option too, otherwise
    9709       # it will coredump.
    9710       lt_prog_compiler_pic='-fPIC -shared'
    9711       ;;
    9712 
    9713     sysv4*MP*)
    9714       if test -d /usr/nec; then
    9715         lt_prog_compiler_pic=-Kconform_pic
    9716       fi
    9717       ;;
    9718 
    9719     *)
    9720       lt_prog_compiler_pic='-fPIC'
    9721       ;;
    9722     esac
    9723 
    9724     case $cc_basename in
    9725     nvcc*) # Cuda Compiler Driver 2.2
    9726       lt_prog_compiler_wl='-Xlinker '
    9727       if test -n "$lt_prog_compiler_pic"; then
    9728         lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
    9729       fi
    9730       ;;
    9731     esac
    9732   else
    9733     # PORTME Check for flag to pass linker flags through the system compiler.
    9734     case $host_os in
    9735     aix*)
    9736       lt_prog_compiler_wl='-Wl,'
    9737       if test ia64 = "$host_cpu"; then
    9738         # AIX 5 now supports IA64 processor
    9739         lt_prog_compiler_static='-Bstatic'
    9740       else
    9741         lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
    9742       fi
    9743       ;;
    9744 
    9745     darwin* | rhapsody*)
    9746       # PIC is the default on this platform
    9747       # Common symbols not allowed in MH_DYLIB files
    9748       lt_prog_compiler_pic='-fno-common'
    9749       case $cc_basename in
    9750       nagfor*)
    9751         # NAG Fortran compiler
    9752         lt_prog_compiler_wl='-Wl,-Wl,,'
    9753         lt_prog_compiler_pic='-PIC'
    9754         lt_prog_compiler_static='-Bstatic'
    9755         ;;
    9756       esac
    9757       ;;
    9758 
    9759     mingw* | cygwin* | pw32* | os2* | cegcc*)
    9760       # This hack is so that the source file can tell whether it is being
    9761       # built for inclusion in a dll (and should export symbols for example).
    9762       lt_prog_compiler_pic='-DDLL_EXPORT'
    9763       case $host_os in
    9764       os2*)
    9765         lt_prog_compiler_static='$wl-static'
    9766         ;;
    9767       esac
    9768       ;;
    9769 
    9770     hpux9* | hpux10* | hpux11*)
    9771       lt_prog_compiler_wl='-Wl,'
    9772       # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
    9773       # not for PA HP-UX.
    9774       case $host_cpu in
    9775       hppa*64*|ia64*)
    9776         # +Z the default
    9777         ;;
    9778       *)
    9779         lt_prog_compiler_pic='+Z'
    9780         ;;
    9781       esac
    9782       # Is there a better lt_prog_compiler_static that works with the bundled CC?
    9783       lt_prog_compiler_static='$wl-a ${wl}archive'
    9784       ;;
    9785 
    9786     irix5* | irix6* | nonstopux*)
    9787       lt_prog_compiler_wl='-Wl,'
    9788       # PIC (with -KPIC) is the default.
    9789       lt_prog_compiler_static='-non_shared'
    9790       ;;
    9791 
    9792     linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    9793       case $cc_basename in
    9794       # old Intel for x86_64, which still supported -KPIC.
    9795       ecc*)
    9796         lt_prog_compiler_wl='-Wl,'
    9797         lt_prog_compiler_pic='-KPIC'
    9798         lt_prog_compiler_static='-static'
    9799         ;;
    9800       # icc used to be incompatible with GCC.
    9801       # ICC 10 doesn't accept -KPIC any more.
    9802       icc* | ifort*)
    9803         lt_prog_compiler_wl='-Wl,'
    9804         lt_prog_compiler_pic='-fPIC'
    9805         lt_prog_compiler_static='-static'
    9806         ;;
    9807       # Lahey Fortran 8.1.
    9808       lf95*)
    9809         lt_prog_compiler_wl='-Wl,'
    9810         lt_prog_compiler_pic='--shared'
    9811         lt_prog_compiler_static='--static'
    9812         ;;
    9813       nagfor*)
    9814         # NAG Fortran compiler
    9815         lt_prog_compiler_wl='-Wl,-Wl,,'
    9816         lt_prog_compiler_pic='-PIC'
    9817         lt_prog_compiler_static='-Bstatic'
    9818         ;;
    9819       tcc*)
    9820         # Fabrice Bellard et al's Tiny C Compiler
    9821         lt_prog_compiler_wl='-Wl,'
    9822         lt_prog_compiler_pic='-fPIC'
    9823         lt_prog_compiler_static='-static'
    9824         ;;
    9825       pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
    9826         # Portland Group compilers (*not* the Pentium gcc compiler,
    9827         # which looks to be a dead project)
    9828         lt_prog_compiler_wl='-Wl,'
    9829         lt_prog_compiler_pic='-fpic'
    9830         lt_prog_compiler_static='-Bstatic'
    9831         ;;
    9832       ccc*)
    9833         lt_prog_compiler_wl='-Wl,'
    9834         # All Alpha code is PIC.
    9835         lt_prog_compiler_static='-non_shared'
    9836         ;;
    9837       xl* | bgxl* | bgf* | mpixl*)
    9838         # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
    9839         lt_prog_compiler_wl='-Wl,'
    9840         lt_prog_compiler_pic='-qpic'
    9841         lt_prog_compiler_static='-qstaticlink'
    9842         ;;
    9843       *)
    9844         case `$CC -V 2>&1 | sed 5q` in
    9845         *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
    9846           # Sun Fortran 8.3 passes all unrecognized flags to the linker
    9847           lt_prog_compiler_pic='-KPIC'
    9848           lt_prog_compiler_static='-Bstatic'
    9849           lt_prog_compiler_wl=''
    9850           ;;
    9851         *Sun\ F* | *Sun*Fortran*)
    9852           lt_prog_compiler_pic='-KPIC'
    9853           lt_prog_compiler_static='-Bstatic'
    9854           lt_prog_compiler_wl='-Qoption ld '
    9855           ;;
    9856         *Sun\ C*)
    9857           # Sun C 5.9
    9858           lt_prog_compiler_pic='-KPIC'
    9859           lt_prog_compiler_static='-Bstatic'
    9860           lt_prog_compiler_wl='-Wl,'
    9861           ;;
    9862         *Intel*\ [CF]*Compiler*)
    9863           lt_prog_compiler_wl='-Wl,'
    9864           lt_prog_compiler_pic='-fPIC'
    9865           lt_prog_compiler_static='-static'
    9866           ;;
    9867         *Portland\ Group*)
    9868           lt_prog_compiler_wl='-Wl,'
    9869           lt_prog_compiler_pic='-fpic'
    9870           lt_prog_compiler_static='-Bstatic'
    9871           ;;
    9872         esac
    9873         ;;
    9874       esac
    9875       ;;
    9876 
    9877     newsos6)
    9878       lt_prog_compiler_pic='-KPIC'
    9879       lt_prog_compiler_static='-Bstatic'
    9880       ;;
    9881 
    9882     *nto* | *qnx*)
    9883       # QNX uses GNU C++, but need to define -shared option too, otherwise
    9884       # it will coredump.
    9885       lt_prog_compiler_pic='-fPIC -shared'
    9886       ;;
    9887 
    9888     osf3* | osf4* | osf5*)
    9889       lt_prog_compiler_wl='-Wl,'
    9890       # All OSF/1 code is PIC.
    9891       lt_prog_compiler_static='-non_shared'
    9892       ;;
    9893 
    9894     rdos*)
    9895       lt_prog_compiler_static='-non_shared'
    9896       ;;
    9897 
    9898     solaris*)
    9899       lt_prog_compiler_pic='-KPIC'
    9900       lt_prog_compiler_static='-Bstatic'
    9901       case $cc_basename in
    9902       f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
    9903         lt_prog_compiler_wl='-Qoption ld ';;
    9904       *)
    9905         lt_prog_compiler_wl='-Wl,';;
    9906       esac
    9907       ;;
    9908 
    9909     sunos4*)
    9910       lt_prog_compiler_wl='-Qoption ld '
    9911       lt_prog_compiler_pic='-PIC'
    9912       lt_prog_compiler_static='-Bstatic'
    9913       ;;
    9914 
    9915     sysv4 | sysv4.2uw2* | sysv4.3*)
    9916       lt_prog_compiler_wl='-Wl,'
    9917       lt_prog_compiler_pic='-KPIC'
    9918       lt_prog_compiler_static='-Bstatic'
    9919       ;;
    9920 
    9921     sysv4*MP*)
    9922       if test -d /usr/nec; then
    9923         lt_prog_compiler_pic='-Kconform_pic'
    9924         lt_prog_compiler_static='-Bstatic'
    9925       fi
    9926       ;;
    9927 
    9928     sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
    9929       lt_prog_compiler_wl='-Wl,'
    9930       lt_prog_compiler_pic='-KPIC'
    9931       lt_prog_compiler_static='-Bstatic'
    9932       ;;
    9933 
    9934     unicos*)
    9935       lt_prog_compiler_wl='-Wl,'
    9936       lt_prog_compiler_can_build_shared=no
    9937       ;;
    9938 
    9939     uts4*)
    9940       lt_prog_compiler_pic='-pic'
    9941       lt_prog_compiler_static='-Bstatic'
    9942       ;;
    9943 
    9944     *)
    9945       lt_prog_compiler_can_build_shared=no
    9946       ;;
    9947     esac
    9948   fi
    9949 
    9950 case $host_os in
    9951   # For platforms that do not support PIC, -DPIC is meaningless:
    9952   *djgpp*)
    9953     lt_prog_compiler_pic=
    9954     ;;
    9955   *)
    9956     lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
    9957     ;;
    9958 esac
    9959 
    9960 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
    9961 $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
    9962 if ${lt_cv_prog_compiler_pic+:} false; then :
    9963   $as_echo_n "(cached) " >&6
    9964 else
    9965   lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
    9966 fi
    9967 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
    9968 $as_echo "$lt_cv_prog_compiler_pic" >&6; }
    9969 lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
    9970 
    9971 #
    9972 # Check to make sure the PIC flag actually works.
    9973 #
    9974 if test -n "$lt_prog_compiler_pic"; then
    9975   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
    9976 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
    9977 if ${lt_cv_prog_compiler_pic_works+:} false; then :
    9978   $as_echo_n "(cached) " >&6
    9979 else
    9980   lt_cv_prog_compiler_pic_works=no
    9981    ac_outfile=conftest.$ac_objext
    9982    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    9983    lt_compiler_flag="$lt_prog_compiler_pic -DPIC"  ## exclude from sc_useless_quotes_in_assignment
    9984    # Insert the option either (1) after the last *FLAGS variable, or
    9985    # (2) before a word containing "conftest.", or (3) at the end.
    9986    # Note that $ac_compile itself does not contain backslashes and begins
    9987    # with a dollar sign (not a hyphen), so the echo should work correctly.
    9988    # The option is referenced via a variable to avoid confusing sed.
    9989    lt_compile=`echo "$ac_compile" | $SED \
    9990    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    9991    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    9992    -e 's:$: $lt_compiler_flag:'`
    9993    (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    9994    (eval "$lt_compile" 2>conftest.err)
    9995    ac_status=$?
    9996    cat conftest.err >&5
    9997    echo "$as_me:$LINENO: \$? = $ac_status" >&5
    9998    if (exit $ac_status) && test -s "$ac_outfile"; then
    9999      # The compiler can only warn and ignore the option if not recognized
    10000      # So say no if there are warnings other than the usual output.
    10001      $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
    10002      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
    10003      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
    10004        lt_cv_prog_compiler_pic_works=yes
    10005      fi
    10006    fi
    10007    $RM conftest*
    10008 
    10009 fi
    10010 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
    10011 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
    10012 
    10013 if test yes = "$lt_cv_prog_compiler_pic_works"; then
    10014     case $lt_prog_compiler_pic in
    10015      "" | " "*) ;;
    10016      *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
    10017      esac
    10018 else
    10019     lt_prog_compiler_pic=
    10020      lt_prog_compiler_can_build_shared=no
    10021 fi
    10022 
    10023 fi
    10024 
    10025 
    10026 
    10027 
    10028 
    10029 
    10030 
    10031 
    10032 
    10033 
    10034 
    10035 #
    10036 # Check to make sure the static flag actually works.
    10037 #
    10038 wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
    10039 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
    10040 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
    10041 if ${lt_cv_prog_compiler_static_works+:} false; then :
    10042   $as_echo_n "(cached) " >&6
    10043 else
    10044   lt_cv_prog_compiler_static_works=no
    10045    save_LDFLAGS=$LDFLAGS
    10046    LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
    10047    echo "$lt_simple_link_test_code" > conftest.$ac_ext
    10048    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
    10049      # The linker can only warn and ignore the option if not recognized
    10050      # So say no if there are warnings
    10051      if test -s conftest.err; then
    10052        # Append any errors to the config.log.
    10053        cat conftest.err 1>&5
    10054        $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
    10055        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
    10056        if diff conftest.exp conftest.er2 >/dev/null; then
    10057          lt_cv_prog_compiler_static_works=yes
    10058        fi
    10059      else
    10060        lt_cv_prog_compiler_static_works=yes
    10061      fi
    10062    fi
    10063    $RM -r conftest*
    10064    LDFLAGS=$save_LDFLAGS
    10065 
    10066 fi
    10067 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
    10068 $as_echo "$lt_cv_prog_compiler_static_works" >&6; }
    10069 
    10070 if test yes = "$lt_cv_prog_compiler_static_works"; then
    10071     :
    10072 else
    10073     lt_prog_compiler_static=
    10074 fi
    10075 
    10076 
    10077 
    10078 
    10079 
    10080 
    10081 
    10082   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
    10083 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
    10084 if ${lt_cv_prog_compiler_c_o+:} false; then :
    10085   $as_echo_n "(cached) " >&6
    10086 else
    10087   lt_cv_prog_compiler_c_o=no
    10088    $RM -r conftest 2>/dev/null
    10089    mkdir conftest
    10090    cd conftest
    10091    mkdir out
    10092    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    10093 
    10094    lt_compiler_flag="-o out/conftest2.$ac_objext"
    10095    # Insert the option either (1) after the last *FLAGS variable, or
    10096    # (2) before a word containing "conftest.", or (3) at the end.
    10097    # Note that $ac_compile itself does not contain backslashes and begins
    10098    # with a dollar sign (not a hyphen), so the echo should work correctly.
    10099    lt_compile=`echo "$ac_compile" | $SED \
    10100    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    10101    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    10102    -e 's:$: $lt_compiler_flag:'`
    10103    (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    10104    (eval "$lt_compile" 2>out/conftest.err)
    10105    ac_status=$?
    10106    cat out/conftest.err >&5
    10107    echo "$as_me:$LINENO: \$? = $ac_status" >&5
    10108    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    10109    then
    10110      # The compiler can only warn and ignore the option if not recognized
    10111      # So say no if there are warnings
    10112      $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
    10113      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
    10114      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
    10115        lt_cv_prog_compiler_c_o=yes
    10116      fi
    10117    fi
    10118    chmod u+w . 2>&5
    10119    $RM conftest*
    10120    # SGI C++ compiler will create directory out/ii_files/ for
    10121    # template instantiation
    10122    test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
    10123    $RM out/* && rmdir out
    10124    cd ..
    10125    $RM -r conftest
    10126    $RM conftest*
    10127 
    10128 fi
    10129 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
    10130 $as_echo "$lt_cv_prog_compiler_c_o" >&6; }
    10131 
    10132 
    10133 
    10134 
    10135 
    10136 
    10137   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
    10138 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
    10139 if ${lt_cv_prog_compiler_c_o+:} false; then :
    10140   $as_echo_n "(cached) " >&6
    10141 else
    10142   lt_cv_prog_compiler_c_o=no
    10143    $RM -r conftest 2>/dev/null
    10144    mkdir conftest
    10145    cd conftest
    10146    mkdir out
    10147    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    10148 
    10149    lt_compiler_flag="-o out/conftest2.$ac_objext"
    10150    # Insert the option either (1) after the last *FLAGS variable, or
    10151    # (2) before a word containing "conftest.", or (3) at the end.
    10152    # Note that $ac_compile itself does not contain backslashes and begins
    10153    # with a dollar sign (not a hyphen), so the echo should work correctly.
    10154    lt_compile=`echo "$ac_compile" | $SED \
    10155    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    10156    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    10157    -e 's:$: $lt_compiler_flag:'`
    10158    (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    10159    (eval "$lt_compile" 2>out/conftest.err)
    10160    ac_status=$?
    10161    cat out/conftest.err >&5
    10162    echo "$as_me:$LINENO: \$? = $ac_status" >&5
    10163    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    10164    then
    10165      # The compiler can only warn and ignore the option if not recognized
    10166      # So say no if there are warnings
    10167      $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
    10168      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
    10169      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
    10170        lt_cv_prog_compiler_c_o=yes
    10171      fi
    10172    fi
    10173    chmod u+w . 2>&5
    10174    $RM conftest*
    10175    # SGI C++ compiler will create directory out/ii_files/ for
    10176    # template instantiation
    10177    test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
    10178    $RM out/* && rmdir out
    10179    cd ..
    10180    $RM -r conftest
    10181    $RM conftest*
    10182 
    10183 fi
    10184 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
    10185 $as_echo "$lt_cv_prog_compiler_c_o" >&6; }
    10186 
    10187 
    10188 
    10189 
    10190 hard_links=nottested
    10191 if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
    10192   # do not overwrite the value of need_locks provided by the user
    10193   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
    10194 $as_echo_n "checking if we can lock with hard links... " >&6; }
    10195   hard_links=yes
    10196   $RM conftest*
    10197   ln conftest.a conftest.b 2>/dev/null && hard_links=no
    10198   touch conftest.a
    10199   ln conftest.a conftest.b 2>&5 || hard_links=no
    10200   ln conftest.a conftest.b 2>/dev/null && hard_links=no
    10201   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
    10202 $as_echo "$hard_links" >&6; }
    10203   if test no = "$hard_links"; then
    10204     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
    10205 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
    10206     need_locks=warn
    10207   fi
    10208 else
    10209   need_locks=no
    10210 fi
    10211 
    10212 
    10213 
    10214 
    10215 
    10216 
    10217   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
    10218 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
    10219 
    10220   runpath_var=
    10221   allow_undefined_flag=
    10222   always_export_symbols=no
    10223   archive_cmds=
    10224   archive_expsym_cmds=
    10225   compiler_needs_object=no
    10226   enable_shared_with_static_runtimes=no
    10227   export_dynamic_flag_spec=
    10228   export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
    10229   hardcode_automatic=no
    10230   hardcode_direct=no
    10231   hardcode_direct_absolute=no
    10232   hardcode_libdir_flag_spec=
    10233   hardcode_libdir_separator=
    10234   hardcode_minus_L=no
    10235   hardcode_shlibpath_var=unsupported
    10236   inherit_rpath=no
    10237   link_all_deplibs=unknown
    10238   module_cmds=
    10239   module_expsym_cmds=
    10240   old_archive_from_new_cmds=
    10241   old_archive_from_expsyms_cmds=
    10242   thread_safe_flag_spec=
    10243   whole_archive_flag_spec=
    10244   # include_expsyms should be a list of space-separated symbols to be *always*
    10245   # included in the symbol list
    10246   include_expsyms=
    10247   # exclude_expsyms can be an extended regexp of symbols to exclude
    10248   # it will be wrapped by ' (' and ')$', so one must not match beginning or
    10249   # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
    10250   # as well as any symbol that contains 'd'.
    10251   exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
    10252   # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
    10253   # platforms (ab)use it in PIC code, but their linkers get confused if
    10254   # the symbol is explicitly referenced.  Since portable code cannot
    10255   # rely on this symbol name, it's probably fine to never include it in
    10256   # preloaded symbol tables.
    10257   # Exclude shared library initialization/finalization symbols.
    10258   extract_expsyms_cmds=
    10259 
    10260   case $host_os in
    10261   cygwin* | mingw* | pw32* | cegcc*)
    10262     # FIXME: the MSVC++ port hasn't been tested in a loooong time
    10263     # When not using gcc, we currently assume that we are using
    10264     # Microsoft Visual C++.
    10265     if test yes != "$GCC"; then
    10266       with_gnu_ld=no
    10267     fi
    10268     ;;
    10269   interix*)
    10270     # we just hope/assume this is gcc and not c89 (= MSVC++)
    10271     with_gnu_ld=yes
    10272     ;;
    10273   openbsd* | bitrig*)
    10274     with_gnu_ld=no
    10275     ;;
    10276   linux* | k*bsd*-gnu | gnu*)
    10277     link_all_deplibs=no
    10278     ;;
    10279   esac
    10280 
    10281   ld_shlibs=yes
    10282 
    10283   # On some targets, GNU ld is compatible enough with the native linker
    10284   # that we're better off using the native interface for both.
    10285   lt_use_gnu_ld_interface=no
    10286   if test yes = "$with_gnu_ld"; then
    10287     case $host_os in
    10288       aix*)
    10289         # The AIX port of GNU ld has always aspired to compatibility
    10290         # with the native linker.  However, as the warning in the GNU ld
    10291         # block says, versions before 2.19.5* couldn't really create working
    10292         # shared libraries, regardless of the interface used.
    10293         case `$LD -v 2>&1` in
    10294           *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
    10295           *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
    10296           *\ \(GNU\ Binutils\)\ [3-9]*) ;;
    10297           *)
    10298             lt_use_gnu_ld_interface=yes
    10299             ;;
    10300         esac
    10301         ;;
    10302       *)
    10303         lt_use_gnu_ld_interface=yes
    10304         ;;
    10305     esac
    10306   fi
    10307 
    10308   if test yes = "$lt_use_gnu_ld_interface"; then
    10309     # If archive_cmds runs LD, not CC, wlarc should be empty
    10310     wlarc='$wl'
    10311 
    10312     # Set some defaults for GNU ld with shared library support. These
    10313     # are reset later if shared libraries are not supported. Putting them
    10314     # here allows them to be overridden if necessary.
    10315     runpath_var=LD_RUN_PATH
    10316     hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
    10317     export_dynamic_flag_spec='$wl--export-dynamic'
    10318     # ancient GNU ld didn't support --whole-archive et. al.
    10319     if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
    10320       whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
    10321     else
    10322       whole_archive_flag_spec=
    10323     fi
    10324     supports_anon_versioning=no
    10325     case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in
    10326       *GNU\ gold*) supports_anon_versioning=yes ;;
    10327       *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
    10328       *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
    10329       *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
    10330       *\ 2.11.*) ;; # other 2.11 versions
    10331       *) supports_anon_versioning=yes ;;
    10332     esac
    10333 
    10334     # See if GNU ld supports shared libraries.
    10335     case $host_os in
    10336     aix[3-9]*)
    10337       # On AIX/PPC, the GNU linker is very broken
    10338       if test ia64 != "$host_cpu"; then
    10339         ld_shlibs=no
    10340         cat <<_LT_EOF 1>&2
    10341 
    10342 *** Warning: the GNU linker, at least up to release 2.19, is reported
    10343 *** to be unable to reliably create shared libraries on AIX.
    10344 *** Therefore, libtool is disabling shared libraries support.  If you
    10345 *** really care for shared libraries, you may want to install binutils
    10346 *** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
    10347 *** You will then need to restart the configuration process.
    10348 
    10349 _LT_EOF
    10350       fi
    10351       ;;
    10352 
    10353     amigaos*)
    10354       case $host_cpu in
    10355       powerpc)
    10356             # see comment about AmigaOS4 .so support
    10357             archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10358             archive_expsym_cmds=''
    10359         ;;
    10360       m68k)
    10361             archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
    10362             hardcode_libdir_flag_spec='-L$libdir'
    10363             hardcode_minus_L=yes
    10364         ;;
    10365       esac
    10366       ;;
    10367 
    10368     beos*)
    10369       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
    10370         allow_undefined_flag=unsupported
    10371         # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
    10372         # support --undefined.  This deserves some investigation.  FIXME
    10373         archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10374       else
    10375         ld_shlibs=no
    10376       fi
    10377       ;;
    10378 
    10379     cygwin* | mingw* | pw32* | cegcc*)
    10380       # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
    10381       # as there is no search path for DLLs.
    10382       hardcode_libdir_flag_spec='-L$libdir'
    10383       export_dynamic_flag_spec='$wl--export-all-symbols'
    10384       allow_undefined_flag=unsupported
    10385       always_export_symbols=no
    10386       enable_shared_with_static_runtimes=yes
    10387       export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
    10388       exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
    10389 
    10390       if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
    10391         archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
    10392         # If the export-symbols file already is a .def file, use it as
    10393         # is; otherwise, prepend EXPORTS...
    10394         archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[   ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([     ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
    10395           cp $export_symbols $output_objdir/$soname.def;
    10396         else
    10397           echo EXPORTS > $output_objdir/$soname.def;
    10398           cat $export_symbols >> $output_objdir/$soname.def;
    10399         fi~
    10400         $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
    10401       else
    10402         ld_shlibs=no
    10403       fi
    10404       ;;
    10405 
    10406     haiku*)
    10407       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10408       link_all_deplibs=yes
    10409       ;;
    10410 
    10411     os2*)
    10412       hardcode_libdir_flag_spec='-L$libdir'
    10413       hardcode_minus_L=yes
    10414       allow_undefined_flag=unsupported
    10415       shrext_cmds=.dll
    10416       archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
    10417         $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
    10418         $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
    10419         $ECHO EXPORTS >> $output_objdir/$libname.def~
    10420         emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
    10421         $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
    10422         emximp -o $lib $output_objdir/$libname.def'
    10423       archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
    10424         $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
    10425         $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
    10426         $ECHO EXPORTS >> $output_objdir/$libname.def~
    10427         prefix_cmds="$SED"~
    10428         if test EXPORTS = "`$SED 1q $export_symbols`"; then
    10429           prefix_cmds="$prefix_cmds -e 1d";
    10430         fi~
    10431         prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
    10432         cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
    10433         $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
    10434         emximp -o $lib $output_objdir/$libname.def'
    10435       old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
    10436       enable_shared_with_static_runtimes=yes
    10437       ;;
    10438 
    10439     interix[3-9]*)
    10440       hardcode_direct=no
    10441       hardcode_shlibpath_var=no
    10442       hardcode_libdir_flag_spec='$wl-rpath,$libdir'
    10443       export_dynamic_flag_spec='$wl-E'
    10444       # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
    10445       # Instead, shared libraries are loaded at an image base (0x10000000 by
    10446       # default) and relocated if they conflict, which is a slow very memory
    10447       # consuming and fragmenting process.  To avoid this, we pick a random,
    10448       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
    10449       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
    10450       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
    10451       archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
    10452       ;;
    10453 
    10454     gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
    10455       tmp_diet=no
    10456       if test linux-dietlibc = "$host_os"; then
    10457         case $cc_basename in
    10458           diet\ *) tmp_diet=yes;;       # linux-dietlibc with static linking (!diet-dyn)
    10459         esac
    10460       fi
    10461       if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
    10462          && test no = "$tmp_diet"
    10463       then
    10464         tmp_addflag=' $pic_flag'
    10465         tmp_sharedflag='-shared'
    10466         case $cc_basename,$host_cpu in
    10467         pgcc*)                          # Portland Group C compiler
    10468           whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
    10469           tmp_addflag=' $pic_flag'
    10470           ;;
    10471         pgf77* | pgf90* | pgf95* | pgfortran*)
    10472                                         # Portland Group f77 and f90 compilers
    10473           whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
    10474           tmp_addflag=' $pic_flag -Mnomain' ;;
    10475         ecc*,ia64* | icc*,ia64*)        # Intel C compiler on ia64
    10476           tmp_addflag=' -i_dynamic' ;;
    10477         efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
    10478           tmp_addflag=' -i_dynamic -nofor_main' ;;
    10479         ifc* | ifort*)                  # Intel Fortran compiler
    10480           tmp_addflag=' -nofor_main' ;;
    10481         lf95*)                          # Lahey Fortran 8.1
    10482           whole_archive_flag_spec=
    10483           tmp_sharedflag='--shared' ;;
    10484         nagfor*)                        # NAGFOR 5.3
    10485           tmp_sharedflag='-Wl,-shared' ;;
    10486         xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
    10487           tmp_sharedflag='-qmkshrobj'
    10488           tmp_addflag= ;;
    10489         nvcc*)  # Cuda Compiler Driver 2.2
    10490           whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
    10491           compiler_needs_object=yes
    10492           ;;
    10493         esac
    10494         case `$CC -V 2>&1 | sed 5q` in
    10495         *Sun\ C*)                       # Sun C 5.9
    10496           whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
    10497           compiler_needs_object=yes
    10498           tmp_sharedflag='-G' ;;
    10499         *Sun\ F*)                       # Sun Fortran 8.3
    10500           tmp_sharedflag='-G' ;;
    10501         esac
    10502         archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10503 
    10504         if test yes = "$supports_anon_versioning"; then
    10505           archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
    10506             cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
    10507             echo "local: *; };" >> $output_objdir/$libname.ver~
    10508             $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
    10509         fi
    10510 
    10511         case $cc_basename in
    10512         tcc*)
    10513           export_dynamic_flag_spec='-rdynamic'
    10514           ;;
    10515         xlf* | bgf* | bgxlf* | mpixlf*)
    10516           # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
    10517           whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
    10518           hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
    10519           archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
    10520           if test yes = "$supports_anon_versioning"; then
    10521             archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
    10522               cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
    10523               echo "local: *; };" >> $output_objdir/$libname.ver~
    10524               $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
    10525           fi
    10526           ;;
    10527         esac
    10528       else
    10529         ld_shlibs=no
    10530       fi
    10531       ;;
    10532 
    10533     netbsd* | netbsdelf*-gnu)
    10534       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
    10535         archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
    10536         wlarc=
    10537       else
    10538         archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10539         archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    10540       fi
    10541       ;;
    10542 
    10543     solaris*)
    10544       if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
    10545         ld_shlibs=no
    10546         cat <<_LT_EOF 1>&2
    10547 
    10548 *** Warning: The releases 2.8.* of the GNU linker cannot reliably
    10549 *** create shared libraries on Solaris systems.  Therefore, libtool
    10550 *** is disabling shared libraries support.  We urge you to upgrade GNU
    10551 *** binutils to release 2.9.1 or newer.  Another option is to modify
    10552 *** your PATH or compiler configuration so that the native linker is
    10553 *** used, and then restart.
    10554 
    10555 _LT_EOF
    10556       elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
    10557         archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10558         archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    10559       else
    10560         ld_shlibs=no
    10561       fi
    10562       ;;
    10563 
    10564     sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
    10565       case `$LD -v 2>&1` in
    10566         *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
    10567         ld_shlibs=no
    10568         cat <<_LT_EOF 1>&2
    10569 
    10570 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
    10571 *** reliably create shared libraries on SCO systems.  Therefore, libtool
    10572 *** is disabling shared libraries support.  We urge you to upgrade GNU
    10573 *** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
    10574 *** your PATH or compiler configuration so that the native linker is
    10575 *** used, and then restart.
    10576 
    10577 _LT_EOF
    10578         ;;
    10579         *)
    10580           # For security reasons, it is highly recommended that you always
    10581           # use absolute paths for naming shared libraries, and exclude the
    10582           # DT_RUNPATH tag from executables and libraries.  But doing so
    10583           # requires that you compile everything twice, which is a pain.
    10584           if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
    10585             hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
    10586             archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10587             archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    10588           else
    10589             ld_shlibs=no
    10590           fi
    10591         ;;
    10592       esac
    10593       ;;
    10594 
    10595     sunos4*)
    10596       archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
    10597       wlarc=
    10598       hardcode_direct=yes
    10599       hardcode_shlibpath_var=no
    10600       ;;
    10601 
    10602     *)
    10603       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
    10604         archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10605         archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    10606       else
    10607         ld_shlibs=no
    10608       fi
    10609       ;;
    10610     esac
    10611 
    10612     if test no = "$ld_shlibs"; then
    10613       runpath_var=
    10614       hardcode_libdir_flag_spec=
    10615       export_dynamic_flag_spec=
    10616       whole_archive_flag_spec=
    10617     fi
    10618   else
    10619     # PORTME fill in a description of your system's linker (not GNU ld)
    10620     case $host_os in
    10621     aix3*)
    10622       allow_undefined_flag=unsupported
    10623       always_export_symbols=yes
    10624       archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
    10625       # Note: this linker hardcodes the directories in LIBPATH if there
    10626       # are no directories specified by -L.
    10627       hardcode_minus_L=yes
    10628       if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
    10629         # Neither direct hardcoding nor static linking is supported with a
    10630         # broken collect2.
    10631         hardcode_direct=unsupported
    10632       fi
    10633       ;;
    10634 
    10635     aix[4-9]*)
    10636       if test ia64 = "$host_cpu"; then
    10637         # On IA64, the linker does run time linking by default, so we don't
    10638         # have to do anything special.
    10639         aix_use_runtimelinking=no
    10640         exp_sym_flag='-Bexport'
    10641         no_entry_flag=
    10642       else
    10643         # If we're using GNU nm, then we don't want the "-C" option.
    10644         # -C means demangle to GNU nm, but means don't demangle to AIX nm.
    10645         # Without the "-l" option, or with the "-B" option, AIX nm treats
    10646         # weak defined symbols like other global defined symbols, whereas
    10647         # GNU nm marks them as "W".
    10648         # While the 'weak' keyword is ignored in the Export File, we need
    10649         # it in the Import File for the 'aix-soname' feature, so we have
    10650         # to replace the "-B" option with "-P" for AIX nm.
    10651         if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
    10652           export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
    10653         else
    10654           export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
    10655         fi
    10656         aix_use_runtimelinking=no
    10657 
    10658         # Test if we are trying to use run time linking or normal
    10659         # AIX style linking. If -brtl is somewhere in LDFLAGS, we
    10660         # have runtime linking enabled, and use it for executables.
    10661         # For shared libraries, we enable/disable runtime linking
    10662         # depending on the kind of the shared library created -
    10663         # when "with_aix_soname,aix_use_runtimelinking" is:
    10664         # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
    10665         # "aix,yes"  lib.so          shared, rtl:yes, for executables
    10666         #            lib.a           static archive
    10667         # "both,no"  lib.so.V(shr.o) shared, rtl:yes
    10668         #            lib.a(lib.so.V) shared, rtl:no,  for executables
    10669         # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
    10670         #            lib.a(lib.so.V) shared, rtl:no
    10671         # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
    10672         #            lib.a           static archive
    10673         case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
    10674           for ld_flag in $LDFLAGS; do
    10675           if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
    10676             aix_use_runtimelinking=yes
    10677             break
    10678           fi
    10679           done
    10680           if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
    10681             # With aix-soname=svr4, we create the lib.so.V shared archives only,
    10682             # so we don't have lib.a shared libs to link our executables.
    10683             # We have to force runtime linking in this case.
    10684             aix_use_runtimelinking=yes
    10685             LDFLAGS="$LDFLAGS -Wl,-brtl"
    10686           fi
    10687           ;;
    10688         esac
    10689 
    10690         exp_sym_flag='-bexport'
    10691         no_entry_flag='-bnoentry'
    10692       fi
    10693 
    10694       # When large executables or shared objects are built, AIX ld can
    10695       # have problems creating the table of contents.  If linking a library
    10696       # or program results in "error TOC overflow" add -mminimal-toc to
    10697       # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
    10698       # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
    10699 
    10700       archive_cmds=''
    10701       hardcode_direct=yes
    10702       hardcode_direct_absolute=yes
    10703       hardcode_libdir_separator=':'
    10704       link_all_deplibs=yes
    10705       file_list_spec='$wl-f,'
    10706       case $with_aix_soname,$aix_use_runtimelinking in
    10707       aix,*) ;; # traditional, no import file
    10708       svr4,* | *,yes) # use import file
    10709         # The Import File defines what to hardcode.
    10710         hardcode_direct=no
    10711         hardcode_direct_absolute=no
    10712         ;;
    10713       esac
    10714 
    10715       if test yes = "$GCC"; then
    10716         case $host_os in aix4.[012]|aix4.[012].*)
    10717         # We only want to do this on AIX 4.2 and lower, the check
    10718         # below for broken collect2 doesn't work under 4.3+
    10719           collect2name=`$CC -print-prog-name=collect2`
    10720           if test -f "$collect2name" &&
    10721            strings "$collect2name" | $GREP resolve_lib_name >/dev/null
    10722           then
    10723           # We have reworked collect2
    10724           :
    10725           else
    10726           # We have old collect2
    10727           hardcode_direct=unsupported
    10728           # It fails to find uninstalled libraries when the uninstalled
    10729           # path is not listed in the libpath.  Setting hardcode_minus_L
    10730           # to unsupported forces relinking
    10731           hardcode_minus_L=yes
    10732           hardcode_libdir_flag_spec='-L$libdir'
    10733           hardcode_libdir_separator=
    10734           fi
    10735           ;;
    10736         esac
    10737         shared_flag='-shared'
    10738         if test yes = "$aix_use_runtimelinking"; then
    10739           shared_flag="$shared_flag "'$wl-G'
    10740         fi
    10741         # Need to ensure runtime linking is disabled for the traditional
    10742         # shared library, or the linker may eventually find shared libraries
    10743         # /with/ Import File - we do not want to mix them.
    10744         shared_flag_aix='-shared'
    10745         shared_flag_svr4='-shared $wl-G'
    10746       else
    10747         # not using gcc
    10748         if test ia64 = "$host_cpu"; then
    10749         # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
    10750         # chokes on -Wl,-G. The following line is correct:
    10751           shared_flag='-G'
    10752         else
    10753           if test yes = "$aix_use_runtimelinking"; then
    10754             shared_flag='$wl-G'
    10755           else
    10756             shared_flag='$wl-bM:SRE'
    10757           fi
    10758           shared_flag_aix='$wl-bM:SRE'
    10759           shared_flag_svr4='$wl-G'
    10760         fi
    10761       fi
    10762 
    10763       export_dynamic_flag_spec='$wl-bexpall'
    10764       # It seems that -bexpall does not export symbols beginning with
    10765       # underscore (_), so it is better to generate a list of symbols to export.
    10766       always_export_symbols=yes
    10767       if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
    10768         # Warning - without using the other runtime loading flags (-brtl),
    10769         # -berok will link without error, but may produce a broken library.
    10770         allow_undefined_flag='-berok'
    10771         # Determine the default libpath from the value encoded in an
    10772         # empty executable.
    10773         if test set = "${lt_cv_aix_libpath+set}"; then
    10774   aix_libpath=$lt_cv_aix_libpath
    10775 else
    10776   if ${lt_cv_aix_libpath_+:} false; then :
     5808#define size_t unsigned int
     5809_ACEOF
     5810
     5811fi
     5812
     5813# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
     5814# for constant arguments.  Useless!
     5815{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
     5816$as_echo_n "checking for working alloca.h... " >&6; }
     5817if ${ac_cv_working_alloca_h+:} false; then :
    107775818  $as_echo_n "(cached) " >&6
    107785819else
    107795820  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    107805821/* end confdefs.h.  */
    10781 
     5822#include <alloca.h>
    107825823int
    107835824main ()
    107845825{
    10785 
     5826char *p = (char *) alloca (2 * sizeof (int));
     5827                          if (p) return 0;
    107865828  ;
    107875829  return 0;
     
    107895831_ACEOF
    107905832if ac_fn_c_try_link "$LINENO"; then :
    10791 
    10792   lt_aix_libpath_sed='
    10793       /Import File Strings/,/^$/ {
    10794           /^0/ {
    10795               s/^0  *\([^ ]*\) *$/\1/
    10796               p
    10797           }
    10798       }'
    10799   lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    10800   # Check for a 64-bit object if we didn't find anything.
    10801   if test -z "$lt_cv_aix_libpath_"; then
    10802     lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    10803   fi
     5833  ac_cv_working_alloca_h=yes
     5834else
     5835  ac_cv_working_alloca_h=no
    108045836fi
    108055837rm -f core conftest.err conftest.$ac_objext \
    108065838    conftest$ac_exeext conftest.$ac_ext
    10807   if test -z "$lt_cv_aix_libpath_"; then
    10808     lt_cv_aix_libpath_=/usr/lib:/lib
    10809   fi
    10810 
    10811 fi
    10812 
    10813   aix_libpath=$lt_cv_aix_libpath_
    10814 fi
    10815 
    10816         hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
    10817         archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
    10818       else
    10819         if test ia64 = "$host_cpu"; then
    10820           hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
    10821           allow_undefined_flag="-z nodefs"
    10822           archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
    10823         else
    10824          # Determine the default libpath from the value encoded in an
    10825          # empty executable.
    10826          if test set = "${lt_cv_aix_libpath+set}"; then
    10827   aix_libpath=$lt_cv_aix_libpath
    10828 else
    10829   if ${lt_cv_aix_libpath_+:} false; then :
     5839fi
     5840{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
     5841$as_echo "$ac_cv_working_alloca_h" >&6; }
     5842if test $ac_cv_working_alloca_h = yes; then
     5843
     5844$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h
     5845
     5846fi
     5847
     5848{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
     5849$as_echo_n "checking for alloca... " >&6; }
     5850if ${ac_cv_func_alloca_works+:} false; then :
    108305851  $as_echo_n "(cached) " >&6
    108315852else
    108325853  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    108335854/* end confdefs.h.  */
     5855#ifdef __GNUC__
     5856# define alloca __builtin_alloca
     5857#else
     5858# ifdef _MSC_VER
     5859#  include <malloc.h>
     5860#  define alloca _alloca
     5861# else
     5862#  ifdef HAVE_ALLOCA_H
     5863#   include <alloca.h>
     5864#  else
     5865#   ifdef _AIX
     5866 #pragma alloca
     5867#   else
     5868#    ifndef alloca /* predefined by HP cc +Olibcalls */
     5869void *alloca (size_t);
     5870#    endif
     5871#   endif
     5872#  endif
     5873# endif
     5874#endif
    108345875
    108355876int
    108365877main ()
    108375878{
    10838 
     5879char *p = (char *) alloca (1);
     5880                                    if (p) return 0;
    108395881  ;
    108405882  return 0;
     
    108425884_ACEOF
    108435885if ac_fn_c_try_link "$LINENO"; then :
    10844 
    10845   lt_aix_libpath_sed='
    10846       /Import File Strings/,/^$/ {
    10847           /^0/ {
    10848               s/^0  *\([^ ]*\) *$/\1/
    10849               p
    10850           }
    10851       }'
    10852   lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    10853   # Check for a 64-bit object if we didn't find anything.
    10854   if test -z "$lt_cv_aix_libpath_"; then
    10855     lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    10856   fi
     5886  ac_cv_func_alloca_works=yes
     5887else
     5888  ac_cv_func_alloca_works=no
    108575889fi
    108585890rm -f core conftest.err conftest.$ac_objext \
    108595891    conftest$ac_exeext conftest.$ac_ext
    10860   if test -z "$lt_cv_aix_libpath_"; then
    10861     lt_cv_aix_libpath_=/usr/lib:/lib
    10862   fi
    10863 
    10864 fi
    10865 
    10866   aix_libpath=$lt_cv_aix_libpath_
    10867 fi
    10868 
    10869          hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
    10870           # Warning - without using the other run time loading flags,
    10871           # -berok will link without error, but may produce a broken library.
    10872           no_undefined_flag=' $wl-bernotok'
    10873           allow_undefined_flag=' $wl-berok'
    10874           if test yes = "$with_gnu_ld"; then
    10875             # We only use this code for GNU lds that support --whole-archive.
    10876             whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
    10877           else
    10878             # Exported symbols can be pulled into shared objects from archives
    10879             whole_archive_flag_spec='$convenience'
    10880           fi
    10881           archive_cmds_need_lc=yes
    10882           archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
    10883           # -brtl affects multiple linker settings, -berok does not and is overridden later
    10884           compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
    10885           if test svr4 != "$with_aix_soname"; then
    10886             # This is similar to how AIX traditionally builds its shared libraries.
    10887             archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
    10888           fi
    10889           if test aix != "$with_aix_soname"; then
    10890             archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
    10891           else
    10892             # used by -dlpreopen to get the symbols
    10893             archive_expsym_cmds="$archive_expsym_cmds"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
    10894           fi
    10895           archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
    10896         fi
    10897       fi
    10898       ;;
    10899 
    10900     amigaos*)
    10901       case $host_cpu in
    10902       powerpc)
    10903             # see comment about AmigaOS4 .so support
    10904             archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    10905             archive_expsym_cmds=''
    10906         ;;
    10907       m68k)
    10908             archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
    10909             hardcode_libdir_flag_spec='-L$libdir'
    10910             hardcode_minus_L=yes
    10911         ;;
    10912       esac
    10913       ;;
    10914 
    10915     bsdi[45]*)
    10916       export_dynamic_flag_spec=-rdynamic
    10917       ;;
    10918 
    10919     cygwin* | mingw* | pw32* | cegcc*)
    10920       # When not using gcc, we currently assume that we are using
    10921       # Microsoft Visual C++.
    10922       # hardcode_libdir_flag_spec is actually meaningless, as there is
    10923       # no search path for DLLs.
    10924       case $cc_basename in
    10925       cl*)
    10926         # Native MSVC
    10927         hardcode_libdir_flag_spec=' '
    10928         allow_undefined_flag=unsupported
    10929         always_export_symbols=yes
    10930         file_list_spec='@'
    10931         # Tell ltmain to make .lib files, not .a files.
    10932         libext=lib
    10933         # Tell ltmain to make .dll files, not .so files.
    10934         shrext_cmds=.dll
    10935         # FIXME: Setting linknames here is a bad hack.
    10936         archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
    10937         archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[   ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([     ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
    10938             cp "$export_symbols" "$output_objdir/$soname.def";
    10939             echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
    10940           else
    10941             $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
    10942           fi~
    10943           $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
    10944           linknames='
    10945         # The linker will not automatically build a static lib if we build a DLL.
    10946         # _LT_TAGVAR(old_archive_from_new_cmds, )='true'
    10947         enable_shared_with_static_runtimes=yes
    10948         exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
    10949         export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
    10950         # Don't use ranlib
    10951         old_postinstall_cmds='chmod 644 $oldlib'
    10952         postlink_cmds='lt_outputfile="@OUTPUT@"~
    10953           lt_tool_outputfile="@TOOL_OUTPUT@"~
    10954           case $lt_outputfile in
    10955             *.exe|*.EXE) ;;
    10956             *)
    10957               lt_outputfile=$lt_outputfile.exe
    10958               lt_tool_outputfile=$lt_tool_outputfile.exe
    10959               ;;
    10960           esac~
    10961           if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
    10962             $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
    10963             $RM "$lt_outputfile.manifest";
    10964           fi'
    10965         ;;
    10966       *)
    10967         # Assume MSVC wrapper
    10968         hardcode_libdir_flag_spec=' '
    10969         allow_undefined_flag=unsupported
    10970         # Tell ltmain to make .lib files, not .a files.
    10971         libext=lib
    10972         # Tell ltmain to make .dll files, not .so files.
    10973         shrext_cmds=.dll
    10974         # FIXME: Setting linknames here is a bad hack.
    10975         archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
    10976         # The linker will automatically build a .lib file if we build a DLL.
    10977         old_archive_from_new_cmds='true'
    10978         # FIXME: Should let the user specify the lib program.
    10979         old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
    10980         enable_shared_with_static_runtimes=yes
    10981         ;;
    10982       esac
    10983       ;;
    10984 
    10985     darwin* | rhapsody*)
    10986 
    10987 
    10988   archive_cmds_need_lc=no
    10989   hardcode_direct=no
    10990   hardcode_automatic=yes
    10991   hardcode_shlibpath_var=unsupported
    10992   if test yes = "$lt_cv_ld_force_load"; then
    10993     whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
    10994 
    10995   else
    10996     whole_archive_flag_spec=''
    10997   fi
    10998   link_all_deplibs=yes
    10999   allow_undefined_flag=$_lt_dar_allow_undefined
    11000   case $cc_basename in
    11001      ifort*|nagfor*) _lt_dar_can_shared=yes ;;
    11002      *) _lt_dar_can_shared=$GCC ;;
    11003   esac
    11004   if test yes = "$_lt_dar_can_shared"; then
    11005     output_verbose_link_cmd=func_echo_all
    11006     archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
    11007     module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
    11008     archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
    11009     module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
    11010 
    11011   else
    11012   ld_shlibs=no
    11013   fi
    11014 
    11015       ;;
    11016 
    11017     dgux*)
    11018       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11019       hardcode_libdir_flag_spec='-L$libdir'
    11020       hardcode_shlibpath_var=no
    11021       ;;
    11022 
    11023     # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
    11024     # support.  Future versions do this automatically, but an explicit c++rt0.o
    11025     # does not break anything, and helps significantly (at the cost of a little
    11026     # extra space).
    11027     freebsd2.2*)
    11028       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
    11029       hardcode_libdir_flag_spec='-R$libdir'
    11030       hardcode_direct=yes
    11031       hardcode_shlibpath_var=no
    11032       ;;
    11033 
    11034     # Unfortunately, older versions of FreeBSD 2 do not have this feature.
    11035     freebsd2.*)
    11036       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
    11037       hardcode_direct=yes
    11038       hardcode_minus_L=yes
    11039       hardcode_shlibpath_var=no
    11040       ;;
    11041 
    11042     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
    11043     freebsd* | dragonfly*)
    11044       archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
    11045       hardcode_libdir_flag_spec='-R$libdir'
    11046       hardcode_direct=yes
    11047       hardcode_shlibpath_var=no
    11048       ;;
    11049 
    11050     hpux9*)
    11051       if test yes = "$GCC"; then
    11052         archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
    11053       else
    11054         archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
    11055       fi
    11056       hardcode_libdir_flag_spec='$wl+b $wl$libdir'
    11057       hardcode_libdir_separator=:
    11058       hardcode_direct=yes
    11059 
    11060       # hardcode_minus_L: Not really in the search PATH,
    11061       # but as the default location of the library.
    11062       hardcode_minus_L=yes
    11063       export_dynamic_flag_spec='$wl-E'
    11064       ;;
    11065 
    11066     hpux10*)
    11067       if test yes,no = "$GCC,$with_gnu_ld"; then
    11068         archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
    11069       else
    11070         archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
    11071       fi
    11072       if test no = "$with_gnu_ld"; then
    11073         hardcode_libdir_flag_spec='$wl+b $wl$libdir'
    11074         hardcode_libdir_separator=:
    11075         hardcode_direct=yes
    11076         hardcode_direct_absolute=yes
    11077         export_dynamic_flag_spec='$wl-E'
    11078         # hardcode_minus_L: Not really in the search PATH,
    11079         # but as the default location of the library.
    11080         hardcode_minus_L=yes
    11081       fi
    11082       ;;
    11083 
    11084     hpux11*)
    11085       if test yes,no = "$GCC,$with_gnu_ld"; then
    11086         case $host_cpu in
    11087         hppa*64*)
    11088           archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
    11089           ;;
    11090         ia64*)
    11091           archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
    11092           ;;
    11093         *)
    11094           archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
    11095           ;;
    11096         esac
    11097       else
    11098         case $host_cpu in
    11099         hppa*64*)
    11100           archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
    11101           ;;
    11102         ia64*)
    11103           archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
    11104           ;;
    11105         *)
    11106 
    11107           # Older versions of the 11.00 compiler do not understand -b yet
    11108           # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
    11109           { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
    11110 $as_echo_n "checking if $CC understands -b... " >&6; }
    11111 if ${lt_cv_prog_compiler__b+:} false; then :
     5892fi
     5893{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5
     5894$as_echo "$ac_cv_func_alloca_works" >&6; }
     5895
     5896if test $ac_cv_func_alloca_works = yes; then
     5897
     5898$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h
     5899
     5900else
     5901  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
     5902# that cause trouble.  Some versions do not even contain alloca or
     5903# contain a buggy version.  If you still want to use their alloca,
     5904# use ar to extract alloca.o from them instead of compiling alloca.c.
     5905
     5906ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
     5907
     5908$as_echo "#define C_ALLOCA 1" >>confdefs.h
     5909
     5910
     5911{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5
     5912$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; }
     5913if ${ac_cv_os_cray+:} false; then :
    111125914  $as_echo_n "(cached) " >&6
    111135915else
    11114   lt_cv_prog_compiler__b=no
    11115    save_LDFLAGS=$LDFLAGS
    11116    LDFLAGS="$LDFLAGS -b"
    11117    echo "$lt_simple_link_test_code" > conftest.$ac_ext
    11118    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
    11119      # The linker can only warn and ignore the option if not recognized
    11120      # So say no if there are warnings
    11121      if test -s conftest.err; then
    11122        # Append any errors to the config.log.
    11123        cat conftest.err 1>&5
    11124        $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
    11125        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
    11126        if diff conftest.exp conftest.er2 >/dev/null; then
    11127          lt_cv_prog_compiler__b=yes
    11128        fi
    11129      else
    11130        lt_cv_prog_compiler__b=yes
    11131      fi
    11132    fi
    11133    $RM -r conftest*
    11134    LDFLAGS=$save_LDFLAGS
    11135 
    11136 fi
    11137 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
    11138 $as_echo "$lt_cv_prog_compiler__b" >&6; }
    11139 
    11140 if test yes = "$lt_cv_prog_compiler__b"; then
    11141     archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
    11142 else
    11143     archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
    11144 fi
    11145 
    11146           ;;
    11147         esac
    11148       fi
    11149       if test no = "$with_gnu_ld"; then
    11150         hardcode_libdir_flag_spec='$wl+b $wl$libdir'
    11151         hardcode_libdir_separator=:
    11152 
    11153         case $host_cpu in
    11154         hppa*64*|ia64*)
    11155           hardcode_direct=no
    11156           hardcode_shlibpath_var=no
    11157           ;;
    11158         *)
    11159           hardcode_direct=yes
    11160           hardcode_direct_absolute=yes
    11161           export_dynamic_flag_spec='$wl-E'
    11162 
    11163           # hardcode_minus_L: Not really in the search PATH,
    11164           # but as the default location of the library.
    11165           hardcode_minus_L=yes
    11166           ;;
    11167         esac
    11168       fi
    11169       ;;
    11170 
    11171     irix5* | irix6* | nonstopux*)
    11172       if test yes = "$GCC"; then
    11173         archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
    11174         # Try to use the -exported_symbol ld option, if it does not
    11175         # work, assume that -exports_file does not work either and
    11176         # implicitly export all symbols.
    11177         # This should be the same for all languages, so no per-tag cache variable.
    11178         { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
    11179 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
    11180 if ${lt_cv_irix_exported_symbol+:} false; then :
    11181   $as_echo_n "(cached) " >&6
    11182 else
    11183   save_LDFLAGS=$LDFLAGS
    11184            LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
    11185            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    11186 /* end confdefs.h.  */
    11187 int foo (void) { return 0; }
    11188 _ACEOF
    11189 if ac_fn_c_try_link "$LINENO"; then :
    11190   lt_cv_irix_exported_symbol=yes
    11191 else
    11192   lt_cv_irix_exported_symbol=no
    11193 fi
    11194 rm -f core conftest.err conftest.$ac_objext \
    11195     conftest$ac_exeext conftest.$ac_ext
    11196            LDFLAGS=$save_LDFLAGS
    11197 fi
    11198 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
    11199 $as_echo "$lt_cv_irix_exported_symbol" >&6; }
    11200         if test yes = "$lt_cv_irix_exported_symbol"; then
    11201           archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
    11202         fi
    11203         link_all_deplibs=no
    11204       else
    11205         archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
    11206         archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
    11207       fi
    11208       archive_cmds_need_lc='no'
    11209       hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
    11210       hardcode_libdir_separator=:
    11211       inherit_rpath=yes
    11212       link_all_deplibs=yes
    11213       ;;
    11214 
    11215     linux*)
    11216       case $cc_basename in
    11217       tcc*)
    11218         # Fabrice Bellard et al's Tiny C Compiler
    11219         ld_shlibs=yes
    11220         archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
    11221         ;;
    11222       esac
    11223       ;;
    11224 
    11225     netbsd* | netbsdelf*-gnu)
    11226       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
    11227         archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
    11228       else
    11229         archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
    11230       fi
    11231       hardcode_libdir_flag_spec='-R$libdir'
    11232       hardcode_direct=yes
    11233       hardcode_shlibpath_var=no
    11234       ;;
    11235 
    11236     newsos6)
    11237       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11238       hardcode_direct=yes
    11239       hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
    11240       hardcode_libdir_separator=:
    11241       hardcode_shlibpath_var=no
    11242       ;;
    11243 
    11244     *nto* | *qnx*)
    11245       ;;
    11246 
    11247     openbsd* | bitrig*)
    11248       if test -f /usr/libexec/ld.so; then
    11249         hardcode_direct=yes
    11250         hardcode_shlibpath_var=no
    11251         hardcode_direct_absolute=yes
    11252         if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
    11253           archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
    11254           archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
    11255           hardcode_libdir_flag_spec='$wl-rpath,$libdir'
    11256           export_dynamic_flag_spec='$wl-E'
    11257         else
    11258           archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
    11259           hardcode_libdir_flag_spec='$wl-rpath,$libdir'
    11260         fi
    11261       else
    11262         ld_shlibs=no
    11263       fi
    11264       ;;
    11265 
    11266     os2*)
    11267       hardcode_libdir_flag_spec='-L$libdir'
    11268       hardcode_minus_L=yes
    11269       allow_undefined_flag=unsupported
    11270       shrext_cmds=.dll
    11271       archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
    11272         $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
    11273         $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
    11274         $ECHO EXPORTS >> $output_objdir/$libname.def~
    11275         emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
    11276         $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
    11277         emximp -o $lib $output_objdir/$libname.def'
    11278       archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
    11279         $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
    11280         $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
    11281         $ECHO EXPORTS >> $output_objdir/$libname.def~
    11282         prefix_cmds="$SED"~
    11283         if test EXPORTS = "`$SED 1q $export_symbols`"; then
    11284           prefix_cmds="$prefix_cmds -e 1d";
    11285         fi~
    11286         prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
    11287         cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
    11288         $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
    11289         emximp -o $lib $output_objdir/$libname.def'
    11290       old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
    11291       enable_shared_with_static_runtimes=yes
    11292       ;;
    11293 
    11294     osf3*)
    11295       if test yes = "$GCC"; then
    11296         allow_undefined_flag=' $wl-expect_unresolved $wl\*'
    11297         archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
    11298       else
    11299         allow_undefined_flag=' -expect_unresolved \*'
    11300         archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
    11301       fi
    11302       archive_cmds_need_lc='no'
    11303       hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
    11304       hardcode_libdir_separator=:
    11305       ;;
    11306 
    11307     osf4* | osf5*)      # as osf3* with the addition of -msym flag
    11308       if test yes = "$GCC"; then
    11309         allow_undefined_flag=' $wl-expect_unresolved $wl\*'
    11310         archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
    11311         hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
    11312       else
    11313         allow_undefined_flag=' -expect_unresolved \*'
    11314         archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
    11315         archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
    11316           $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
    11317 
    11318         # Both c and cxx compiler support -rpath directly
    11319         hardcode_libdir_flag_spec='-rpath $libdir'
    11320       fi
    11321       archive_cmds_need_lc='no'
    11322       hardcode_libdir_separator=:
    11323       ;;
    11324 
    11325     solaris*)
    11326       no_undefined_flag=' -z defs'
    11327       if test yes = "$GCC"; then
    11328         wlarc='$wl'
    11329         archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
    11330         archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
    11331           $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
    11332       else
    11333         case `$CC -V 2>&1` in
    11334         *"Compilers 5.0"*)
    11335           wlarc=''
    11336           archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11337           archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
    11338             $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
    11339           ;;
    11340         *)
    11341           wlarc='$wl'
    11342           archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
    11343           archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
    11344             $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
    11345           ;;
    11346         esac
    11347       fi
    11348       hardcode_libdir_flag_spec='-R$libdir'
    11349       hardcode_shlibpath_var=no
    11350       case $host_os in
    11351       solaris2.[0-5] | solaris2.[0-5].*) ;;
    11352       *)
    11353         # The compiler driver will combine and reorder linker options,
    11354         # but understands '-z linker_flag'.  GCC discards it without '$wl',
    11355         # but is careful enough not to reorder.
    11356         # Supported since Solaris 2.6 (maybe 2.5.1?)
    11357         if test yes = "$GCC"; then
    11358           whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
    11359         else
    11360           whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
    11361         fi
    11362         ;;
    11363       esac
    11364       link_all_deplibs=yes
    11365       ;;
    11366 
    11367     sunos4*)
    11368       if test sequent = "$host_vendor"; then
    11369         # Use $CC to link under sequent, because it throws in some extra .o
    11370         # files that make .init and .fini sections work.
    11371         archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
    11372       else
    11373         archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
    11374       fi
    11375       hardcode_libdir_flag_spec='-L$libdir'
    11376       hardcode_direct=yes
    11377       hardcode_minus_L=yes
    11378       hardcode_shlibpath_var=no
    11379       ;;
    11380 
    11381     sysv4)
    11382       case $host_vendor in
    11383         sni)
    11384           archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11385           hardcode_direct=yes # is this really true???
    11386         ;;
    11387         siemens)
    11388           ## LD is ld it makes a PLAMLIB
    11389           ## CC just makes a GrossModule.
    11390           archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
    11391           reload_cmds='$CC -r -o $output$reload_objs'
    11392           hardcode_direct=no
    11393         ;;
    11394         motorola)
    11395           archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11396           hardcode_direct=no #Motorola manual says yes, but my tests say they lie
    11397         ;;
    11398       esac
    11399       runpath_var='LD_RUN_PATH'
    11400       hardcode_shlibpath_var=no
    11401       ;;
    11402 
    11403     sysv4.3*)
    11404       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11405       hardcode_shlibpath_var=no
    11406       export_dynamic_flag_spec='-Bexport'
    11407       ;;
    11408 
    11409     sysv4*MP*)
    11410       if test -d /usr/nec; then
    11411         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11412         hardcode_shlibpath_var=no
    11413         runpath_var=LD_RUN_PATH
    11414         hardcode_runpath_var=yes
    11415         ld_shlibs=yes
    11416       fi
    11417       ;;
    11418 
    11419     sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
    11420       no_undefined_flag='$wl-z,text'
    11421       archive_cmds_need_lc=no
    11422       hardcode_shlibpath_var=no
    11423       runpath_var='LD_RUN_PATH'
    11424 
    11425       if test yes = "$GCC"; then
    11426         archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11427         archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11428       else
    11429         archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11430         archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11431       fi
    11432       ;;
    11433 
    11434     sysv5* | sco3.2v5* | sco5v6*)
    11435       # Note: We CANNOT use -z defs as we might desire, because we do not
    11436       # link with -lc, and that would cause any symbols used from libc to
    11437       # always be unresolved, which means just about no library would
    11438       # ever link correctly.  If we're not using GNU ld we use -z text
    11439       # though, which does catch some bad symbols but isn't as heavy-handed
    11440       # as -z defs.
    11441       no_undefined_flag='$wl-z,text'
    11442       allow_undefined_flag='$wl-z,nodefs'
    11443       archive_cmds_need_lc=no
    11444       hardcode_shlibpath_var=no
    11445       hardcode_libdir_flag_spec='$wl-R,$libdir'
    11446       hardcode_libdir_separator=':'
    11447       link_all_deplibs=yes
    11448       export_dynamic_flag_spec='$wl-Bexport'
    11449       runpath_var='LD_RUN_PATH'
    11450 
    11451       if test yes = "$GCC"; then
    11452         archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11453         archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11454       else
    11455         archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11456         archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    11457       fi
    11458       ;;
    11459 
    11460     uts4*)
    11461       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
    11462       hardcode_libdir_flag_spec='-L$libdir'
    11463       hardcode_shlibpath_var=no
    11464       ;;
    11465 
    11466     *)
    11467       ld_shlibs=no
    11468       ;;
    11469     esac
    11470 
    11471     if test sni = "$host_vendor"; then
    11472       case $host in
    11473       sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
    11474         export_dynamic_flag_spec='$wl-Blargedynsym'
    11475         ;;
    11476       esac
    11477     fi
    11478   fi
    11479 
    11480 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
    11481 $as_echo "$ld_shlibs" >&6; }
    11482 test no = "$ld_shlibs" && can_build_shared=no
    11483 
    11484 with_gnu_ld=$with_gnu_ld
    11485 
    11486 
    11487 
    11488 
    11489 
    11490 
    11491 
    11492 
    11493 
    11494 
    11495 
    11496 
    11497 
    11498 
    11499 
    11500 #
    11501 # Do we need to explicitly link libc?
    11502 #
    11503 case "x$archive_cmds_need_lc" in
    11504 x|xyes)
    11505   # Assume -lc should be added
    11506   archive_cmds_need_lc=yes
    11507 
    11508   if test yes,yes = "$GCC,$enable_shared"; then
    11509     case $archive_cmds in
    11510     *'~'*)
    11511       # FIXME: we may have to deal with multi-command sequences.
    11512       ;;
    11513     '$CC '*)
    11514       # Test whether the compiler implicitly links with -lc since on some
    11515       # systems, -lgcc has to come before -lc. If gcc already passes -lc
    11516       # to ld, don't add -lc before -lgcc.
    11517       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
    11518 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
    11519 if ${lt_cv_archive_cmds_need_lc+:} false; then :
    11520   $as_echo_n "(cached) " >&6
    11521 else
    11522   $RM conftest*
    11523         echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    11524 
    11525         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    11526   (eval $ac_compile) 2>&5
    11527   ac_status=$?
    11528   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    11529   test $ac_status = 0; } 2>conftest.err; then
    11530           soname=conftest
    11531           lib=conftest
    11532           libobjs=conftest.$ac_objext
    11533           deplibs=
    11534           wl=$lt_prog_compiler_wl
    11535           pic_flag=$lt_prog_compiler_pic
    11536           compiler_flags=-v
    11537           linker_flags=-v
    11538           verstring=
    11539           output_objdir=.
    11540           libname=conftest
    11541           lt_save_allow_undefined_flag=$allow_undefined_flag
    11542           allow_undefined_flag=
    11543           if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
    11544   (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
    11545   ac_status=$?
    11546   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    11547   test $ac_status = 0; }
    11548           then
    11549             lt_cv_archive_cmds_need_lc=no
    11550           else
    11551             lt_cv_archive_cmds_need_lc=yes
    11552           fi
    11553           allow_undefined_flag=$lt_save_allow_undefined_flag
    11554         else
    11555           cat conftest.err 1>&5
    11556         fi
    11557         $RM conftest*
    11558 
    11559 fi
    11560 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
    11561 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
    11562       archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
    11563       ;;
    11564     esac
    11565   fi
    11566   ;;
    11567 esac
    11568 
    11569 
    11570 
    11571 
    11572 
    11573 
    11574 
    11575 
    11576 
    11577 
    11578 
    11579 
    11580 
    11581 
    11582 
    11583 
    11584 
    11585 
    11586 
    11587 
    11588 
    11589 
    11590 
    11591 
    11592 
    11593 
    11594 
    11595 
    11596 
    11597 
    11598 
    11599 
    11600 
    11601 
    11602 
    11603 
    11604 
    11605 
    11606 
    11607 
    11608 
    11609 
    11610 
    11611 
    11612 
    11613 
    11614 
    11615 
    11616 
    11617 
    11618 
    11619 
    11620 
    11621 
    11622 
    11623 
    11624 
    11625 
    11626 
    11627 
    11628 
    11629 
    11630 
    11631 
    11632 
    11633 
    11634 
    11635 
    11636 
    11637 
    11638 
    11639 
    11640 
    11641 
    11642 
    11643 
    11644 
    11645 
    11646 
    11647 
    11648 
    11649 
    11650 
    11651 
    11652 
    11653 
    11654 
    11655 
    11656 
    11657 
    11658 
    11659 
    11660 
    11661 
    11662 
    11663 
    11664 
    11665 
    11666 
    11667 
    11668 
    11669 
    11670 
    11671 
    11672 
    11673 
    11674 
    11675 
    11676 
    11677 
    11678 
    11679 
    11680 
    11681 
    11682 
    11683 
    11684 
    11685 
    11686 
    11687 
    11688 
    11689 
    11690 
    11691 
    11692 
    11693 
    11694 
    11695 
    11696 
    11697 
    11698 
    11699 
    11700 
    11701 
    11702 
    11703 
    11704 
    11705 
    11706 
    11707 
    11708 
    11709 
    11710 
    11711 
    11712 
    11713 
    11714 
    11715 
    11716 
    11717 
    11718 
    11719 
    11720   { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
    11721 $as_echo_n "checking dynamic linker characteristics... " >&6; }
    11722 
    11723 if test yes = "$GCC"; then
    11724   case $host_os in
    11725     darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
    11726     *) lt_awk_arg='/^libraries:/' ;;
    11727   esac
    11728   case $host_os in
    11729     mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
    11730     *) lt_sed_strip_eq='s|=/|/|g' ;;
    11731   esac
    11732   lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
    11733   case $lt_search_path_spec in
    11734   *\;*)
    11735     # if the path contains ";" then we assume it to be the separator
    11736     # otherwise default to the standard path separator (i.e. ":") - it is
    11737     # assumed that no part of a normal pathname contains ";" but that should
    11738     # okay in the real world where ";" in dirpaths is itself problematic.
    11739     lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
    11740     ;;
    11741   *)
    11742     lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
    11743     ;;
    11744   esac
    11745   # Ok, now we have the path, separated by spaces, we can step through it
    11746   # and add multilib dir if necessary...
    11747   lt_tmp_lt_search_path_spec=
    11748   lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
    11749   # ...but if some path component already ends with the multilib dir we assume
    11750   # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
    11751   case "$lt_multi_os_dir; $lt_search_path_spec " in
    11752   "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
    11753     lt_multi_os_dir=
    11754     ;;
    11755   esac
    11756   for lt_sys_path in $lt_search_path_spec; do
    11757     if test -d "$lt_sys_path$lt_multi_os_dir"; then
    11758       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
    11759     elif test -n "$lt_multi_os_dir"; then
    11760       test -d "$lt_sys_path" && \
    11761         lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
    11762     fi
    11763   done
    11764   lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
    11765 BEGIN {RS = " "; FS = "/|\n";} {
    11766   lt_foo = "";
    11767   lt_count = 0;
    11768   for (lt_i = NF; lt_i > 0; lt_i--) {
    11769     if ($lt_i != "" && $lt_i != ".") {
    11770       if ($lt_i == "..") {
    11771         lt_count++;
    11772       } else {
    11773         if (lt_count == 0) {
    11774           lt_foo = "/" $lt_i lt_foo;
    11775         } else {
    11776           lt_count--;
    11777         }
    11778       }
    11779     }
    11780   }
    11781   if (lt_foo != "") { lt_freq[lt_foo]++; }
    11782   if (lt_freq[lt_foo] == 1) { print lt_foo; }
    11783 }'`
    11784   # AWK program above erroneously prepends '/' to C:/dos/paths
    11785   # for these hosts.
    11786   case $host_os in
    11787     mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
    11788       $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
    11789   esac
    11790   sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
    11791 else
    11792   sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
    11793 fi
    11794 library_names_spec=
    11795 libname_spec='lib$name'
    11796 soname_spec=
    11797 shrext_cmds=.so
    11798 postinstall_cmds=
    11799 postuninstall_cmds=
    11800 finish_cmds=
    11801 finish_eval=
    11802 shlibpath_var=
    11803 shlibpath_overrides_runpath=unknown
    11804 version_type=none
    11805 dynamic_linker="$host_os ld.so"
    11806 sys_lib_dlsearch_path_spec="/lib /usr/lib"
    11807 need_lib_prefix=unknown
    11808 hardcode_into_libs=no
    11809 
    11810 # when you set need_version to no, make sure it does not cause -set_version
    11811 # flags to be left without arguments
    11812 need_version=unknown
    11813 
    11814 
    11815 
    11816 case $host_os in
    11817 aix3*)
    11818   version_type=linux # correct to gnu/linux during the next big refactor
    11819   library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
    11820   shlibpath_var=LIBPATH
    11821 
    11822   # AIX 3 has no versioning support, so we append a major version to the name.
    11823   soname_spec='$libname$release$shared_ext$major'
    11824   ;;
    11825 
    11826 aix[4-9]*)
    11827   version_type=linux # correct to gnu/linux during the next big refactor
    11828   need_lib_prefix=no
    11829   need_version=no
    11830   hardcode_into_libs=yes
    11831   if test ia64 = "$host_cpu"; then
    11832     # AIX 5 supports IA64
    11833     library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
    11834     shlibpath_var=LD_LIBRARY_PATH
    11835   else
    11836     # With GCC up to 2.95.x, collect2 would create an import file
    11837     # for dependence libraries.  The import file would start with
    11838     # the line '#! .'.  This would cause the generated library to
    11839     # depend on '.', always an invalid library.  This was fixed in
    11840     # development snapshots of GCC prior to 3.0.
    11841     case $host_os in
    11842       aix4 | aix4.[01] | aix4.[01].*)
    11843       if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
    11844            echo ' yes '
    11845            echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
    11846         :
    11847       else
    11848         can_build_shared=no
    11849       fi
    11850       ;;
    11851     esac
    11852     # Using Import Files as archive members, it is possible to support
    11853     # filename-based versioning of shared library archives on AIX. While
    11854     # this would work for both with and without runtime linking, it will
    11855     # prevent static linking of such archives. So we do filename-based
    11856     # shared library versioning with .so extension only, which is used
    11857     # when both runtime linking and shared linking is enabled.
    11858     # Unfortunately, runtime linking may impact performance, so we do
    11859     # not want this to be the default eventually. Also, we use the
    11860     # versioned .so libs for executables only if there is the -brtl
    11861     # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
    11862     # To allow for filename-based versioning support, we need to create
    11863     # libNAME.so.V as an archive file, containing:
    11864     # *) an Import File, referring to the versioned filename of the
    11865     #    archive as well as the shared archive member, telling the
    11866     #    bitwidth (32 or 64) of that shared object, and providing the
    11867     #    list of exported symbols of that shared object, eventually
    11868     #    decorated with the 'weak' keyword
    11869     # *) the shared object with the F_LOADONLY flag set, to really avoid
    11870     #    it being seen by the linker.
    11871     # At run time we better use the real file rather than another symlink,
    11872     # but for link time we create the symlink libNAME.so -> libNAME.so.V
    11873 
    11874     case $with_aix_soname,$aix_use_runtimelinking in
    11875     # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
    11876     # soname into executable. Probably we can add versioning support to
    11877     # collect2, so additional links can be useful in future.
    11878     aix,yes) # traditional libtool
    11879       dynamic_linker='AIX unversionable lib.so'
    11880       # If using run time linking (on AIX 4.2 or later) use lib<name>.so
    11881       # instead of lib<name>.a to let people know that these are not
    11882       # typical AIX shared libraries.
    11883       library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    11884       ;;
    11885     aix,no) # traditional AIX only
    11886       dynamic_linker='AIX lib.a(lib.so.V)'
    11887       # We preserve .a as extension for shared libraries through AIX4.2
    11888       # and later when we are not doing run time linking.
    11889       library_names_spec='$libname$release.a $libname.a'
    11890       soname_spec='$libname$release$shared_ext$major'
    11891       ;;
    11892     svr4,*) # full svr4 only
    11893       dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
    11894       library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
    11895       # We do not specify a path in Import Files, so LIBPATH fires.
    11896       shlibpath_overrides_runpath=yes
    11897       ;;
    11898     *,yes) # both, prefer svr4
    11899       dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
    11900       library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
    11901       # unpreferred sharedlib libNAME.a needs extra handling
    11902       postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
    11903       postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
    11904       # We do not specify a path in Import Files, so LIBPATH fires.
    11905       shlibpath_overrides_runpath=yes
    11906       ;;
    11907     *,no) # both, prefer aix
    11908       dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
    11909       library_names_spec='$libname$release.a $libname.a'
    11910       soname_spec='$libname$release$shared_ext$major'
    11911       # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
    11912       postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
    11913       postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
    11914       ;;
    11915     esac
    11916     shlibpath_var=LIBPATH
    11917   fi
    11918   ;;
    11919 
    11920 amigaos*)
    11921   case $host_cpu in
    11922   powerpc)
    11923     # Since July 2007 AmigaOS4 officially supports .so libraries.
    11924     # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
    11925     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    11926     ;;
    11927   m68k)
    11928     library_names_spec='$libname.ixlibrary $libname.a'
    11929     # Create ${libname}_ixlibrary.a entries in /sys/libs.
    11930     finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
    11931     ;;
    11932   esac
    11933   ;;
    11934 
    11935 beos*)
    11936   library_names_spec='$libname$shared_ext'
    11937   dynamic_linker="$host_os ld.so"
    11938   shlibpath_var=LIBRARY_PATH
    11939   ;;
    11940 
    11941 bsdi[45]*)
    11942   version_type=linux # correct to gnu/linux during the next big refactor
    11943   need_version=no
    11944   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    11945   soname_spec='$libname$release$shared_ext$major'
    11946   finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
    11947   shlibpath_var=LD_LIBRARY_PATH
    11948   sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
    11949   sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
    11950   # the default ld.so.conf also contains /usr/contrib/lib and
    11951   # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
    11952   # libtool to hard-code these into programs
    11953   ;;
    11954 
    11955 cygwin* | mingw* | pw32* | cegcc*)
    11956   version_type=windows
    11957   shrext_cmds=.dll
    11958   need_version=no
    11959   need_lib_prefix=no
    11960 
    11961   case $GCC,$cc_basename in
    11962   yes,*)
    11963     # gcc
    11964     library_names_spec='$libname.dll.a'
    11965     # DLL is installed to $(libdir)/../bin by postinstall_cmds
    11966     postinstall_cmds='base_file=`basename \$file`~
    11967       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
    11968       dldir=$destdir/`dirname \$dlpath`~
    11969       test -d \$dldir || mkdir -p \$dldir~
    11970       $install_prog $dir/$dlname \$dldir/$dlname~
    11971       chmod a+x \$dldir/$dlname~
    11972       if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
    11973         eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
    11974       fi'
    11975     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
    11976       dlpath=$dir/\$dldll~
    11977        $RM \$dlpath'
    11978     shlibpath_overrides_runpath=yes
    11979 
    11980     case $host_os in
    11981     cygwin*)
    11982       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
    11983       soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    11984 
    11985       sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
    11986       ;;
    11987     mingw* | cegcc*)
    11988       # MinGW DLLs use traditional 'lib' prefix
    11989       soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    11990       ;;
    11991     pw32*)
    11992       # pw32 DLLs use 'pw' prefix rather than 'lib'
    11993       library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    11994       ;;
    11995     esac
    11996     dynamic_linker='Win32 ld.exe'
    11997     ;;
    11998 
    11999   *,cl*)
    12000     # Native MSVC
    12001     libname_spec='$name'
    12002     soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    12003     library_names_spec='$libname.dll.lib'
    12004 
    12005     case $build_os in
    12006     mingw*)
    12007       sys_lib_search_path_spec=
    12008       lt_save_ifs=$IFS
    12009       IFS=';'
    12010       for lt_path in $LIB
    12011       do
    12012         IFS=$lt_save_ifs
    12013         # Let DOS variable expansion print the short 8.3 style file name.
    12014         lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
    12015         sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
    12016       done
    12017       IFS=$lt_save_ifs
    12018       # Convert to MSYS style.
    12019       sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
    12020       ;;
    12021     cygwin*)
    12022       # Convert to unix form, then to dos form, then back to unix form
    12023       # but this time dos style (no spaces!) so that the unix form looks
    12024       # like /cygdrive/c/PROGRA~1:/cygdr...
    12025       sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
    12026       sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
    12027       sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
    12028       ;;
    12029     *)
    12030       sys_lib_search_path_spec=$LIB
    12031       if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
    12032         # It is most probably a Windows format PATH.
    12033         sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
    12034       else
    12035         sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
    12036       fi
    12037       # FIXME: find the short name or the path components, as spaces are
    12038       # common. (e.g. "Program Files" -> "PROGRA~1")
    12039       ;;
    12040     esac
    12041 
    12042     # DLL is installed to $(libdir)/../bin by postinstall_cmds
    12043     postinstall_cmds='base_file=`basename \$file`~
    12044       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
    12045       dldir=$destdir/`dirname \$dlpath`~
    12046       test -d \$dldir || mkdir -p \$dldir~
    12047       $install_prog $dir/$dlname \$dldir/$dlname'
    12048     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
    12049       dlpath=$dir/\$dldll~
    12050        $RM \$dlpath'
    12051     shlibpath_overrides_runpath=yes
    12052     dynamic_linker='Win32 link.exe'
    12053     ;;
    12054 
    12055   *)
    12056     # Assume MSVC wrapper
    12057     library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
    12058     dynamic_linker='Win32 ld.exe'
    12059     ;;
    12060   esac
    12061   # FIXME: first we should search . and the directory the executable is in
    12062   shlibpath_var=PATH
    12063   ;;
    12064 
    12065 darwin* | rhapsody*)
    12066   dynamic_linker="$host_os dyld"
    12067   version_type=darwin
    12068   need_lib_prefix=no
    12069   need_version=no
    12070   library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
    12071   soname_spec='$libname$release$major$shared_ext'
    12072   shlibpath_overrides_runpath=yes
    12073   shlibpath_var=DYLD_LIBRARY_PATH
    12074   shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
    12075 
    12076   sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
    12077   sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
    12078   ;;
    12079 
    12080 dgux*)
    12081   version_type=linux # correct to gnu/linux during the next big refactor
    12082   need_lib_prefix=no
    12083   need_version=no
    12084   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12085   soname_spec='$libname$release$shared_ext$major'
    12086   shlibpath_var=LD_LIBRARY_PATH
    12087   ;;
    12088 
    12089 freebsd* | dragonfly*)
    12090   # DragonFly does not have aout.  When/if they implement a new
    12091   # versioning mechanism, adjust this.
    12092   if test -x /usr/bin/objformat; then
    12093     objformat=`/usr/bin/objformat`
    12094   else
    12095     case $host_os in
    12096     freebsd[23].*) objformat=aout ;;
    12097     *) objformat=elf ;;
    12098     esac
    12099   fi
    12100   version_type=freebsd-$objformat
    12101   case $version_type in
    12102     freebsd-elf*)
    12103       library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12104       soname_spec='$libname$release$shared_ext$major'
    12105       need_version=no
    12106       need_lib_prefix=no
    12107       ;;
    12108     freebsd-*)
    12109       library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    12110       need_version=yes
    12111       ;;
    12112   esac
    12113   shlibpath_var=LD_LIBRARY_PATH
    12114   case $host_os in
    12115   freebsd2.*)
    12116     shlibpath_overrides_runpath=yes
    12117     ;;
    12118   freebsd3.[01]* | freebsdelf3.[01]*)
    12119     shlibpath_overrides_runpath=yes
    12120     hardcode_into_libs=yes
    12121     ;;
    12122   freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
    12123   freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
    12124     shlibpath_overrides_runpath=no
    12125     hardcode_into_libs=yes
    12126     ;;
    12127   *) # from 4.6 on, and DragonFly
    12128     shlibpath_overrides_runpath=yes
    12129     hardcode_into_libs=yes
    12130     ;;
    12131   esac
    12132   ;;
    12133 
    12134 haiku*)
    12135   version_type=linux # correct to gnu/linux during the next big refactor
    12136   need_lib_prefix=no
    12137   need_version=no
    12138   dynamic_linker="$host_os runtime_loader"
    12139   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12140   soname_spec='$libname$release$shared_ext$major'
    12141   shlibpath_var=LIBRARY_PATH
    12142   shlibpath_overrides_runpath=no
    12143   sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
    12144   hardcode_into_libs=yes
    12145   ;;
    12146 
    12147 hpux9* | hpux10* | hpux11*)
    12148   # Give a soname corresponding to the major version so that dld.sl refuses to
    12149   # link against other versions.
    12150   version_type=sunos
    12151   need_lib_prefix=no
    12152   need_version=no
    12153   case $host_cpu in
    12154   ia64*)
    12155     shrext_cmds='.so'
    12156     hardcode_into_libs=yes
    12157     dynamic_linker="$host_os dld.so"
    12158     shlibpath_var=LD_LIBRARY_PATH
    12159     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
    12160     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12161     soname_spec='$libname$release$shared_ext$major'
    12162     if test 32 = "$HPUX_IA64_MODE"; then
    12163       sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
    12164       sys_lib_dlsearch_path_spec=/usr/lib/hpux32
    12165     else
    12166       sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
    12167       sys_lib_dlsearch_path_spec=/usr/lib/hpux64
    12168     fi
    12169     ;;
    12170   hppa*64*)
    12171     shrext_cmds='.sl'
    12172     hardcode_into_libs=yes
    12173     dynamic_linker="$host_os dld.sl"
    12174     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
    12175     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
    12176     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12177     soname_spec='$libname$release$shared_ext$major'
    12178     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
    12179     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
    12180     ;;
    12181   *)
    12182     shrext_cmds='.sl'
    12183     dynamic_linker="$host_os dld.sl"
    12184     shlibpath_var=SHLIB_PATH
    12185     shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
    12186     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12187     soname_spec='$libname$release$shared_ext$major'
    12188     ;;
    12189   esac
    12190   # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
    12191   postinstall_cmds='chmod 555 $lib'
    12192   # or fails outright, so override atomically:
    12193   install_override_mode=555
    12194   ;;
    12195 
    12196 interix[3-9]*)
    12197   version_type=linux # correct to gnu/linux during the next big refactor
    12198   need_lib_prefix=no
    12199   need_version=no
    12200   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12201   soname_spec='$libname$release$shared_ext$major'
    12202   dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
    12203   shlibpath_var=LD_LIBRARY_PATH
    12204   shlibpath_overrides_runpath=no
    12205   hardcode_into_libs=yes
    12206   ;;
    12207 
    12208 irix5* | irix6* | nonstopux*)
    12209   case $host_os in
    12210     nonstopux*) version_type=nonstopux ;;
    12211     *)
    12212         if test yes = "$lt_cv_prog_gnu_ld"; then
    12213                 version_type=linux # correct to gnu/linux during the next big refactor
    12214         else
    12215                 version_type=irix
    12216         fi ;;
    12217   esac
    12218   need_lib_prefix=no
    12219   need_version=no
    12220   soname_spec='$libname$release$shared_ext$major'
    12221   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
    12222   case $host_os in
    12223   irix5* | nonstopux*)
    12224     libsuff= shlibsuff=
    12225     ;;
    12226   *)
    12227     case $LD in # libtool.m4 will add one of these switches to LD
    12228     *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
    12229       libsuff= shlibsuff= libmagic=32-bit;;
    12230     *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
    12231       libsuff=32 shlibsuff=N32 libmagic=N32;;
    12232     *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
    12233       libsuff=64 shlibsuff=64 libmagic=64-bit;;
    12234     *) libsuff= shlibsuff= libmagic=never-match;;
    12235     esac
    12236     ;;
    12237   esac
    12238   shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
    12239   shlibpath_overrides_runpath=no
    12240   sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
    12241   sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
    12242   hardcode_into_libs=yes
    12243   ;;
    12244 
    12245 # No shared lib support for Linux oldld, aout, or coff.
    12246 linux*oldld* | linux*aout* | linux*coff*)
    12247   dynamic_linker=no
    12248   ;;
    12249 
    12250 linux*android*)
    12251   version_type=none # Android doesn't support versioned libraries.
    12252   need_lib_prefix=no
    12253   need_version=no
    12254   library_names_spec='$libname$release$shared_ext'
    12255   soname_spec='$libname$release$shared_ext'
    12256   finish_cmds=
    12257   shlibpath_var=LD_LIBRARY_PATH
    12258   shlibpath_overrides_runpath=yes
    12259 
    12260   # This implies no fast_install, which is unacceptable.
    12261   # Some rework will be needed to allow for fast_install
    12262   # before this can be enabled.
    12263   hardcode_into_libs=yes
    12264 
    12265   dynamic_linker='Android linker'
    12266   # Don't embed -rpath directories since the linker doesn't support them.
    12267   hardcode_libdir_flag_spec='-L$libdir'
    12268   ;;
    12269 
    12270 # This must be glibc/ELF.
    12271 linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    12272   version_type=linux # correct to gnu/linux during the next big refactor
    12273   need_lib_prefix=no
    12274   need_version=no
    12275   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12276   soname_spec='$libname$release$shared_ext$major'
    12277   finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
    12278   shlibpath_var=LD_LIBRARY_PATH
    12279   shlibpath_overrides_runpath=no
    12280 
    12281   # Some binutils ld are patched to set DT_RUNPATH
    12282   if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
    12283   $as_echo_n "(cached) " >&6
    12284 else
    12285   lt_cv_shlibpath_overrides_runpath=no
    12286     save_LDFLAGS=$LDFLAGS
    12287     save_libdir=$libdir
    12288     eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
    12289          LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
    12290     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    12291 /* end confdefs.h.  */
    12292 
    12293 int
    12294 main ()
    12295 {
    12296 
    12297   ;
    12298   return 0;
    12299 }
    12300 _ACEOF
    12301 if ac_fn_c_try_link "$LINENO"; then :
    12302   if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
    12303   lt_cv_shlibpath_overrides_runpath=yes
    12304 fi
    12305 fi
    12306 rm -f core conftest.err conftest.$ac_objext \
    12307     conftest$ac_exeext conftest.$ac_ext
    12308     LDFLAGS=$save_LDFLAGS
    12309     libdir=$save_libdir
    12310 
    12311 fi
    12312 
    12313   shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
    12314 
    12315   # This implies no fast_install, which is unacceptable.
    12316   # Some rework will be needed to allow for fast_install
    12317   # before this can be enabled.
    12318   hardcode_into_libs=yes
    12319 
    12320   # Ideally, we could use ldconfig to report *all* directores which are
    12321   # searched for libraries, however this is still not possible.  Aside from not
    12322   # being certain /sbin/ldconfig is available, command
    12323   # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
    12324   # even though it is searched at run-time.  Try to do the best guess by
    12325   # appending ld.so.conf contents (and includes) to the search path.
    12326   if test -f /etc/ld.so.conf; then
    12327     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[       ]*hwcap[        ]/d;s/[:,      ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
    12328     sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
    12329   fi
    12330 
    12331   # We used to test for /lib/ld.so.1 and disable shared libraries on
    12332   # powerpc, because MkLinux only supported shared libraries with the
    12333   # GNU dynamic linker.  Since this was broken with cross compilers,
    12334   # most powerpc-linux boxes support dynamic linking these days and
    12335   # people can always --disable-shared, the test was removed, and we
    12336   # assume the GNU/Linux dynamic linker is in use.
    12337   dynamic_linker='GNU/Linux ld.so'
    12338   ;;
    12339 
    12340 netbsdelf*-gnu)
    12341   version_type=linux
    12342   need_lib_prefix=no
    12343   need_version=no
    12344   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
    12345   soname_spec='${libname}${release}${shared_ext}$major'
    12346   shlibpath_var=LD_LIBRARY_PATH
    12347   shlibpath_overrides_runpath=no
    12348   hardcode_into_libs=yes
    12349   dynamic_linker='NetBSD ld.elf_so'
    12350   ;;
    12351 
    12352 netbsd*)
    12353   version_type=sunos
    12354   need_lib_prefix=no
    12355   need_version=no
    12356   if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
    12357     library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    12358     finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
    12359     dynamic_linker='NetBSD (a.out) ld.so'
    12360   else
    12361     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12362     soname_spec='$libname$release$shared_ext$major'
    12363     dynamic_linker='NetBSD ld.elf_so'
    12364   fi
    12365   shlibpath_var=LD_LIBRARY_PATH
    12366   shlibpath_overrides_runpath=yes
    12367   hardcode_into_libs=yes
    12368   ;;
    12369 
    12370 newsos6)
    12371   version_type=linux # correct to gnu/linux during the next big refactor
    12372   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12373   shlibpath_var=LD_LIBRARY_PATH
    12374   shlibpath_overrides_runpath=yes
    12375   ;;
    12376 
    12377 *nto* | *qnx*)
    12378   version_type=qnx
    12379   need_lib_prefix=no
    12380   need_version=no
    12381   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12382   soname_spec='$libname$release$shared_ext$major'
    12383   shlibpath_var=LD_LIBRARY_PATH
    12384   shlibpath_overrides_runpath=no
    12385   hardcode_into_libs=yes
    12386   dynamic_linker='ldqnx.so'
    12387   ;;
    12388 
    12389 openbsd* | bitrig*)
    12390   version_type=sunos
    12391   sys_lib_dlsearch_path_spec=/usr/lib
    12392   need_lib_prefix=no
    12393   if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
    12394     need_version=no
    12395   else
    12396     need_version=yes
    12397   fi
    12398   library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    12399   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
    12400   shlibpath_var=LD_LIBRARY_PATH
    12401   shlibpath_overrides_runpath=yes
    12402   ;;
    12403 
    12404 os2*)
    12405   libname_spec='$name'
    12406   version_type=windows
    12407   shrext_cmds=.dll
    12408   need_version=no
    12409   need_lib_prefix=no
    12410   # OS/2 can only load a DLL with a base name of 8 characters or less.
    12411   soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
    12412     v=$($ECHO $release$versuffix | tr -d .-);
    12413     n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
    12414     $ECHO $n$v`$shared_ext'
    12415   library_names_spec='${libname}_dll.$libext'
    12416   dynamic_linker='OS/2 ld.exe'
    12417   shlibpath_var=BEGINLIBPATH
    12418   sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
    12419   sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
    12420   postinstall_cmds='base_file=`basename \$file`~
    12421     dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
    12422     dldir=$destdir/`dirname \$dlpath`~
    12423     test -d \$dldir || mkdir -p \$dldir~
    12424     $install_prog $dir/$dlname \$dldir/$dlname~
    12425     chmod a+x \$dldir/$dlname~
    12426     if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
    12427       eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
    12428     fi'
    12429   postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
    12430     dlpath=$dir/\$dldll~
    12431     $RM \$dlpath'
    12432   ;;
    12433 
    12434 osf3* | osf4* | osf5*)
    12435   version_type=osf
    12436   need_lib_prefix=no
    12437   need_version=no
    12438   soname_spec='$libname$release$shared_ext$major'
    12439   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12440   shlibpath_var=LD_LIBRARY_PATH
    12441   sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
    12442   sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
    12443   ;;
    12444 
    12445 rdos*)
    12446   dynamic_linker=no
    12447   ;;
    12448 
    12449 solaris*)
    12450   version_type=linux # correct to gnu/linux during the next big refactor
    12451   need_lib_prefix=no
    12452   need_version=no
    12453   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12454   soname_spec='$libname$release$shared_ext$major'
    12455   shlibpath_var=LD_LIBRARY_PATH
    12456   shlibpath_overrides_runpath=yes
    12457   hardcode_into_libs=yes
    12458   # ldd complains unless libraries are executable
    12459   postinstall_cmds='chmod +x $lib'
    12460   ;;
    12461 
    12462 sunos4*)
    12463   version_type=sunos
    12464   library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    12465   finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
    12466   shlibpath_var=LD_LIBRARY_PATH
    12467   shlibpath_overrides_runpath=yes
    12468   if test yes = "$with_gnu_ld"; then
    12469     need_lib_prefix=no
    12470   fi
    12471   need_version=yes
    12472   ;;
    12473 
    12474 sysv4 | sysv4.3*)
    12475   version_type=linux # correct to gnu/linux during the next big refactor
    12476   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12477   soname_spec='$libname$release$shared_ext$major'
    12478   shlibpath_var=LD_LIBRARY_PATH
    12479   case $host_vendor in
    12480     sni)
    12481       shlibpath_overrides_runpath=no
    12482       need_lib_prefix=no
    12483       runpath_var=LD_RUN_PATH
    12484       ;;
    12485     siemens)
    12486       need_lib_prefix=no
    12487       ;;
    12488     motorola)
    12489       need_lib_prefix=no
    12490       need_version=no
    12491       shlibpath_overrides_runpath=no
    12492       sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
    12493       ;;
    12494   esac
    12495   ;;
    12496 
    12497 sysv4*MP*)
    12498   if test -d /usr/nec; then
    12499     version_type=linux # correct to gnu/linux during the next big refactor
    12500     library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
    12501     soname_spec='$libname$shared_ext.$major'
    12502     shlibpath_var=LD_LIBRARY_PATH
    12503   fi
    12504   ;;
    12505 
    12506 sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
    12507   version_type=sco
    12508   need_lib_prefix=no
    12509   need_version=no
    12510   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
    12511   soname_spec='$libname$release$shared_ext$major'
    12512   shlibpath_var=LD_LIBRARY_PATH
    12513   shlibpath_overrides_runpath=yes
    12514   hardcode_into_libs=yes
    12515   if test yes = "$with_gnu_ld"; then
    12516     sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
    12517   else
    12518     sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
    12519     case $host_os in
    12520       sco3.2v5*)
    12521         sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
    12522         ;;
    12523     esac
    12524   fi
    12525   sys_lib_dlsearch_path_spec='/usr/lib'
    12526   ;;
    12527 
    12528 tpf*)
    12529   # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
    12530   version_type=linux # correct to gnu/linux during the next big refactor
    12531   need_lib_prefix=no
    12532   need_version=no
    12533   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12534   shlibpath_var=LD_LIBRARY_PATH
    12535   shlibpath_overrides_runpath=no
    12536   hardcode_into_libs=yes
    12537   ;;
    12538 
    12539 uts4*)
    12540   version_type=linux # correct to gnu/linux during the next big refactor
    12541   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    12542   soname_spec='$libname$release$shared_ext$major'
    12543   shlibpath_var=LD_LIBRARY_PATH
    12544   ;;
    12545 
    12546 *)
    12547   dynamic_linker=no
    12548   ;;
    12549 esac
    12550 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
    12551 $as_echo "$dynamic_linker" >&6; }
    12552 test no = "$dynamic_linker" && can_build_shared=no
    12553 
    12554 variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
    12555 if test yes = "$GCC"; then
    12556   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
    12557 fi
    12558 
    12559 if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
    12560   sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
    12561 fi
    12562 
    12563 if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
    12564   sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
    12565 fi
    12566 
    12567 # remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
    12568 configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
    12569 
    12570 # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
    12571 func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
    12572 
    12573 # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
    12574 configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
    12575 
    12576 
    12577 
    12578 
    12579 
    12580 
    12581 
    12582 
    12583 
    12584 
    12585 
    12586 
    12587 
    12588 
    12589 
    12590 
    12591 
    12592 
    12593 
    12594 
    12595 
    12596 
    12597 
    12598 
    12599 
    12600 
    12601 
    12602 
    12603 
    12604 
    12605 
    12606 
    12607 
    12608 
    12609 
    12610 
    12611 
    12612 
    12613 
    12614 
    12615 
    12616 
    12617 
    12618 
    12619 
    12620 
    12621 
    12622 
    12623 
    12624 
    12625 
    12626 
    12627 
    12628 
    12629 
    12630 
    12631 
    12632 
    12633 
    12634 
    12635 
    12636 
    12637 
    12638 
    12639 
    12640 
    12641 
    12642 
    12643 
    12644 
    12645 
    12646 
    12647 
    12648 
    12649 
    12650 
    12651 
    12652 
    12653 
    12654 
    12655 
    12656 
    12657 
    12658 
    12659 
    12660 
    12661 
    12662 
    12663 
    12664 
    12665 
    12666 
    12667 
    12668 
    12669 
    12670 
    12671 
    12672   { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
    12673 $as_echo_n "checking how to hardcode library paths into programs... " >&6; }
    12674 hardcode_action=
    12675 if test -n "$hardcode_libdir_flag_spec" ||
    12676    test -n "$runpath_var" ||
    12677    test yes = "$hardcode_automatic"; then
    12678 
    12679   # We can hardcode non-existent directories.
    12680   if test no != "$hardcode_direct" &&
    12681      # If the only mechanism to avoid hardcoding is shlibpath_var, we
    12682      # have to relink, otherwise we might link with an installed library
    12683      # when we should be linking with a yet-to-be-installed one
    12684      ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
    12685      test no != "$hardcode_minus_L"; then
    12686     # Linking always hardcodes the temporary library directory.
    12687     hardcode_action=relink
    12688   else
    12689     # We can link without hardcoding, and we can hardcode nonexisting dirs.
    12690     hardcode_action=immediate
    12691   fi
    12692 else
    12693   # We cannot hardcode anything, or else we can only hardcode existing
    12694   # directories.
    12695   hardcode_action=unsupported
    12696 fi
    12697 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
    12698 $as_echo "$hardcode_action" >&6; }
    12699 
    12700 if test relink = "$hardcode_action" ||
    12701    test yes = "$inherit_rpath"; then
    12702   # Fast installation is not supported
    12703   enable_fast_install=no
    12704 elif test yes = "$shlibpath_overrides_runpath" ||
    12705      test no = "$enable_shared"; then
    12706   # Fast installation is not necessary
    12707   enable_fast_install=needless
    12708 fi
    12709 
    12710 
    12711 
    12712 
    12713 
    12714 
    12715   if test yes != "$enable_dlopen"; then
    12716   enable_dlopen=unknown
    12717   enable_dlopen_self=unknown
    12718   enable_dlopen_self_static=unknown
    12719 else
    12720   lt_cv_dlopen=no
    12721   lt_cv_dlopen_libs=
    12722 
    12723   case $host_os in
    12724   beos*)
    12725     lt_cv_dlopen=load_add_on
    12726     lt_cv_dlopen_libs=
    12727     lt_cv_dlopen_self=yes
    12728     ;;
    12729 
    12730   mingw* | pw32* | cegcc*)
    12731     lt_cv_dlopen=LoadLibrary
    12732     lt_cv_dlopen_libs=
    12733     ;;
    12734 
    12735   cygwin*)
    12736     lt_cv_dlopen=dlopen
    12737     lt_cv_dlopen_libs=
    12738     ;;
    12739 
    12740   darwin*)
    12741     # if libdl is installed we need to link against it
    12742     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
    12743 $as_echo_n "checking for dlopen in -ldl... " >&6; }
    12744 if ${ac_cv_lib_dl_dlopen+:} false; then :
    12745   $as_echo_n "(cached) " >&6
    12746 else
    12747   ac_check_lib_save_LIBS=$LIBS
    12748 LIBS="-ldl  $LIBS"
    12749 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    12750 /* end confdefs.h.  */
    12751 
    12752 /* Override any GCC internal prototype to avoid an error.
    12753    Use char because int might match the return type of a GCC
    12754    builtin and then its argument prototype would still apply.  */
    12755 #ifdef __cplusplus
    12756 extern "C"
    12757 #endif
    12758 char dlopen ();
    12759 int
    12760 main ()
    12761 {
    12762 return dlopen ();
    12763   ;
    12764   return 0;
    12765 }
    12766 _ACEOF
    12767 if ac_fn_c_try_link "$LINENO"; then :
    12768   ac_cv_lib_dl_dlopen=yes
    12769 else
    12770   ac_cv_lib_dl_dlopen=no
    12771 fi
    12772 rm -f core conftest.err conftest.$ac_objext \
    12773     conftest$ac_exeext conftest.$ac_ext
    12774 LIBS=$ac_check_lib_save_LIBS
    12775 fi
    12776 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
    12777 $as_echo "$ac_cv_lib_dl_dlopen" >&6; }
    12778 if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
    12779   lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
    12780 else
    12781 
    12782     lt_cv_dlopen=dyld
    12783     lt_cv_dlopen_libs=
    12784     lt_cv_dlopen_self=yes
    12785 
    12786 fi
    12787 
    12788     ;;
    12789 
    12790   tpf*)
    12791     # Don't try to run any link tests for TPF.  We know it's impossible
    12792     # because TPF is a cross-compiler, and we know how we open DSOs.
    12793     lt_cv_dlopen=dlopen
    12794     lt_cv_dlopen_libs=
    12795     lt_cv_dlopen_self=no
    12796     ;;
    12797 
    12798   *)
    12799     ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
    12800 if test "x$ac_cv_func_shl_load" = xyes; then :
    12801   lt_cv_dlopen=shl_load
    12802 else
    12803   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
    12804 $as_echo_n "checking for shl_load in -ldld... " >&6; }
    12805 if ${ac_cv_lib_dld_shl_load+:} false; then :
    12806   $as_echo_n "(cached) " >&6
    12807 else
    12808   ac_check_lib_save_LIBS=$LIBS
    12809 LIBS="-ldld  $LIBS"
    12810 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    12811 /* end confdefs.h.  */
    12812 
    12813 /* Override any GCC internal prototype to avoid an error.
    12814    Use char because int might match the return type of a GCC
    12815    builtin and then its argument prototype would still apply.  */
    12816 #ifdef __cplusplus
    12817 extern "C"
    12818 #endif
    12819 char shl_load ();
    12820 int
    12821 main ()
    12822 {
    12823 return shl_load ();
    12824   ;
    12825   return 0;
    12826 }
    12827 _ACEOF
    12828 if ac_fn_c_try_link "$LINENO"; then :
    12829   ac_cv_lib_dld_shl_load=yes
    12830 else
    12831   ac_cv_lib_dld_shl_load=no
    12832 fi
    12833 rm -f core conftest.err conftest.$ac_objext \
    12834     conftest$ac_exeext conftest.$ac_ext
    12835 LIBS=$ac_check_lib_save_LIBS
    12836 fi
    12837 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
    12838 $as_echo "$ac_cv_lib_dld_shl_load" >&6; }
    12839 if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
    12840   lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
    12841 else
    12842   ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
    12843 if test "x$ac_cv_func_dlopen" = xyes; then :
    12844   lt_cv_dlopen=dlopen
    12845 else
    12846   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
    12847 $as_echo_n "checking for dlopen in -ldl... " >&6; }
    12848 if ${ac_cv_lib_dl_dlopen+:} false; then :
    12849   $as_echo_n "(cached) " >&6
    12850 else
    12851   ac_check_lib_save_LIBS=$LIBS
    12852 LIBS="-ldl  $LIBS"
    12853 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    12854 /* end confdefs.h.  */
    12855 
    12856 /* Override any GCC internal prototype to avoid an error.
    12857    Use char because int might match the return type of a GCC
    12858    builtin and then its argument prototype would still apply.  */
    12859 #ifdef __cplusplus
    12860 extern "C"
    12861 #endif
    12862 char dlopen ();
    12863 int
    12864 main ()
    12865 {
    12866 return dlopen ();
    12867   ;
    12868   return 0;
    12869 }
    12870 _ACEOF
    12871 if ac_fn_c_try_link "$LINENO"; then :
    12872   ac_cv_lib_dl_dlopen=yes
    12873 else
    12874   ac_cv_lib_dl_dlopen=no
    12875 fi
    12876 rm -f core conftest.err conftest.$ac_objext \
    12877     conftest$ac_exeext conftest.$ac_ext
    12878 LIBS=$ac_check_lib_save_LIBS
    12879 fi
    12880 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
    12881 $as_echo "$ac_cv_lib_dl_dlopen" >&6; }
    12882 if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
    12883   lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
    12884 else
    12885   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
    12886 $as_echo_n "checking for dlopen in -lsvld... " >&6; }
    12887 if ${ac_cv_lib_svld_dlopen+:} false; then :
    12888   $as_echo_n "(cached) " >&6
    12889 else
    12890   ac_check_lib_save_LIBS=$LIBS
    12891 LIBS="-lsvld  $LIBS"
    12892 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    12893 /* end confdefs.h.  */
    12894 
    12895 /* Override any GCC internal prototype to avoid an error.
    12896    Use char because int might match the return type of a GCC
    12897    builtin and then its argument prototype would still apply.  */
    12898 #ifdef __cplusplus
    12899 extern "C"
    12900 #endif
    12901 char dlopen ();
    12902 int
    12903 main ()
    12904 {
    12905 return dlopen ();
    12906   ;
    12907   return 0;
    12908 }
    12909 _ACEOF
    12910 if ac_fn_c_try_link "$LINENO"; then :
    12911   ac_cv_lib_svld_dlopen=yes
    12912 else
    12913   ac_cv_lib_svld_dlopen=no
    12914 fi
    12915 rm -f core conftest.err conftest.$ac_objext \
    12916     conftest$ac_exeext conftest.$ac_ext
    12917 LIBS=$ac_check_lib_save_LIBS
    12918 fi
    12919 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
    12920 $as_echo "$ac_cv_lib_svld_dlopen" >&6; }
    12921 if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
    12922   lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
    12923 else
    12924   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
    12925 $as_echo_n "checking for dld_link in -ldld... " >&6; }
    12926 if ${ac_cv_lib_dld_dld_link+:} false; then :
    12927   $as_echo_n "(cached) " >&6
    12928 else
    12929   ac_check_lib_save_LIBS=$LIBS
    12930 LIBS="-ldld  $LIBS"
    12931 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    12932 /* end confdefs.h.  */
    12933 
    12934 /* Override any GCC internal prototype to avoid an error.
    12935    Use char because int might match the return type of a GCC
    12936    builtin and then its argument prototype would still apply.  */
    12937 #ifdef __cplusplus
    12938 extern "C"
    12939 #endif
    12940 char dld_link ();
    12941 int
    12942 main ()
    12943 {
    12944 return dld_link ();
    12945   ;
    12946   return 0;
    12947 }
    12948 _ACEOF
    12949 if ac_fn_c_try_link "$LINENO"; then :
    12950   ac_cv_lib_dld_dld_link=yes
    12951 else
    12952   ac_cv_lib_dld_dld_link=no
    12953 fi
    12954 rm -f core conftest.err conftest.$ac_objext \
    12955     conftest$ac_exeext conftest.$ac_ext
    12956 LIBS=$ac_check_lib_save_LIBS
    12957 fi
    12958 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
    12959 $as_echo "$ac_cv_lib_dld_dld_link" >&6; }
    12960 if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
    12961   lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
    12962 fi
    12963 
    12964 
    12965 fi
    12966 
    12967 
    12968 fi
    12969 
    12970 
    12971 fi
    12972 
    12973 
    12974 fi
    12975 
    12976 
    12977 fi
    12978 
    12979     ;;
    12980   esac
    12981 
    12982   if test no = "$lt_cv_dlopen"; then
    12983     enable_dlopen=no
    12984   else
    12985     enable_dlopen=yes
    12986   fi
    12987 
    12988   case $lt_cv_dlopen in
    12989   dlopen)
    12990     save_CPPFLAGS=$CPPFLAGS
    12991     test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
    12992 
    12993     save_LDFLAGS=$LDFLAGS
    12994     wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
    12995 
    12996     save_LIBS=$LIBS
    12997     LIBS="$lt_cv_dlopen_libs $LIBS"
    12998 
    12999     { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
    13000 $as_echo_n "checking whether a program can dlopen itself... " >&6; }
    13001 if ${lt_cv_dlopen_self+:} false; then :
    13002   $as_echo_n "(cached) " >&6
    13003 else
    13004           if test yes = "$cross_compiling"; then :
    13005   lt_cv_dlopen_self=cross
    13006 else
    13007   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    13008   lt_status=$lt_dlunknown
    13009   cat > conftest.$ac_ext <<_LT_EOF
    13010 #line $LINENO "configure"
    13011 #include "confdefs.h"
    13012 
    13013 #if HAVE_DLFCN_H
    13014 #include <dlfcn.h>
    13015 #endif
    13016 
    13017 #include <stdio.h>
    13018 
    13019 #ifdef RTLD_GLOBAL
    13020 #  define LT_DLGLOBAL           RTLD_GLOBAL
    13021 #else
    13022 #  ifdef DL_GLOBAL
    13023 #    define LT_DLGLOBAL         DL_GLOBAL
    13024 #  else
    13025 #    define LT_DLGLOBAL         0
    13026 #  endif
    13027 #endif
    13028 
    13029 /* We may have to define LT_DLLAZY_OR_NOW in the command line if we
    13030    find out it does not work in some platform. */
    13031 #ifndef LT_DLLAZY_OR_NOW
    13032 #  ifdef RTLD_LAZY
    13033 #    define LT_DLLAZY_OR_NOW            RTLD_LAZY
    13034 #  else
    13035 #    ifdef DL_LAZY
    13036 #      define LT_DLLAZY_OR_NOW          DL_LAZY
    13037 #    else
    13038 #      ifdef RTLD_NOW
    13039 #        define LT_DLLAZY_OR_NOW        RTLD_NOW
    13040 #      else
    13041 #        ifdef DL_NOW
    13042 #          define LT_DLLAZY_OR_NOW      DL_NOW
    13043 #        else
    13044 #          define LT_DLLAZY_OR_NOW      0
    13045 #        endif
    13046 #      endif
    13047 #    endif
    13048 #  endif
    13049 #endif
    13050 
    13051 /* When -fvisibility=hidden is used, assume the code has been annotated
    13052    correspondingly for the symbols needed.  */
    13053 #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
    13054 int fnord () __attribute__((visibility("default")));
    13055 #endif
    13056 
    13057 int fnord () { return 42; }
    13058 int main ()
    13059 {
    13060   void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
    13061   int status = $lt_dlunknown;
    13062 
    13063   if (self)
    13064     {
    13065       if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
    13066       else
    13067         {
    13068           if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
    13069           else puts (dlerror ());
    13070         }
    13071       /* dlclose (self); */
    13072     }
    13073   else
    13074     puts (dlerror ());
    13075 
    13076   return status;
    13077 }
    13078 _LT_EOF
    13079   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
    13080   (eval $ac_link) 2>&5
    13081   ac_status=$?
    13082   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    13083   test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
    13084     (./conftest; exit; ) >&5 2>/dev/null
    13085     lt_status=$?
    13086     case x$lt_status in
    13087       x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
    13088       x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
    13089       x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
    13090     esac
    13091   else :
    13092     # compilation failed
    13093     lt_cv_dlopen_self=no
    13094   fi
    13095 fi
    13096 rm -fr conftest*
    13097 
    13098 
    13099 fi
    13100 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
    13101 $as_echo "$lt_cv_dlopen_self" >&6; }
    13102 
    13103     if test yes = "$lt_cv_dlopen_self"; then
    13104       wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
    13105       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
    13106 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
    13107 if ${lt_cv_dlopen_self_static+:} false; then :
    13108   $as_echo_n "(cached) " >&6
    13109 else
    13110           if test yes = "$cross_compiling"; then :
    13111   lt_cv_dlopen_self_static=cross
    13112 else
    13113   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
    13114   lt_status=$lt_dlunknown
    13115   cat > conftest.$ac_ext <<_LT_EOF
    13116 #line $LINENO "configure"
    13117 #include "confdefs.h"
    13118 
    13119 #if HAVE_DLFCN_H
    13120 #include <dlfcn.h>
    13121 #endif
    13122 
    13123 #include <stdio.h>
    13124 
    13125 #ifdef RTLD_GLOBAL
    13126 #  define LT_DLGLOBAL           RTLD_GLOBAL
    13127 #else
    13128 #  ifdef DL_GLOBAL
    13129 #    define LT_DLGLOBAL         DL_GLOBAL
    13130 #  else
    13131 #    define LT_DLGLOBAL         0
    13132 #  endif
    13133 #endif
    13134 
    13135 /* We may have to define LT_DLLAZY_OR_NOW in the command line if we
    13136    find out it does not work in some platform. */
    13137 #ifndef LT_DLLAZY_OR_NOW
    13138 #  ifdef RTLD_LAZY
    13139 #    define LT_DLLAZY_OR_NOW            RTLD_LAZY
    13140 #  else
    13141 #    ifdef DL_LAZY
    13142 #      define LT_DLLAZY_OR_NOW          DL_LAZY
    13143 #    else
    13144 #      ifdef RTLD_NOW
    13145 #        define LT_DLLAZY_OR_NOW        RTLD_NOW
    13146 #      else
    13147 #        ifdef DL_NOW
    13148 #          define LT_DLLAZY_OR_NOW      DL_NOW
    13149 #        else
    13150 #          define LT_DLLAZY_OR_NOW      0
    13151 #        endif
    13152 #      endif
    13153 #    endif
    13154 #  endif
    13155 #endif
    13156 
    13157 /* When -fvisibility=hidden is used, assume the code has been annotated
    13158    correspondingly for the symbols needed.  */
    13159 #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
    13160 int fnord () __attribute__((visibility("default")));
    13161 #endif
    13162 
    13163 int fnord () { return 42; }
    13164 int main ()
    13165 {
    13166   void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
    13167   int status = $lt_dlunknown;
    13168 
    13169   if (self)
    13170     {
    13171       if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
    13172       else
    13173         {
    13174           if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
    13175           else puts (dlerror ());
    13176         }
    13177       /* dlclose (self); */
    13178     }
    13179   else
    13180     puts (dlerror ());
    13181 
    13182   return status;
    13183 }
    13184 _LT_EOF
    13185   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
    13186   (eval $ac_link) 2>&5
    13187   ac_status=$?
    13188   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    13189   test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
    13190     (./conftest; exit; ) >&5 2>/dev/null
    13191     lt_status=$?
    13192     case x$lt_status in
    13193       x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
    13194       x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
    13195       x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
    13196     esac
    13197   else :
    13198     # compilation failed
    13199     lt_cv_dlopen_self_static=no
    13200   fi
    13201 fi
    13202 rm -fr conftest*
    13203 
    13204 
    13205 fi
    13206 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
    13207 $as_echo "$lt_cv_dlopen_self_static" >&6; }
    13208     fi
    13209 
    13210     CPPFLAGS=$save_CPPFLAGS
    13211     LDFLAGS=$save_LDFLAGS
    13212     LIBS=$save_LIBS
    13213     ;;
    13214   esac
    13215 
    13216   case $lt_cv_dlopen_self in
    13217   yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
    13218   *) enable_dlopen_self=unknown ;;
    13219   esac
    13220 
    13221   case $lt_cv_dlopen_self_static in
    13222   yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
    13223   *) enable_dlopen_self_static=unknown ;;
    13224   esac
    13225 fi
    13226 
    13227 
    13228 
    13229 
    13230 
    13231 
    13232 
    13233 
    13234 
    13235 
    13236 
    13237 
    13238 
    13239 
    13240 
    13241 
    13242 
    13243 striplib=
    13244 old_striplib=
    13245 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
    13246 $as_echo_n "checking whether stripping libraries is possible... " >&6; }
    13247 if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
    13248   test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
    13249   test -z "$striplib" && striplib="$STRIP --strip-unneeded"
    13250   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
    13251 $as_echo "yes" >&6; }
    13252 else
    13253 # FIXME - insert some real tests, host_os isn't really good enough
    13254   case $host_os in
    13255   darwin*)
    13256     if test -n "$STRIP"; then
    13257       striplib="$STRIP -x"
    13258       old_striplib="$STRIP -S"
    13259       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
    13260 $as_echo "yes" >&6; }
    13261     else
    13262       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    13263 $as_echo "no" >&6; }
    13264     fi
    13265     ;;
    13266   *)
    13267     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    13268 $as_echo "no" >&6; }
    13269     ;;
    13270   esac
    13271 fi
    13272 
    13273 
    13274 
    13275 
    13276 
    13277 
    13278 
    13279 
    13280 
    13281 
    13282 
    13283 
    13284   # Report what library types will actually be built
    13285   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
    13286 $as_echo_n "checking if libtool supports shared libraries... " >&6; }
    13287   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
    13288 $as_echo "$can_build_shared" >&6; }
    13289 
    13290   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
    13291 $as_echo_n "checking whether to build shared libraries... " >&6; }
    13292   test no = "$can_build_shared" && enable_shared=no
    13293 
    13294   # On AIX, shared libraries and static libraries use the same namespace, and
    13295   # are all built from PIC.
    13296   case $host_os in
    13297   aix3*)
    13298     test yes = "$enable_shared" && enable_static=no
    13299     if test -n "$RANLIB"; then
    13300       archive_cmds="$archive_cmds~\$RANLIB \$lib"
    13301       postinstall_cmds='$RANLIB $lib'
    13302     fi
    13303     ;;
    13304 
    13305   aix[4-9]*)
    13306     if test ia64 != "$host_cpu"; then
    13307       case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
    13308       yes,aix,yes) ;;                   # shared object as lib.so file only
    13309       yes,svr4,*) ;;                    # shared object as lib.so archive member only
    13310       yes,*) enable_static=no ;;        # shared object in lib.a archive as well
    13311       esac
    13312     fi
    13313     ;;
    13314   esac
    13315   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
    13316 $as_echo "$enable_shared" >&6; }
    13317 
    13318   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
    13319 $as_echo_n "checking whether to build static libraries... " >&6; }
    13320   # Make sure either enable_shared or enable_static is yes.
    13321   test yes = "$enable_shared" || enable_static=yes
    13322   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
    13323 $as_echo "$enable_static" >&6; }
    13324 
    13325 
    13326 
    13327 
    13328 fi
    13329 ac_ext=c
    13330 ac_cpp='$CPP $CPPFLAGS'
    13331 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    13332 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    13333 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    13334 
    13335 CC=$lt_save_CC
    13336 
    13337       if test -n "$CXX" && ( test no != "$CXX" &&
    13338     ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
    13339     (test g++ != "$CXX"))); then
    13340   ac_ext=cpp
    13341 ac_cpp='$CXXCPP $CPPFLAGS'
    13342 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    13343 ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    13344 ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
    13345 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
    13346 $as_echo_n "checking how to run the C++ preprocessor... " >&6; }
    13347 if test -z "$CXXCPP"; then
    13348   if ${ac_cv_prog_CXXCPP+:} false; then :
    13349   $as_echo_n "(cached) " >&6
    13350 else
    13351       # Double quotes because CXXCPP needs to be expanded
    13352     for CXXCPP in "$CXX -E" "/lib/cpp"
    13353     do
    13354       ac_preproc_ok=false
    13355 for ac_cxx_preproc_warn_flag in '' yes
    13356 do
    13357   # Use a header file that comes with gcc, so configuring glibc
    13358   # with a fresh cross-compiler works.
    13359   # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    13360   # <limits.h> exists even on freestanding compilers.
    13361   # On the NeXT, cc -E runs the code through the compiler's parser,
    13362   # not just through cpp. "Syntax error" is here to catch this case.
    133635916  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    133645917/* end confdefs.h.  */
    13365 #ifdef __STDC__
    13366 # include <limits.h>
     5918#if defined CRAY && ! defined CRAY2
     5919webecray
    133675920#else
    13368 # include <assert.h>
     5921wenotbecray
    133695922#endif
    13370                      Syntax error
    13371 _ACEOF
    13372 if ac_fn_cxx_try_cpp "$LINENO"; then :
    13373 
    13374 else
    13375   # Broken: fails on valid input.
    13376 continue
    13377 fi
    13378 rm -f conftest.err conftest.i conftest.$ac_ext
    13379 
    13380   # OK, works on sane cases.  Now check whether nonexistent headers
    13381   # can be detected and how.
     5923
     5924_ACEOF
     5925if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
     5926  $EGREP "webecray" >/dev/null 2>&1; then :
     5927  ac_cv_os_cray=yes
     5928else
     5929  ac_cv_os_cray=no
     5930fi
     5931rm -f conftest*
     5932
     5933fi
     5934{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
     5935$as_echo "$ac_cv_os_cray" >&6; }
     5936if test $ac_cv_os_cray = yes; then
     5937  for ac_func in _getb67 GETB67 getb67; do
     5938    as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
     5939ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
     5940if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
     5941
     5942cat >>confdefs.h <<_ACEOF
     5943#define CRAY_STACKSEG_END $ac_func
     5944_ACEOF
     5945
     5946    break
     5947fi
     5948
     5949  done
     5950fi
     5951
     5952{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
     5953$as_echo_n "checking stack direction for C alloca... " >&6; }
     5954if ${ac_cv_c_stack_direction+:} false; then :
     5955  $as_echo_n "(cached) " >&6
     5956else
     5957  if test "$cross_compiling" = yes; then :
     5958  ac_cv_c_stack_direction=0
     5959else
    133825960  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    133835961/* end confdefs.h.  */
    13384 #include <ac_nonexistent.h>
    13385 _ACEOF
    13386 if ac_fn_cxx_try_cpp "$LINENO"; then :
    13387   # Broken: success on invalid input.
    13388 continue
    13389 else
    13390   # Passes both tests.
    13391 ac_preproc_ok=:
    13392 break
    13393 fi
    13394 rm -f conftest.err conftest.i conftest.$ac_ext
    13395 
    13396 done
    13397 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
    13398 rm -f conftest.i conftest.err conftest.$ac_ext
    13399 if $ac_preproc_ok; then :
    13400   break
    13401 fi
    13402 
    13403     done
    13404     ac_cv_prog_CXXCPP=$CXXCPP
    13405 
    13406 fi
    13407   CXXCPP=$ac_cv_prog_CXXCPP
    13408 else
    13409   ac_cv_prog_CXXCPP=$CXXCPP
    13410 fi
    13411 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
    13412 $as_echo "$CXXCPP" >&6; }
    13413 ac_preproc_ok=false
    13414 for ac_cxx_preproc_warn_flag in '' yes
    13415 do
    13416   # Use a header file that comes with gcc, so configuring glibc
    13417   # with a fresh cross-compiler works.
    13418   # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    13419   # <limits.h> exists even on freestanding compilers.
    13420   # On the NeXT, cc -E runs the code through the compiler's parser,
    13421   # not just through cpp. "Syntax error" is here to catch this case.
    13422   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    13423 /* end confdefs.h.  */
    13424 #ifdef __STDC__
    13425 # include <limits.h>
    13426 #else
    13427 # include <assert.h>
    13428 #endif
    13429                      Syntax error
    13430 _ACEOF
    13431 if ac_fn_cxx_try_cpp "$LINENO"; then :
    13432 
    13433 else
    13434   # Broken: fails on valid input.
    13435 continue
    13436 fi
    13437 rm -f conftest.err conftest.i conftest.$ac_ext
    13438 
    13439   # OK, works on sane cases.  Now check whether nonexistent headers
    13440   # can be detected and how.
    13441   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    13442 /* end confdefs.h.  */
    13443 #include <ac_nonexistent.h>
    13444 _ACEOF
    13445 if ac_fn_cxx_try_cpp "$LINENO"; then :
    13446   # Broken: success on invalid input.
    13447 continue
    13448 else
    13449   # Passes both tests.
    13450 ac_preproc_ok=:
    13451 break
    13452 fi
    13453 rm -f conftest.err conftest.i conftest.$ac_ext
    13454 
    13455 done
    13456 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
    13457 rm -f conftest.i conftest.err conftest.$ac_ext
    13458 if $ac_preproc_ok; then :
    13459 
    13460 else
    13461   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
    13462 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
    13463 as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
    13464 See \`config.log' for more details" "$LINENO" 5; }
    13465 fi
    13466 
    13467 ac_ext=c
    13468 ac_cpp='$CPP $CPPFLAGS'
    13469 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    13470 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    13471 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    13472 
    13473 else
    13474   _lt_caught_CXX_error=yes
    13475 fi
    13476 
    13477 ac_ext=cpp
    13478 ac_cpp='$CXXCPP $CPPFLAGS'
    13479 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    13480 ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    13481 ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
    13482 
    13483 archive_cmds_need_lc_CXX=no
    13484 allow_undefined_flag_CXX=
    13485 always_export_symbols_CXX=no
    13486 archive_expsym_cmds_CXX=
    13487 compiler_needs_object_CXX=no
    13488 export_dynamic_flag_spec_CXX=
    13489 hardcode_direct_CXX=no
    13490 hardcode_direct_absolute_CXX=no
    13491 hardcode_libdir_flag_spec_CXX=
    13492 hardcode_libdir_separator_CXX=
    13493 hardcode_minus_L_CXX=no
    13494 hardcode_shlibpath_var_CXX=unsupported
    13495 hardcode_automatic_CXX=no
    13496 inherit_rpath_CXX=no
    13497 module_cmds_CXX=
    13498 module_expsym_cmds_CXX=
    13499 link_all_deplibs_CXX=unknown
    13500 old_archive_cmds_CXX=$old_archive_cmds
    13501 reload_flag_CXX=$reload_flag
    13502 reload_cmds_CXX=$reload_cmds
    13503 no_undefined_flag_CXX=
    13504 whole_archive_flag_spec_CXX=
    13505 enable_shared_with_static_runtimes_CXX=no
    13506 
    13507 # Source file extension for C++ test sources.
    13508 ac_ext=cpp
    13509 
    13510 # Object file extension for compiled C++ test sources.
    13511 objext=o
    13512 objext_CXX=$objext
    13513 
    13514 # No sense in running all these tests if we already determined that
    13515 # the CXX compiler isn't working.  Some variables (like enable_shared)
    13516 # are currently assumed to apply to all compilers on this platform,
    13517 # and will be corrupted by setting them based on a non-working compiler.
    13518 if test yes != "$_lt_caught_CXX_error"; then
    13519   # Code to be used in simple compile tests
    13520   lt_simple_compile_test_code="int some_variable = 0;"
    13521 
    13522   # Code to be used in simple link tests
    13523   lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
    13524 
    13525   # ltmain only uses $CC for tagged configurations so make sure $CC is set.
    13526 
    13527 
    13528 
    13529 
    13530 
    13531 
    13532 # If no C compiler was specified, use CC.
    13533 LTCC=${LTCC-"$CC"}
    13534 
    13535 # If no C compiler flags were specified, use CFLAGS.
    13536 LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
    13537 
    13538 # Allow CC to be a program name with arguments.
    13539 compiler=$CC
    13540 
    13541 
    13542   # save warnings/boilerplate of simple test code
    13543   ac_outfile=conftest.$ac_objext
    13544 echo "$lt_simple_compile_test_code" >conftest.$ac_ext
    13545 eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
    13546 _lt_compiler_boilerplate=`cat conftest.err`
    13547 $RM conftest*
    13548 
    13549   ac_outfile=conftest.$ac_objext
    13550 echo "$lt_simple_link_test_code" >conftest.$ac_ext
    13551 eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
    13552 _lt_linker_boilerplate=`cat conftest.err`
    13553 $RM -r conftest*
    13554 
    13555 
    13556   # Allow CC to be a program name with arguments.
    13557   lt_save_CC=$CC
    13558   lt_save_CFLAGS=$CFLAGS
    13559   lt_save_LD=$LD
    13560   lt_save_GCC=$GCC
    13561   GCC=$GXX
    13562   lt_save_with_gnu_ld=$with_gnu_ld
    13563   lt_save_path_LD=$lt_cv_path_LD
    13564   if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
    13565     lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
    13566   else
    13567     $as_unset lt_cv_prog_gnu_ld
    13568   fi
    13569   if test -n "${lt_cv_path_LDCXX+set}"; then
    13570     lt_cv_path_LD=$lt_cv_path_LDCXX
    13571   else
    13572     $as_unset lt_cv_path_LD
    13573   fi
    13574   test -z "${LDCXX+set}" || LD=$LDCXX
    13575   CC=${CXX-"c++"}
    13576   CFLAGS=$CXXFLAGS
    13577   compiler=$CC
    13578   compiler_CXX=$CC
    13579   func_cc_basename $compiler
    13580 cc_basename=$func_cc_basename_result
    13581 
    13582 
    13583   if test -n "$compiler"; then
    13584     # We don't want -fno-exception when compiling C++ code, so set the
    13585     # no_builtin_flag separately
    13586     if test yes = "$GXX"; then
    13587       lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
    13588     else
    13589       lt_prog_compiler_no_builtin_flag_CXX=
    13590     fi
    13591 
    13592     if test yes = "$GXX"; then
    13593       # Set up default GNU C++ configuration
    13594 
    13595 
    13596 
    13597 # Check whether --with-gnu-ld was given.
    13598 if test "${with_gnu_ld+set}" = set; then :
    13599   withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
    13600 else
    13601   with_gnu_ld=no
    13602 fi
    13603 
    13604 ac_prog=ld
    13605 if test yes = "$GCC"; then
    13606   # Check if gcc -print-prog-name=ld gives a path.
    13607   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
    13608 $as_echo_n "checking for ld used by $CC... " >&6; }
    13609   case $host in
    13610   *-*-mingw*)
    13611     # gcc leaves a trailing carriage return, which upsets mingw
    13612     ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
    13613   *)
    13614     ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
    13615   esac
    13616   case $ac_prog in
    13617     # Accept absolute paths.
    13618     [\\/]* | ?:[\\/]*)
    13619       re_direlt='/[^/][^/]*/\.\./'
    13620       # Canonicalize the pathname of ld
    13621       ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
    13622       while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
    13623         ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
    13624       done
    13625       test -z "$LD" && LD=$ac_prog
    13626       ;;
    13627   "")
    13628     # If it fails, then pretend we aren't using GCC.
    13629     ac_prog=ld
    13630     ;;
    13631   *)
    13632     # If it is relative, then search for the first ld in PATH.
    13633     with_gnu_ld=unknown
    13634     ;;
    13635   esac
    13636 elif test yes = "$with_gnu_ld"; then
    13637   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
    13638 $as_echo_n "checking for GNU ld... " >&6; }
    13639 else
    13640   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
    13641 $as_echo_n "checking for non-GNU ld... " >&6; }
    13642 fi
    13643 if ${lt_cv_path_LD+:} false; then :
    13644   $as_echo_n "(cached) " >&6
    13645 else
    13646   if test -z "$LD"; then
    13647   lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
    13648   for ac_dir in $PATH; do
    13649     IFS=$lt_save_ifs
    13650     test -z "$ac_dir" && ac_dir=.
    13651     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
    13652       lt_cv_path_LD=$ac_dir/$ac_prog
    13653       # Check to see if the program is GNU ld.  I'd rather use --version,
    13654       # but apparently some variants of GNU ld only accept -v.
    13655       # Break only if it was the GNU/non-GNU ld that we prefer.
    13656       case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
    13657       *GNU* | *'with BFD'*)
    13658         test no != "$with_gnu_ld" && break
    13659         ;;
    13660       *)
    13661         test yes != "$with_gnu_ld" && break
    13662         ;;
    13663       esac
    13664     fi
    13665   done
    13666   IFS=$lt_save_ifs
    13667 else
    13668   lt_cv_path_LD=$LD # Let the user override the test with a path.
    13669 fi
    13670 fi
    13671 
    13672 LD=$lt_cv_path_LD
    13673 if test -n "$LD"; then
    13674   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
    13675 $as_echo "$LD" >&6; }
    13676 else
    13677   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    13678 $as_echo "no" >&6; }
    13679 fi
    13680 test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
    13681 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
    13682 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
    13683 if ${lt_cv_prog_gnu_ld+:} false; then :
    13684   $as_echo_n "(cached) " >&6
    13685 else
    13686   # I'd rather use --version here, but apparently some GNU lds only accept -v.
    13687 case `$LD -v 2>&1 </dev/null` in
    13688 *GNU* | *'with BFD'*)
    13689   lt_cv_prog_gnu_ld=yes
    13690   ;;
    13691 *)
    13692   lt_cv_prog_gnu_ld=no
    13693   ;;
    13694 esac
    13695 fi
    13696 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
    13697 $as_echo "$lt_cv_prog_gnu_ld" >&6; }
    13698 with_gnu_ld=$lt_cv_prog_gnu_ld
    13699 
    13700 
    13701 
    13702 
    13703 
    13704 
    13705 
    13706       # Check if GNU C++ uses GNU ld as the underlying linker, since the
    13707       # archiving commands below assume that GNU ld is being used.
    13708       if test yes = "$with_gnu_ld"; then
    13709         archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
    13710         archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    13711 
    13712         hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
    13713         export_dynamic_flag_spec_CXX='$wl--export-dynamic'
    13714 
    13715         # If archive_cmds runs LD, not CC, wlarc should be empty
    13716         # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
    13717         #     investigate it a little bit more. (MM)
    13718         wlarc='$wl'
    13719 
    13720         # ancient GNU ld didn't support --whole-archive et. al.
    13721         if eval "`$CC -print-prog-name=ld` --help 2>&1" |
    13722           $GREP 'no-whole-archive' > /dev/null; then
    13723           whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
    13724         else
    13725           whole_archive_flag_spec_CXX=
    13726         fi
    13727       else
    13728         with_gnu_ld=no
    13729         wlarc=
    13730 
    13731         # A generic and very simple default shared library creation
    13732         # command for GNU C++ for the case where it uses the native
    13733         # linker, instead of GNU ld.  If possible, this setting should
    13734         # overridden to take advantage of the native linker features on
    13735         # the platform it is being used on.
    13736         archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
    13737       fi
    13738 
    13739       # Commands to make compiler produce verbose output that lists
    13740       # what "hidden" libraries, object files and flags are used when
    13741       # linking a shared library.
    13742       output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
    13743 
    13744     else
    13745       GXX=no
    13746       with_gnu_ld=no
    13747       wlarc=
    13748     fi
    13749 
    13750     # PORTME: fill in a description of your system's C++ link characteristics
    13751     { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
    13752 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
    13753     ld_shlibs_CXX=yes
    13754     case $host_os in
    13755       aix3*)
    13756         # FIXME: insert proper C++ library support
    13757         ld_shlibs_CXX=no
    13758         ;;
    13759       aix[4-9]*)
    13760         if test ia64 = "$host_cpu"; then
    13761           # On IA64, the linker does run time linking by default, so we don't
    13762           # have to do anything special.
    13763           aix_use_runtimelinking=no
    13764           exp_sym_flag='-Bexport'
    13765           no_entry_flag=
    13766         else
    13767           aix_use_runtimelinking=no
    13768 
    13769           # Test if we are trying to use run time linking or normal
    13770           # AIX style linking. If -brtl is somewhere in LDFLAGS, we
    13771           # have runtime linking enabled, and use it for executables.
    13772           # For shared libraries, we enable/disable runtime linking
    13773           # depending on the kind of the shared library created -
    13774           # when "with_aix_soname,aix_use_runtimelinking" is:
    13775           # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
    13776           # "aix,yes"  lib.so          shared, rtl:yes, for executables
    13777           #            lib.a           static archive
    13778           # "both,no"  lib.so.V(shr.o) shared, rtl:yes
    13779           #            lib.a(lib.so.V) shared, rtl:no,  for executables
    13780           # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
    13781           #            lib.a(lib.so.V) shared, rtl:no
    13782           # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
    13783           #            lib.a           static archive
    13784           case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
    13785             for ld_flag in $LDFLAGS; do
    13786               case $ld_flag in
    13787               *-brtl*)
    13788                 aix_use_runtimelinking=yes
    13789                 break
    13790                 ;;
    13791               esac
    13792             done
    13793             if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
    13794               # With aix-soname=svr4, we create the lib.so.V shared archives only,
    13795               # so we don't have lib.a shared libs to link our executables.
    13796               # We have to force runtime linking in this case.
    13797               aix_use_runtimelinking=yes
    13798               LDFLAGS="$LDFLAGS -Wl,-brtl"
    13799             fi
    13800             ;;
    13801           esac
    13802 
    13803           exp_sym_flag='-bexport'
    13804           no_entry_flag='-bnoentry'
    13805         fi
    13806 
    13807         # When large executables or shared objects are built, AIX ld can
    13808         # have problems creating the table of contents.  If linking a library
    13809         # or program results in "error TOC overflow" add -mminimal-toc to
    13810         # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
    13811         # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
    13812 
    13813         archive_cmds_CXX=''
    13814         hardcode_direct_CXX=yes
    13815         hardcode_direct_absolute_CXX=yes
    13816         hardcode_libdir_separator_CXX=':'
    13817         link_all_deplibs_CXX=yes
    13818         file_list_spec_CXX='$wl-f,'
    13819         case $with_aix_soname,$aix_use_runtimelinking in
    13820         aix,*) ;;       # no import file
    13821         svr4,* | *,yes) # use import file
    13822           # The Import File defines what to hardcode.
    13823           hardcode_direct_CXX=no
    13824           hardcode_direct_absolute_CXX=no
    13825           ;;
    13826         esac
    13827 
    13828         if test yes = "$GXX"; then
    13829           case $host_os in aix4.[012]|aix4.[012].*)
    13830           # We only want to do this on AIX 4.2 and lower, the check
    13831           # below for broken collect2 doesn't work under 4.3+
    13832           collect2name=`$CC -print-prog-name=collect2`
    13833           if test -f "$collect2name" &&
    13834              strings "$collect2name" | $GREP resolve_lib_name >/dev/null
    13835           then
    13836             # We have reworked collect2
    13837             :
    13838           else
    13839             # We have old collect2
    13840             hardcode_direct_CXX=unsupported
    13841             # It fails to find uninstalled libraries when the uninstalled
    13842             # path is not listed in the libpath.  Setting hardcode_minus_L
    13843             # to unsupported forces relinking
    13844             hardcode_minus_L_CXX=yes
    13845             hardcode_libdir_flag_spec_CXX='-L$libdir'
    13846             hardcode_libdir_separator_CXX=
    13847           fi
    13848           esac
    13849           shared_flag='-shared'
    13850           if test yes = "$aix_use_runtimelinking"; then
    13851             shared_flag=$shared_flag' $wl-G'
    13852           fi
    13853           # Need to ensure runtime linking is disabled for the traditional
    13854           # shared library, or the linker may eventually find shared libraries
    13855           # /with/ Import File - we do not want to mix them.
    13856           shared_flag_aix='-shared'
    13857           shared_flag_svr4='-shared $wl-G'
    13858         else
    13859           # not using gcc
    13860           if test ia64 = "$host_cpu"; then
    13861           # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
    13862           # chokes on -Wl,-G. The following line is correct:
    13863           shared_flag='-G'
    13864           else
    13865             if test yes = "$aix_use_runtimelinking"; then
    13866               shared_flag='$wl-G'
    13867             else
    13868               shared_flag='$wl-bM:SRE'
    13869             fi
    13870             shared_flag_aix='$wl-bM:SRE'
    13871             shared_flag_svr4='$wl-G'
    13872           fi
    13873         fi
    13874 
    13875         export_dynamic_flag_spec_CXX='$wl-bexpall'
    13876         # It seems that -bexpall does not export symbols beginning with
    13877         # underscore (_), so it is better to generate a list of symbols to
    13878         # export.
    13879         always_export_symbols_CXX=yes
    13880         if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
    13881           # Warning - without using the other runtime loading flags (-brtl),
    13882           # -berok will link without error, but may produce a broken library.
    13883           # The "-G" linker flag allows undefined symbols.
    13884           no_undefined_flag_CXX='-bernotok'
    13885           # Determine the default libpath from the value encoded in an empty
    13886           # executable.
    13887           if test set = "${lt_cv_aix_libpath+set}"; then
    13888   aix_libpath=$lt_cv_aix_libpath
    13889 else
    13890   if ${lt_cv_aix_libpath__CXX+:} false; then :
    13891   $as_echo_n "(cached) " >&6
    13892 else
    13893   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    13894 /* end confdefs.h.  */
    13895 
     5962$ac_includes_default
    138965963int
    13897 main ()
     5964find_stack_direction (int *addr, int depth)
    138985965{
    13899 
    13900   ;
    13901   return 0;
     5966  int dir, dummy = 0;
     5967  if (! addr)
     5968    addr = &dummy;
     5969  *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
     5970  dir = depth ? find_stack_direction (addr, depth - 1) : 0;
     5971  return dir + dummy;
    139025972}
    13903 _ACEOF
    13904 if ac_fn_cxx_try_link "$LINENO"; then :
    13905 
    13906   lt_aix_libpath_sed='
    13907       /Import File Strings/,/^$/ {
    13908           /^0/ {
    13909               s/^0  *\([^ ]*\) *$/\1/
    13910               p
    13911           }
    13912       }'
    13913   lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    13914   # Check for a 64-bit object if we didn't find anything.
    13915   if test -z "$lt_cv_aix_libpath__CXX"; then
    13916     lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    13917   fi
    13918 fi
    13919 rm -f core conftest.err conftest.$ac_objext \
    13920     conftest$ac_exeext conftest.$ac_ext
    13921   if test -z "$lt_cv_aix_libpath__CXX"; then
    13922     lt_cv_aix_libpath__CXX=/usr/lib:/lib
    13923   fi
    13924 
    13925 fi
    13926 
    13927   aix_libpath=$lt_cv_aix_libpath__CXX
    13928 fi
    13929 
    13930           hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
    13931 
    13932           archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
    13933         else
    13934           if test ia64 = "$host_cpu"; then
    13935             hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib'
    13936             allow_undefined_flag_CXX="-z nodefs"
    13937             archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
    13938           else
    13939             # Determine the default libpath from the value encoded in an
    13940             # empty executable.
    13941             if test set = "${lt_cv_aix_libpath+set}"; then
    13942   aix_libpath=$lt_cv_aix_libpath
    13943 else
    13944   if ${lt_cv_aix_libpath__CXX+:} false; then :
    13945   $as_echo_n "(cached) " >&6
    13946 else
    13947   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    13948 /* end confdefs.h.  */
    139495973
    139505974int
    13951 main ()
     5975main (int argc, char **argv)
    139525976{
    13953 
    13954   ;
    13955   return 0;
     5977  return find_stack_direction (0, argc + !argv + 20) < 0;
    139565978}
    139575979_ACEOF
    13958 if ac_fn_cxx_try_link "$LINENO"; then :
    13959 
    13960   lt_aix_libpath_sed='
    13961       /Import File Strings/,/^$/ {
    13962           /^0/ {
    13963               s/^0  *\([^ ]*\) *$/\1/
    13964               p
    13965           }
    13966       }'
    13967   lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    13968   # Check for a 64-bit object if we didn't find anything.
    13969   if test -z "$lt_cv_aix_libpath__CXX"; then
    13970     lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
    13971   fi
    13972 fi
    13973 rm -f core conftest.err conftest.$ac_objext \
    13974     conftest$ac_exeext conftest.$ac_ext
    13975   if test -z "$lt_cv_aix_libpath__CXX"; then
    13976     lt_cv_aix_libpath__CXX=/usr/lib:/lib
    13977   fi
    13978 
    13979 fi
    13980 
    13981   aix_libpath=$lt_cv_aix_libpath__CXX
    13982 fi
    13983 
    13984             hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
    13985             # Warning - without using the other run time loading flags,
    13986             # -berok will link without error, but may produce a broken library.
    13987             no_undefined_flag_CXX=' $wl-bernotok'
    13988             allow_undefined_flag_CXX=' $wl-berok'
    13989             if test yes = "$with_gnu_ld"; then
    13990               # We only use this code for GNU lds that support --whole-archive.
    13991               whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
    13992             else
    13993               # Exported symbols can be pulled into shared objects from archives
    13994               whole_archive_flag_spec_CXX='$convenience'
    13995             fi
    13996             archive_cmds_need_lc_CXX=yes
    13997             archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
    13998             # -brtl affects multiple linker settings, -berok does not and is overridden later
    13999             compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
    14000             if test svr4 != "$with_aix_soname"; then
    14001               # This is similar to how AIX traditionally builds its shared
    14002               # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
    14003               archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
    14004             fi
    14005             if test aix != "$with_aix_soname"; then
    14006               archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
    14007             else
    14008               # used by -dlpreopen to get the symbols
    14009               archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
    14010             fi
    14011             archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d'
    14012           fi
    14013         fi
    14014         ;;
    14015 
    14016       beos*)
    14017         if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
    14018           allow_undefined_flag_CXX=unsupported
    14019           # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
    14020           # support --undefined.  This deserves some investigation.  FIXME
    14021           archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    14022         else
    14023           ld_shlibs_CXX=no
    14024         fi
    14025         ;;
    14026 
    14027       chorus*)
    14028         case $cc_basename in
    14029           *)
    14030           # FIXME: insert proper C++ library support
    14031           ld_shlibs_CXX=no
    14032           ;;
    14033         esac
    14034         ;;
    14035 
    14036       cygwin* | mingw* | pw32* | cegcc*)
    14037         case $GXX,$cc_basename in
    14038         ,cl* | no,cl*)
    14039           # Native MSVC
    14040           # hardcode_libdir_flag_spec is actually meaningless, as there is
    14041           # no search path for DLLs.
    14042           hardcode_libdir_flag_spec_CXX=' '
    14043           allow_undefined_flag_CXX=unsupported
    14044           always_export_symbols_CXX=yes
    14045           file_list_spec_CXX='@'
    14046           # Tell ltmain to make .lib files, not .a files.
    14047           libext=lib
    14048           # Tell ltmain to make .dll files, not .so files.
    14049           shrext_cmds=.dll
    14050           # FIXME: Setting linknames here is a bad hack.
    14051           archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
    14052           archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[     ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([     ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
    14053               cp "$export_symbols" "$output_objdir/$soname.def";
    14054               echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
    14055             else
    14056               $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
    14057             fi~
    14058             $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
    14059             linknames='
    14060           # The linker will not automatically build a static lib if we build a DLL.
    14061           # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true'
    14062           enable_shared_with_static_runtimes_CXX=yes
    14063           # Don't use ranlib
    14064           old_postinstall_cmds_CXX='chmod 644 $oldlib'
    14065           postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~
    14066             lt_tool_outputfile="@TOOL_OUTPUT@"~
    14067             case $lt_outputfile in
    14068               *.exe|*.EXE) ;;
    14069               *)
    14070                 lt_outputfile=$lt_outputfile.exe
    14071                 lt_tool_outputfile=$lt_tool_outputfile.exe
    14072                 ;;
    14073             esac~
    14074             func_to_tool_file "$lt_outputfile"~
    14075             if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
    14076               $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
    14077               $RM "$lt_outputfile.manifest";
    14078             fi'
    14079           ;;
    14080         *)
    14081           # g++
    14082           # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
    14083           # as there is no search path for DLLs.
    14084           hardcode_libdir_flag_spec_CXX='-L$libdir'
    14085           export_dynamic_flag_spec_CXX='$wl--export-all-symbols'
    14086           allow_undefined_flag_CXX=unsupported
    14087           always_export_symbols_CXX=no
    14088           enable_shared_with_static_runtimes_CXX=yes
    14089 
    14090           if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
    14091             archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
    14092             # If the export-symbols file already is a .def file, use it as
    14093             # is; otherwise, prepend EXPORTS...
    14094             archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[   ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([     ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
    14095               cp $export_symbols $output_objdir/$soname.def;
    14096             else
    14097               echo EXPORTS > $output_objdir/$soname.def;
    14098               cat $export_symbols >> $output_objdir/$soname.def;
    14099             fi~
    14100             $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
    14101           else
    14102             ld_shlibs_CXX=no
    14103           fi
    14104           ;;
    14105         esac
    14106         ;;
    14107       darwin* | rhapsody*)
    14108 
    14109 
    14110   archive_cmds_need_lc_CXX=no
    14111   hardcode_direct_CXX=no
    14112   hardcode_automatic_CXX=yes
    14113   hardcode_shlibpath_var_CXX=unsupported
    14114   if test yes = "$lt_cv_ld_force_load"; then
    14115     whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
    14116 
    14117   else
    14118     whole_archive_flag_spec_CXX=''
    14119   fi
    14120   link_all_deplibs_CXX=yes
    14121   allow_undefined_flag_CXX=$_lt_dar_allow_undefined
    14122   case $cc_basename in
    14123      ifort*|nagfor*) _lt_dar_can_shared=yes ;;
    14124      *) _lt_dar_can_shared=$GCC ;;
    14125   esac
    14126   if test yes = "$_lt_dar_can_shared"; then
    14127     output_verbose_link_cmd=func_echo_all
    14128     archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
    14129     module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
    14130     archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
    14131     module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
    14132        if test yes != "$lt_cv_apple_cc_single_mod"; then
    14133       archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
    14134       archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
    14135     fi
    14136 
    14137   else
    14138   ld_shlibs_CXX=no
    14139   fi
    14140 
    14141         ;;
    14142 
    14143       os2*)
    14144         hardcode_libdir_flag_spec_CXX='-L$libdir'
    14145         hardcode_minus_L_CXX=yes
    14146         allow_undefined_flag_CXX=unsupported
    14147         shrext_cmds=.dll
    14148         archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
    14149           $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
    14150           $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
    14151           $ECHO EXPORTS >> $output_objdir/$libname.def~
    14152           emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
    14153           $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
    14154           emximp -o $lib $output_objdir/$libname.def'
    14155         archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
    14156           $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
    14157           $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
    14158           $ECHO EXPORTS >> $output_objdir/$libname.def~
    14159           prefix_cmds="$SED"~
    14160           if test EXPORTS = "`$SED 1q $export_symbols`"; then
    14161             prefix_cmds="$prefix_cmds -e 1d";
    14162           fi~
    14163           prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
    14164           cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
    14165           $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
    14166           emximp -o $lib $output_objdir/$libname.def'
    14167         old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
    14168         enable_shared_with_static_runtimes_CXX=yes
    14169         ;;
    14170 
    14171       dgux*)
    14172         case $cc_basename in
    14173           ec++*)
    14174             # FIXME: insert proper C++ library support
    14175             ld_shlibs_CXX=no
    14176             ;;
    14177           ghcx*)
    14178             # Green Hills C++ Compiler
    14179             # FIXME: insert proper C++ library support
    14180             ld_shlibs_CXX=no
    14181             ;;
    14182           *)
    14183             # FIXME: insert proper C++ library support
    14184             ld_shlibs_CXX=no
    14185             ;;
    14186         esac
    14187         ;;
    14188 
    14189       freebsd2.*)
    14190         # C++ shared libraries reported to be fairly broken before
    14191         # switch to ELF
    14192         ld_shlibs_CXX=no
    14193         ;;
    14194 
    14195       freebsd-elf*)
    14196         archive_cmds_need_lc_CXX=no
    14197         ;;
    14198 
    14199       freebsd* | dragonfly*)
    14200         # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
    14201         # conventions
    14202         ld_shlibs_CXX=yes
    14203         ;;
    14204 
    14205       haiku*)
    14206         archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    14207         link_all_deplibs_CXX=yes
    14208         ;;
    14209 
    14210       hpux9*)
    14211         hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
    14212         hardcode_libdir_separator_CXX=:
    14213         export_dynamic_flag_spec_CXX='$wl-E'
    14214         hardcode_direct_CXX=yes
    14215         hardcode_minus_L_CXX=yes # Not in the search PATH,
    14216                                              # but as the default
    14217                                              # location of the library.
    14218 
    14219         case $cc_basename in
    14220           CC*)
    14221             # FIXME: insert proper C++ library support
    14222             ld_shlibs_CXX=no
    14223             ;;
    14224           aCC*)
    14225             archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
    14226             # Commands to make compiler produce verbose output that lists
    14227             # what "hidden" libraries, object files and flags are used when
    14228             # linking a shared library.
    14229             #
    14230             # There doesn't appear to be a way to prevent this compiler from
    14231             # explicitly linking system object files so we need to strip them
    14232             # from the output so that they don't get included in the library
    14233             # dependencies.
    14234             output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
    14235             ;;
    14236           *)
    14237             if test yes = "$GXX"; then
    14238               archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
    14239             else
    14240               # FIXME: insert proper C++ library support
    14241               ld_shlibs_CXX=no
    14242             fi
    14243             ;;
    14244         esac
    14245         ;;
    14246 
    14247       hpux10*|hpux11*)
    14248         if test no = "$with_gnu_ld"; then
    14249           hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
    14250           hardcode_libdir_separator_CXX=:
    14251 
    14252           case $host_cpu in
    14253             hppa*64*|ia64*)
    14254               ;;
    14255             *)
    14256               export_dynamic_flag_spec_CXX='$wl-E'
    14257               ;;
    14258           esac
    14259         fi
    14260         case $host_cpu in
    14261           hppa*64*|ia64*)
    14262             hardcode_direct_CXX=no
    14263             hardcode_shlibpath_var_CXX=no
    14264             ;;
    14265           *)
    14266             hardcode_direct_CXX=yes
    14267             hardcode_direct_absolute_CXX=yes
    14268             hardcode_minus_L_CXX=yes # Not in the search PATH,
    14269                                                  # but as the default
    14270                                                  # location of the library.
    14271             ;;
    14272         esac
    14273 
    14274         case $cc_basename in
    14275           CC*)
    14276             # FIXME: insert proper C++ library support
    14277             ld_shlibs_CXX=no
    14278             ;;
    14279           aCC*)
    14280             case $host_cpu in
    14281               hppa*64*)
    14282                 archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14283                 ;;
    14284               ia64*)
    14285                 archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14286                 ;;
    14287               *)
    14288                 archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14289                 ;;
    14290             esac
    14291             # Commands to make compiler produce verbose output that lists
    14292             # what "hidden" libraries, object files and flags are used when
    14293             # linking a shared library.
    14294             #
    14295             # There doesn't appear to be a way to prevent this compiler from
    14296             # explicitly linking system object files so we need to strip them
    14297             # from the output so that they don't get included in the library
    14298             # dependencies.
    14299             output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
    14300             ;;
    14301           *)
    14302             if test yes = "$GXX"; then
    14303               if test no = "$with_gnu_ld"; then
    14304                 case $host_cpu in
    14305                   hppa*64*)
    14306                     archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14307                     ;;
    14308                   ia64*)
    14309                     archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14310                     ;;
    14311                   *)
    14312                     archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14313                     ;;
    14314                 esac
    14315               fi
    14316             else
    14317               # FIXME: insert proper C++ library support
    14318               ld_shlibs_CXX=no
    14319             fi
    14320             ;;
    14321         esac
    14322         ;;
    14323 
    14324       interix[3-9]*)
    14325         hardcode_direct_CXX=no
    14326         hardcode_shlibpath_var_CXX=no
    14327         hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
    14328         export_dynamic_flag_spec_CXX='$wl-E'
    14329         # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
    14330         # Instead, shared libraries are loaded at an image base (0x10000000 by
    14331         # default) and relocated if they conflict, which is a slow very memory
    14332         # consuming and fragmenting process.  To avoid this, we pick a random,
    14333         # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
    14334         # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
    14335         archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
    14336         archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
    14337         ;;
    14338       irix5* | irix6*)
    14339         case $cc_basename in
    14340           CC*)
    14341             # SGI C++
    14342             archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
    14343 
    14344             # Archives containing C++ object files must be created using
    14345             # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
    14346             # necessary to make sure instantiated templates are included
    14347             # in the archive.
    14348             old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
    14349             ;;
    14350           *)
    14351             if test yes = "$GXX"; then
    14352               if test no = "$with_gnu_ld"; then
    14353                 archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
    14354               else
    14355                 archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
    14356               fi
    14357             fi
    14358             link_all_deplibs_CXX=yes
    14359             ;;
    14360         esac
    14361         hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
    14362         hardcode_libdir_separator_CXX=:
    14363         inherit_rpath_CXX=yes
    14364         ;;
    14365 
    14366       linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    14367         case $cc_basename in
    14368           KCC*)
    14369             # Kuck and Associates, Inc. (KAI) C++ Compiler
    14370 
    14371             # KCC will only create a shared library if the output file
    14372             # ends with ".so" (or ".sl" for HP-UX), so rename the library
    14373             # to its proper name (with version) after linking.
    14374             archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
    14375             archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
    14376             # Commands to make compiler produce verbose output that lists
    14377             # what "hidden" libraries, object files and flags are used when
    14378             # linking a shared library.
    14379             #
    14380             # There doesn't appear to be a way to prevent this compiler from
    14381             # explicitly linking system object files so we need to strip them
    14382             # from the output so that they don't get included in the library
    14383             # dependencies.
    14384             output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
    14385 
    14386             hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
    14387             export_dynamic_flag_spec_CXX='$wl--export-dynamic'
    14388 
    14389             # Archives containing C++ object files must be created using
    14390             # "CC -Bstatic", where "CC" is the KAI C++ compiler.
    14391             old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
    14392             ;;
    14393           icpc* | ecpc* )
    14394             # Intel C++
    14395             with_gnu_ld=yes
    14396             # version 8.0 and above of icpc choke on multiply defined symbols
    14397             # if we add $predep_objects and $postdep_objects, however 7.1 and
    14398             # earlier do not add the objects themselves.
    14399             case `$CC -V 2>&1` in
    14400               *"Version 7."*)
    14401                 archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
    14402                 archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    14403                 ;;
    14404               *)  # Version 8.0 or newer
    14405                 tmp_idyn=
    14406                 case $host_cpu in
    14407                   ia64*) tmp_idyn=' -i_dynamic';;
    14408                 esac
    14409                 archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    14410                 archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    14411                 ;;
    14412             esac
    14413             archive_cmds_need_lc_CXX=no
    14414             hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
    14415             export_dynamic_flag_spec_CXX='$wl--export-dynamic'
    14416             whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
    14417             ;;
    14418           pgCC* | pgcpp*)
    14419             # Portland Group C++ compiler
    14420             case `$CC -V` in
    14421             *pgCC\ [1-5].* | *pgcpp\ [1-5].*)
    14422               prelink_cmds_CXX='tpldir=Template.dir~
    14423                rm -rf $tpldir~
    14424                $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
    14425                compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
    14426               old_archive_cmds_CXX='tpldir=Template.dir~
    14427                 rm -rf $tpldir~
    14428                 $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
    14429                 $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
    14430                 $RANLIB $oldlib'
    14431               archive_cmds_CXX='tpldir=Template.dir~
    14432                 rm -rf $tpldir~
    14433                 $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
    14434                 $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
    14435               archive_expsym_cmds_CXX='tpldir=Template.dir~
    14436                 rm -rf $tpldir~
    14437                 $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
    14438                 $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    14439               ;;
    14440             *) # Version 6 and above use weak symbols
    14441               archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
    14442               archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
    14443               ;;
    14444             esac
    14445 
    14446             hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir'
    14447             export_dynamic_flag_spec_CXX='$wl--export-dynamic'
    14448             whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
    14449             ;;
    14450           cxx*)
    14451             # Compaq C++
    14452             archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
    14453             archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
    14454 
    14455             runpath_var=LD_RUN_PATH
    14456             hardcode_libdir_flag_spec_CXX='-rpath $libdir'
    14457             hardcode_libdir_separator_CXX=:
    14458 
    14459             # Commands to make compiler produce verbose output that lists
    14460             # what "hidden" libraries, object files and flags are used when
    14461             # linking a shared library.
    14462             #
    14463             # There doesn't appear to be a way to prevent this compiler from
    14464             # explicitly linking system object files so we need to strip them
    14465             # from the output so that they don't get included in the library
    14466             # dependencies.
    14467             output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
    14468             ;;
    14469           xl* | mpixl* | bgxl*)
    14470             # IBM XL 8.0 on PPC, with GNU ld
    14471             hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
    14472             export_dynamic_flag_spec_CXX='$wl--export-dynamic'
    14473             archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
    14474             if test yes = "$supports_anon_versioning"; then
    14475               archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~
    14476                 cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
    14477                 echo "local: *; };" >> $output_objdir/$libname.ver~
    14478                 $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
    14479             fi
    14480             ;;
    14481           *)
    14482             case `$CC -V 2>&1 | sed 5q` in
    14483             *Sun\ C*)
    14484               # Sun C++ 5.9
    14485               no_undefined_flag_CXX=' -zdefs'
    14486               archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14487               archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
    14488               hardcode_libdir_flag_spec_CXX='-R$libdir'
    14489               whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
    14490               compiler_needs_object_CXX=yes
    14491 
    14492               # Not sure whether something based on
    14493               # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
    14494               # would be better.
    14495               output_verbose_link_cmd='func_echo_all'
    14496 
    14497               # Archives containing C++ object files must be created using
    14498               # "CC -xar", where "CC" is the Sun C++ compiler.  This is
    14499               # necessary to make sure instantiated templates are included
    14500               # in the archive.
    14501               old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
    14502               ;;
    14503             esac
    14504             ;;
    14505         esac
    14506         ;;
    14507 
    14508       lynxos*)
    14509         # FIXME: insert proper C++ library support
    14510         ld_shlibs_CXX=no
    14511         ;;
    14512 
    14513       m88k*)
    14514         # FIXME: insert proper C++ library support
    14515         ld_shlibs_CXX=no
    14516         ;;
    14517 
    14518       mvs*)
    14519         case $cc_basename in
    14520           cxx*)
    14521             # FIXME: insert proper C++ library support
    14522             ld_shlibs_CXX=no
    14523             ;;
    14524           *)
    14525             # FIXME: insert proper C++ library support
    14526             ld_shlibs_CXX=no
    14527             ;;
    14528         esac
    14529         ;;
    14530 
    14531       netbsd*)
    14532         if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
    14533           archive_cmds_CXX='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
    14534           wlarc=
    14535           hardcode_libdir_flag_spec_CXX='-R$libdir'
    14536           hardcode_direct_CXX=yes
    14537           hardcode_shlibpath_var_CXX=no
    14538         fi
    14539         # Workaround some broken pre-1.5 toolchains
    14540         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
    14541         ;;
    14542 
    14543       *nto* | *qnx*)
    14544         ld_shlibs_CXX=yes
    14545         ;;
    14546 
    14547       openbsd* | bitrig*)
    14548         if test -f /usr/libexec/ld.so; then
    14549           hardcode_direct_CXX=yes
    14550           hardcode_shlibpath_var_CXX=no
    14551           hardcode_direct_absolute_CXX=yes
    14552           archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
    14553           hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
    14554           if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
    14555             archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
    14556             export_dynamic_flag_spec_CXX='$wl-E'
    14557             whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
    14558           fi
    14559           output_verbose_link_cmd=func_echo_all
    14560         else
    14561           ld_shlibs_CXX=no
    14562         fi
    14563         ;;
    14564 
    14565       osf3* | osf4* | osf5*)
    14566         case $cc_basename in
    14567           KCC*)
    14568             # Kuck and Associates, Inc. (KAI) C++ Compiler
    14569 
    14570             # KCC will only create a shared library if the output file
    14571             # ends with ".so" (or ".sl" for HP-UX), so rename the library
    14572             # to its proper name (with version) after linking.
    14573             archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
    14574 
    14575             hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
    14576             hardcode_libdir_separator_CXX=:
    14577 
    14578             # Archives containing C++ object files must be created using
    14579             # the KAI C++ compiler.
    14580             case $host in
    14581               osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;;
    14582               *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;;
    14583             esac
    14584             ;;
    14585           RCC*)
    14586             # Rational C++ 2.4.1
    14587             # FIXME: insert proper C++ library support
    14588             ld_shlibs_CXX=no
    14589             ;;
    14590           cxx*)
    14591             case $host in
    14592               osf3*)
    14593                 allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
    14594                 archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
    14595                 hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
    14596                 ;;
    14597               *)
    14598                 allow_undefined_flag_CXX=' -expect_unresolved \*'
    14599                 archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
    14600                 archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
    14601                   echo "-hidden">> $lib.exp~
    14602                   $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
    14603                   $RM $lib.exp'
    14604                 hardcode_libdir_flag_spec_CXX='-rpath $libdir'
    14605                 ;;
    14606             esac
    14607 
    14608             hardcode_libdir_separator_CXX=:
    14609 
    14610             # Commands to make compiler produce verbose output that lists
    14611             # what "hidden" libraries, object files and flags are used when
    14612             # linking a shared library.
    14613             #
    14614             # There doesn't appear to be a way to prevent this compiler from
    14615             # explicitly linking system object files so we need to strip them
    14616             # from the output so that they don't get included in the library
    14617             # dependencies.
    14618             output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
    14619             ;;
    14620           *)
    14621             if test yes,no = "$GXX,$with_gnu_ld"; then
    14622               allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
    14623               case $host in
    14624                 osf3*)
    14625                   archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
    14626                   ;;
    14627                 *)
    14628                   archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
    14629                   ;;
    14630               esac
    14631 
    14632               hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
    14633               hardcode_libdir_separator_CXX=:
    14634 
    14635               # Commands to make compiler produce verbose output that lists
    14636               # what "hidden" libraries, object files and flags are used when
    14637               # linking a shared library.
    14638               output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
    14639 
    14640             else
    14641               # FIXME: insert proper C++ library support
    14642               ld_shlibs_CXX=no
    14643             fi
    14644             ;;
    14645         esac
    14646         ;;
    14647 
    14648       psos*)
    14649         # FIXME: insert proper C++ library support
    14650         ld_shlibs_CXX=no
    14651         ;;
    14652 
    14653       sunos4*)
    14654         case $cc_basename in
    14655           CC*)
    14656             # Sun C++ 4.x
    14657             # FIXME: insert proper C++ library support
    14658             ld_shlibs_CXX=no
    14659             ;;
    14660           lcc*)
    14661             # Lucid
    14662             # FIXME: insert proper C++ library support
    14663             ld_shlibs_CXX=no
    14664             ;;
    14665           *)
    14666             # FIXME: insert proper C++ library support
    14667             ld_shlibs_CXX=no
    14668             ;;
    14669         esac
    14670         ;;
    14671 
    14672       solaris*)
    14673         case $cc_basename in
    14674           CC* | sunCC*)
    14675             # Sun C++ 4.2, 5.x and Centerline C++
    14676             archive_cmds_need_lc_CXX=yes
    14677             no_undefined_flag_CXX=' -zdefs'
    14678             archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
    14679             archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
    14680               $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
    14681 
    14682             hardcode_libdir_flag_spec_CXX='-R$libdir'
    14683             hardcode_shlibpath_var_CXX=no
    14684             case $host_os in
    14685               solaris2.[0-5] | solaris2.[0-5].*) ;;
    14686               *)
    14687                 # The compiler driver will combine and reorder linker options,
    14688                 # but understands '-z linker_flag'.
    14689                 # Supported since Solaris 2.6 (maybe 2.5.1?)
    14690                 whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
    14691                 ;;
    14692             esac
    14693             link_all_deplibs_CXX=yes
    14694 
    14695             output_verbose_link_cmd='func_echo_all'
    14696 
    14697             # Archives containing C++ object files must be created using
    14698             # "CC -xar", where "CC" is the Sun C++ compiler.  This is
    14699             # necessary to make sure instantiated templates are included
    14700             # in the archive.
    14701             old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
    14702             ;;
    14703           gcx*)
    14704             # Green Hills C++ Compiler
    14705             archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
    14706 
    14707             # The C++ compiler must be used to create the archive.
    14708             old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
    14709             ;;
    14710           *)
    14711             # GNU C++ compiler with Solaris linker
    14712             if test yes,no = "$GXX,$with_gnu_ld"; then
    14713               no_undefined_flag_CXX=' $wl-z ${wl}defs'
    14714               if $CC --version | $GREP -v '^2\.7' > /dev/null; then
    14715                 archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
    14716                 archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
    14717                   $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
    14718 
    14719                 # Commands to make compiler produce verbose output that lists
    14720                 # what "hidden" libraries, object files and flags are used when
    14721                 # linking a shared library.
    14722                 output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
    14723               else
    14724                 # g++ 2.7 appears to require '-G' NOT '-shared' on this
    14725                 # platform.
    14726                 archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
    14727                 archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
    14728                   $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
    14729 
    14730                 # Commands to make compiler produce verbose output that lists
    14731                 # what "hidden" libraries, object files and flags are used when
    14732                 # linking a shared library.
    14733                 output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
    14734               fi
    14735 
    14736               hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir'
    14737               case $host_os in
    14738                 solaris2.[0-5] | solaris2.[0-5].*) ;;
    14739                 *)
    14740                   whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
    14741                   ;;
    14742               esac
    14743             fi
    14744             ;;
    14745         esac
    14746         ;;
    14747 
    14748     sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
    14749       no_undefined_flag_CXX='$wl-z,text'
    14750       archive_cmds_need_lc_CXX=no
    14751       hardcode_shlibpath_var_CXX=no
    14752       runpath_var='LD_RUN_PATH'
    14753 
    14754       case $cc_basename in
    14755         CC*)
    14756           archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14757           archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14758           ;;
    14759         *)
    14760           archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14761           archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14762           ;;
    14763       esac
    14764       ;;
    14765 
    14766       sysv5* | sco3.2v5* | sco5v6*)
    14767         # Note: We CANNOT use -z defs as we might desire, because we do not
    14768         # link with -lc, and that would cause any symbols used from libc to
    14769         # always be unresolved, which means just about no library would
    14770         # ever link correctly.  If we're not using GNU ld we use -z text
    14771         # though, which does catch some bad symbols but isn't as heavy-handed
    14772         # as -z defs.
    14773         no_undefined_flag_CXX='$wl-z,text'
    14774         allow_undefined_flag_CXX='$wl-z,nodefs'
    14775         archive_cmds_need_lc_CXX=no
    14776         hardcode_shlibpath_var_CXX=no
    14777         hardcode_libdir_flag_spec_CXX='$wl-R,$libdir'
    14778         hardcode_libdir_separator_CXX=':'
    14779         link_all_deplibs_CXX=yes
    14780         export_dynamic_flag_spec_CXX='$wl-Bexport'
    14781         runpath_var='LD_RUN_PATH'
    14782 
    14783         case $cc_basename in
    14784           CC*)
    14785             archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14786             archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14787             old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~
    14788               '"$old_archive_cmds_CXX"
    14789             reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~
    14790               '"$reload_cmds_CXX"
    14791             ;;
    14792           *)
    14793             archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14794             archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
    14795             ;;
    14796         esac
    14797       ;;
    14798 
    14799       tandem*)
    14800         case $cc_basename in
    14801           NCC*)
    14802             # NonStop-UX NCC 3.20
    14803             # FIXME: insert proper C++ library support
    14804             ld_shlibs_CXX=no
    14805             ;;
    14806           *)
    14807             # FIXME: insert proper C++ library support
    14808             ld_shlibs_CXX=no
    14809             ;;
    14810         esac
    14811         ;;
    14812 
    14813       vxworks*)
    14814         # FIXME: insert proper C++ library support
    14815         ld_shlibs_CXX=no
    14816         ;;
    14817 
    14818       *)
    14819         # FIXME: insert proper C++ library support
    14820         ld_shlibs_CXX=no
    14821         ;;
    14822     esac
    14823 
    14824     { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
    14825 $as_echo "$ld_shlibs_CXX" >&6; }
    14826     test no = "$ld_shlibs_CXX" && can_build_shared=no
    14827 
    14828     GCC_CXX=$GXX
    14829     LD_CXX=$LD
    14830 
    14831     ## CAVEAT EMPTOR:
    14832     ## There is no encapsulation within the following macros, do not change
    14833     ## the running order or otherwise move them around unless you know exactly
    14834     ## what you are doing...
    14835     # Dependencies to place before and after the object being linked:
    14836 predep_objects_CXX=
    14837 postdep_objects_CXX=
    14838 predeps_CXX=
    14839 postdeps_CXX=
    14840 compiler_lib_search_path_CXX=
    14841 
    14842 cat > conftest.$ac_ext <<_LT_EOF
    14843 class Foo
    14844 {
    14845 public:
    14846   Foo (void) { a = 0; }
    14847 private:
    14848   int a;
    14849 };
    14850 _LT_EOF
    14851 
    14852 
    14853 _lt_libdeps_save_CFLAGS=$CFLAGS
    14854 case "$CC $CFLAGS " in #(
    14855 *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
    14856 *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
    14857 *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
    14858 esac
    14859 
    14860 if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    14861   (eval $ac_compile) 2>&5
    14862   ac_status=$?
    14863   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    14864   test $ac_status = 0; }; then
    14865   # Parse the compiler output and extract the necessary
    14866   # objects, libraries and library flags.
    14867 
    14868   # Sentinel used to keep track of whether or not we are before
    14869   # the conftest object file.
    14870   pre_test_object_deps_done=no
    14871 
    14872   for p in `eval "$output_verbose_link_cmd"`; do
    14873     case $prev$p in
    14874 
    14875     -L* | -R* | -l*)
    14876        # Some compilers place space between "-{L,R}" and the path.
    14877        # Remove the space.
    14878        if test x-L = "$p" ||
    14879           test x-R = "$p"; then
    14880          prev=$p
    14881          continue
    14882        fi
    14883 
    14884        # Expand the sysroot to ease extracting the directories later.
    14885        if test -z "$prev"; then
    14886          case $p in
    14887          -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
    14888          -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
    14889          -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
    14890          esac
    14891        fi
    14892        case $p in
    14893        =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
    14894        esac
    14895        if test no = "$pre_test_object_deps_done"; then
    14896          case $prev in
    14897          -L | -R)
    14898            # Internal compiler library paths should come after those
    14899            # provided the user.  The postdeps already come after the
    14900            # user supplied libs so there is no need to process them.
    14901            if test -z "$compiler_lib_search_path_CXX"; then
    14902              compiler_lib_search_path_CXX=$prev$p
    14903            else
    14904              compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p"
    14905            fi
    14906            ;;
    14907          # The "-l" case would never come before the object being
    14908          # linked, so don't bother handling this case.
    14909          esac
    14910        else
    14911          if test -z "$postdeps_CXX"; then
    14912            postdeps_CXX=$prev$p
    14913          else
    14914            postdeps_CXX="${postdeps_CXX} $prev$p"
    14915          fi
    14916        fi
    14917        prev=
    14918        ;;
    14919 
    14920     *.lto.$objext) ;; # Ignore GCC LTO objects
    14921     *.$objext)
    14922        # This assumes that the test object file only shows up
    14923        # once in the compiler output.
    14924        if test "$p" = "conftest.$objext"; then
    14925          pre_test_object_deps_done=yes
    14926          continue
    14927        fi
    14928 
    14929        if test no = "$pre_test_object_deps_done"; then
    14930          if test -z "$predep_objects_CXX"; then
    14931            predep_objects_CXX=$p
    14932          else
    14933            predep_objects_CXX="$predep_objects_CXX $p"
    14934          fi
    14935        else
    14936          if test -z "$postdep_objects_CXX"; then
    14937            postdep_objects_CXX=$p
    14938          else
    14939            postdep_objects_CXX="$postdep_objects_CXX $p"
    14940          fi
    14941        fi
    14942        ;;
    14943 
    14944     *) ;; # Ignore the rest.
    14945 
    14946     esac
    14947   done
    14948 
    14949   # Clean up.
    14950   rm -f a.out a.exe
    14951 else
    14952   echo "libtool.m4: error: problem compiling CXX test program"
    14953 fi
    14954 
    14955 $RM -f confest.$objext
    14956 CFLAGS=$_lt_libdeps_save_CFLAGS
    14957 
    14958 # PORTME: override above test on systems where it is broken
    14959 case $host_os in
    14960 interix[3-9]*)
    14961   # Interix 3.5 installs completely hosed .la files for C++, so rather than
    14962   # hack all around it, let's just trust "g++" to DTRT.
    14963   predep_objects_CXX=
    14964   postdep_objects_CXX=
    14965   postdeps_CXX=
    14966   ;;
    14967 esac
    14968 
    14969 
    14970 case " $postdeps_CXX " in
    14971 *" -lc "*) archive_cmds_need_lc_CXX=no ;;
    14972 esac
    14973  compiler_lib_search_dirs_CXX=
    14974 if test -n "${compiler_lib_search_path_CXX}"; then
    14975  compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'`
    14976 fi
    14977 
    14978 
    14979 
    14980 
    14981 
    14982 
    14983 
    14984 
    14985 
    14986 
    14987 
    14988 
    14989 
    14990 
    14991 
    14992 
    14993 
    14994 
    14995 
    14996 
    14997 
    14998 
    14999 
    15000 
    15001 
    15002 
    15003 
    15004 
    15005 
    15006 
    15007 
    15008     lt_prog_compiler_wl_CXX=
    15009 lt_prog_compiler_pic_CXX=
    15010 lt_prog_compiler_static_CXX=
    15011 
    15012 
    15013   # C++ specific cases for pic, static, wl, etc.
    15014   if test yes = "$GXX"; then
    15015     lt_prog_compiler_wl_CXX='-Wl,'
    15016     lt_prog_compiler_static_CXX='-static'
    15017 
    15018     case $host_os in
    15019     aix*)
    15020       # All AIX code is PIC.
    15021       if test ia64 = "$host_cpu"; then
    15022         # AIX 5 now supports IA64 processor
    15023         lt_prog_compiler_static_CXX='-Bstatic'
    15024       fi
    15025       lt_prog_compiler_pic_CXX='-fPIC'
    15026       ;;
    15027 
    15028     amigaos*)
    15029       case $host_cpu in
    15030       powerpc)
    15031             # see comment about AmigaOS4 .so support
    15032             lt_prog_compiler_pic_CXX='-fPIC'
    15033         ;;
    15034       m68k)
    15035             # FIXME: we need at least 68020 code to build shared libraries, but
    15036             # adding the '-m68020' flag to GCC prevents building anything better,
    15037             # like '-m68040'.
    15038             lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
    15039         ;;
    15040       esac
    15041       ;;
    15042 
    15043     beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
    15044       # PIC is the default for these OSes.
    15045       ;;
    15046     mingw* | cygwin* | os2* | pw32* | cegcc*)
    15047       # This hack is so that the source file can tell whether it is being
    15048       # built for inclusion in a dll (and should export symbols for example).
    15049       # Although the cygwin gcc ignores -fPIC, still need this for old-style
    15050       # (--disable-auto-import) libraries
    15051       lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
    15052       case $host_os in
    15053       os2*)
    15054         lt_prog_compiler_static_CXX='$wl-static'
    15055         ;;
    15056       esac
    15057       ;;
    15058     darwin* | rhapsody*)
    15059       # PIC is the default on this platform
    15060       # Common symbols not allowed in MH_DYLIB files
    15061       lt_prog_compiler_pic_CXX='-fno-common'
    15062       ;;
    15063     *djgpp*)
    15064       # DJGPP does not support shared libraries at all
    15065       lt_prog_compiler_pic_CXX=
    15066       ;;
    15067     haiku*)
    15068       # PIC is the default for Haiku.
    15069       # The "-static" flag exists, but is broken.
    15070       lt_prog_compiler_static_CXX=
    15071       ;;
    15072     interix[3-9]*)
    15073       # Interix 3.x gcc -fpic/-fPIC options generate broken code.
    15074       # Instead, we relocate shared libraries at runtime.
    15075       ;;
    15076     sysv4*MP*)
    15077       if test -d /usr/nec; then
    15078         lt_prog_compiler_pic_CXX=-Kconform_pic
    15079       fi
    15080       ;;
    15081     hpux*)
    15082       # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
    15083       # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
    15084       # sets the default TLS model and affects inlining.
    15085       case $host_cpu in
    15086       hppa*64*)
    15087         ;;
    15088       *)
    15089         lt_prog_compiler_pic_CXX='-fPIC'
    15090         ;;
    15091       esac
    15092       ;;
    15093     *qnx* | *nto*)
    15094       # QNX uses GNU C++, but need to define -shared option too, otherwise
    15095       # it will coredump.
    15096       lt_prog_compiler_pic_CXX='-fPIC -shared'
    15097       ;;
    15098     *)
    15099       lt_prog_compiler_pic_CXX='-fPIC'
    15100       ;;
    15101     esac
    15102   else
    15103     case $host_os in
    15104       aix[4-9]*)
    15105         # All AIX code is PIC.
    15106         if test ia64 = "$host_cpu"; then
    15107           # AIX 5 now supports IA64 processor
    15108           lt_prog_compiler_static_CXX='-Bstatic'
    15109         else
    15110           lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
    15111         fi
    15112         ;;
    15113       chorus*)
    15114         case $cc_basename in
    15115         cxch68*)
    15116           # Green Hills C++ Compiler
    15117           # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
    15118           ;;
    15119         esac
    15120         ;;
    15121       mingw* | cygwin* | os2* | pw32* | cegcc*)
    15122         # This hack is so that the source file can tell whether it is being
    15123         # built for inclusion in a dll (and should export symbols for example).
    15124         lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
    15125         ;;
    15126       dgux*)
    15127         case $cc_basename in
    15128           ec++*)
    15129             lt_prog_compiler_pic_CXX='-KPIC'
    15130             ;;
    15131           ghcx*)
    15132             # Green Hills C++ Compiler
    15133             lt_prog_compiler_pic_CXX='-pic'
    15134             ;;
    15135           *)
    15136             ;;
    15137         esac
    15138         ;;
    15139       freebsd* | dragonfly*)
    15140         # FreeBSD uses GNU C++
    15141         ;;
    15142       hpux9* | hpux10* | hpux11*)
    15143         case $cc_basename in
    15144           CC*)
    15145             lt_prog_compiler_wl_CXX='-Wl,'
    15146             lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
    15147             if test ia64 != "$host_cpu"; then
    15148               lt_prog_compiler_pic_CXX='+Z'
    15149             fi
    15150             ;;
    15151           aCC*)
    15152             lt_prog_compiler_wl_CXX='-Wl,'
    15153             lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
    15154             case $host_cpu in
    15155             hppa*64*|ia64*)
    15156               # +Z the default
    15157               ;;
    15158             *)
    15159               lt_prog_compiler_pic_CXX='+Z'
    15160               ;;
    15161             esac
    15162             ;;
    15163           *)
    15164             ;;
    15165         esac
    15166         ;;
    15167       interix*)
    15168         # This is c89, which is MS Visual C++ (no shared libs)
    15169         # Anyone wants to do a port?
    15170         ;;
    15171       irix5* | irix6* | nonstopux*)
    15172         case $cc_basename in
    15173           CC*)
    15174             lt_prog_compiler_wl_CXX='-Wl,'
    15175             lt_prog_compiler_static_CXX='-non_shared'
    15176             # CC pic flag -KPIC is the default.
    15177             ;;
    15178           *)
    15179             ;;
    15180         esac
    15181         ;;
    15182       linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    15183         case $cc_basename in
    15184           KCC*)
    15185             # KAI C++ Compiler
    15186             lt_prog_compiler_wl_CXX='--backend -Wl,'
    15187             lt_prog_compiler_pic_CXX='-fPIC'
    15188             ;;
    15189           ecpc* )
    15190             # old Intel C++ for x86_64, which still supported -KPIC.
    15191             lt_prog_compiler_wl_CXX='-Wl,'
    15192             lt_prog_compiler_pic_CXX='-KPIC'
    15193             lt_prog_compiler_static_CXX='-static'
    15194             ;;
    15195           icpc* )
    15196             # Intel C++, used to be incompatible with GCC.
    15197             # ICC 10 doesn't accept -KPIC any more.
    15198             lt_prog_compiler_wl_CXX='-Wl,'
    15199             lt_prog_compiler_pic_CXX='-fPIC'
    15200             lt_prog_compiler_static_CXX='-static'
    15201             ;;
    15202           pgCC* | pgcpp*)
    15203             # Portland Group C++ compiler
    15204             lt_prog_compiler_wl_CXX='-Wl,'
    15205             lt_prog_compiler_pic_CXX='-fpic'
    15206             lt_prog_compiler_static_CXX='-Bstatic'
    15207             ;;
    15208           cxx*)
    15209             # Compaq C++
    15210             # Make sure the PIC flag is empty.  It appears that all Alpha
    15211             # Linux and Compaq Tru64 Unix objects are PIC.
    15212             lt_prog_compiler_pic_CXX=
    15213             lt_prog_compiler_static_CXX='-non_shared'
    15214             ;;
    15215           xlc* | xlC* | bgxl[cC]* | mpixl[cC]*)
    15216             # IBM XL 8.0, 9.0 on PPC and BlueGene
    15217             lt_prog_compiler_wl_CXX='-Wl,'
    15218             lt_prog_compiler_pic_CXX='-qpic'
    15219             lt_prog_compiler_static_CXX='-qstaticlink'
    15220             ;;
    15221           *)
    15222             case `$CC -V 2>&1 | sed 5q` in
    15223             *Sun\ C*)
    15224               # Sun C++ 5.9
    15225               lt_prog_compiler_pic_CXX='-KPIC'
    15226               lt_prog_compiler_static_CXX='-Bstatic'
    15227               lt_prog_compiler_wl_CXX='-Qoption ld '
    15228               ;;
    15229             esac
    15230             ;;
    15231         esac
    15232         ;;
    15233       lynxos*)
    15234         ;;
    15235       m88k*)
    15236         ;;
    15237       mvs*)
    15238         case $cc_basename in
    15239           cxx*)
    15240             lt_prog_compiler_pic_CXX='-W c,exportall'
    15241             ;;
    15242           *)
    15243             ;;
    15244         esac
    15245         ;;
    15246       netbsd* | netbsdelf*-gnu)
    15247         ;;
    15248       *qnx* | *nto*)
    15249         # QNX uses GNU C++, but need to define -shared option too, otherwise
    15250         # it will coredump.
    15251         lt_prog_compiler_pic_CXX='-fPIC -shared'
    15252         ;;
    15253       osf3* | osf4* | osf5*)
    15254         case $cc_basename in
    15255           KCC*)
    15256             lt_prog_compiler_wl_CXX='--backend -Wl,'
    15257             ;;
    15258           RCC*)
    15259             # Rational C++ 2.4.1
    15260             lt_prog_compiler_pic_CXX='-pic'
    15261             ;;
    15262           cxx*)
    15263             # Digital/Compaq C++
    15264             lt_prog_compiler_wl_CXX='-Wl,'
    15265             # Make sure the PIC flag is empty.  It appears that all Alpha
    15266             # Linux and Compaq Tru64 Unix objects are PIC.
    15267             lt_prog_compiler_pic_CXX=
    15268             lt_prog_compiler_static_CXX='-non_shared'
    15269             ;;
    15270           *)
    15271             ;;
    15272         esac
    15273         ;;
    15274       psos*)
    15275         ;;
    15276       solaris*)
    15277         case $cc_basename in
    15278           CC* | sunCC*)
    15279             # Sun C++ 4.2, 5.x and Centerline C++
    15280             lt_prog_compiler_pic_CXX='-KPIC'
    15281             lt_prog_compiler_static_CXX='-Bstatic'
    15282             lt_prog_compiler_wl_CXX='-Qoption ld '
    15283             ;;
    15284           gcx*)
    15285             # Green Hills C++ Compiler
    15286             lt_prog_compiler_pic_CXX='-PIC'
    15287             ;;
    15288           *)
    15289             ;;
    15290         esac
    15291         ;;
    15292       sunos4*)
    15293         case $cc_basename in
    15294           CC*)
    15295             # Sun C++ 4.x
    15296             lt_prog_compiler_pic_CXX='-pic'
    15297             lt_prog_compiler_static_CXX='-Bstatic'
    15298             ;;
    15299           lcc*)
    15300             # Lucid
    15301             lt_prog_compiler_pic_CXX='-pic'
    15302             ;;
    15303           *)
    15304             ;;
    15305         esac
    15306         ;;
    15307       sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
    15308         case $cc_basename in
    15309           CC*)
    15310             lt_prog_compiler_wl_CXX='-Wl,'
    15311             lt_prog_compiler_pic_CXX='-KPIC'
    15312             lt_prog_compiler_static_CXX='-Bstatic'
    15313             ;;
    15314         esac
    15315         ;;
    15316       tandem*)
    15317         case $cc_basename in
    15318           NCC*)
    15319             # NonStop-UX NCC 3.20
    15320             lt_prog_compiler_pic_CXX='-KPIC'
    15321             ;;
    15322           *)
    15323             ;;
    15324         esac
    15325         ;;
    15326       vxworks*)
    15327         ;;
    15328       *)
    15329         lt_prog_compiler_can_build_shared_CXX=no
    15330         ;;
    15331     esac
    15332   fi
    15333 
    15334 case $host_os in
    15335   # For platforms that do not support PIC, -DPIC is meaningless:
    15336   *djgpp*)
    15337     lt_prog_compiler_pic_CXX=
    15338     ;;
    15339   *)
    15340     lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
    15341     ;;
    15342 esac
    15343 
    15344 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
    15345 $as_echo_n "checking for $compiler option to produce PIC... " >&6; }
    15346 if ${lt_cv_prog_compiler_pic_CXX+:} false; then :
    15347   $as_echo_n "(cached) " >&6
    15348 else
    15349   lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX
    15350 fi
    15351 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5
    15352 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; }
    15353 lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX
    15354 
    15355 #
    15356 # Check to make sure the PIC flag actually works.
    15357 #
    15358 if test -n "$lt_prog_compiler_pic_CXX"; then
    15359   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
    15360 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
    15361 if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then :
    15362   $as_echo_n "(cached) " >&6
    15363 else
    15364   lt_cv_prog_compiler_pic_works_CXX=no
    15365    ac_outfile=conftest.$ac_objext
    15366    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    15367    lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"  ## exclude from sc_useless_quotes_in_assignment
    15368    # Insert the option either (1) after the last *FLAGS variable, or
    15369    # (2) before a word containing "conftest.", or (3) at the end.
    15370    # Note that $ac_compile itself does not contain backslashes and begins
    15371    # with a dollar sign (not a hyphen), so the echo should work correctly.
    15372    # The option is referenced via a variable to avoid confusing sed.
    15373    lt_compile=`echo "$ac_compile" | $SED \
    15374    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    15375    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    15376    -e 's:$: $lt_compiler_flag:'`
    15377    (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    15378    (eval "$lt_compile" 2>conftest.err)
    15379    ac_status=$?
    15380    cat conftest.err >&5
    15381    echo "$as_me:$LINENO: \$? = $ac_status" >&5
    15382    if (exit $ac_status) && test -s "$ac_outfile"; then
    15383      # The compiler can only warn and ignore the option if not recognized
    15384      # So say no if there are warnings other than the usual output.
    15385      $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
    15386      $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
    15387      if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
    15388        lt_cv_prog_compiler_pic_works_CXX=yes
    15389      fi
    15390    fi
    15391    $RM conftest*
    15392 
    15393 fi
    15394 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
    15395 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
    15396 
    15397 if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then
    15398     case $lt_prog_compiler_pic_CXX in
    15399      "" | " "*) ;;
    15400      *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
    15401      esac
    15402 else
    15403     lt_prog_compiler_pic_CXX=
    15404      lt_prog_compiler_can_build_shared_CXX=no
    15405 fi
    15406 
    15407 fi
    15408 
    15409 
    15410 
    15411 
    15412 
    15413 #
    15414 # Check to make sure the static flag actually works.
    15415 #
    15416 wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
    15417 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
    15418 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
    15419 if ${lt_cv_prog_compiler_static_works_CXX+:} false; then :
    15420   $as_echo_n "(cached) " >&6
    15421 else
    15422   lt_cv_prog_compiler_static_works_CXX=no
    15423    save_LDFLAGS=$LDFLAGS
    15424    LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
    15425    echo "$lt_simple_link_test_code" > conftest.$ac_ext
    15426    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
    15427      # The linker can only warn and ignore the option if not recognized
    15428      # So say no if there are warnings
    15429      if test -s conftest.err; then
    15430        # Append any errors to the config.log.
    15431        cat conftest.err 1>&5
    15432        $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
    15433        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
    15434        if diff conftest.exp conftest.er2 >/dev/null; then
    15435          lt_cv_prog_compiler_static_works_CXX=yes
    15436        fi
    15437      else
    15438        lt_cv_prog_compiler_static_works_CXX=yes
    15439      fi
    15440    fi
    15441    $RM -r conftest*
    15442    LDFLAGS=$save_LDFLAGS
    15443 
    15444 fi
    15445 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
    15446 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; }
    15447 
    15448 if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then
    15449     :
    15450 else
    15451     lt_prog_compiler_static_CXX=
    15452 fi
    15453 
    15454 
    15455 
    15456 
    15457     { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
    15458 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
    15459 if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
    15460   $as_echo_n "(cached) " >&6
    15461 else
    15462   lt_cv_prog_compiler_c_o_CXX=no
    15463    $RM -r conftest 2>/dev/null
    15464    mkdir conftest
    15465    cd conftest
    15466    mkdir out
    15467    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    15468 
    15469    lt_compiler_flag="-o out/conftest2.$ac_objext"
    15470    # Insert the option either (1) after the last *FLAGS variable, or
    15471    # (2) before a word containing "conftest.", or (3) at the end.
    15472    # Note that $ac_compile itself does not contain backslashes and begins
    15473    # with a dollar sign (not a hyphen), so the echo should work correctly.
    15474    lt_compile=`echo "$ac_compile" | $SED \
    15475    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    15476    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    15477    -e 's:$: $lt_compiler_flag:'`
    15478    (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    15479    (eval "$lt_compile" 2>out/conftest.err)
    15480    ac_status=$?
    15481    cat out/conftest.err >&5
    15482    echo "$as_me:$LINENO: \$? = $ac_status" >&5
    15483    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    15484    then
    15485      # The compiler can only warn and ignore the option if not recognized
    15486      # So say no if there are warnings
    15487      $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
    15488      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
    15489      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
    15490        lt_cv_prog_compiler_c_o_CXX=yes
    15491      fi
    15492    fi
    15493    chmod u+w . 2>&5
    15494    $RM conftest*
    15495    # SGI C++ compiler will create directory out/ii_files/ for
    15496    # template instantiation
    15497    test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
    15498    $RM out/* && rmdir out
    15499    cd ..
    15500    $RM -r conftest
    15501    $RM conftest*
    15502 
    15503 fi
    15504 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
    15505 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
    15506 
    15507 
    15508 
    15509     { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
    15510 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
    15511 if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
    15512   $as_echo_n "(cached) " >&6
    15513 else
    15514   lt_cv_prog_compiler_c_o_CXX=no
    15515    $RM -r conftest 2>/dev/null
    15516    mkdir conftest
    15517    cd conftest
    15518    mkdir out
    15519    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    15520 
    15521    lt_compiler_flag="-o out/conftest2.$ac_objext"
    15522    # Insert the option either (1) after the last *FLAGS variable, or
    15523    # (2) before a word containing "conftest.", or (3) at the end.
    15524    # Note that $ac_compile itself does not contain backslashes and begins
    15525    # with a dollar sign (not a hyphen), so the echo should work correctly.
    15526    lt_compile=`echo "$ac_compile" | $SED \
    15527    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    15528    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    15529    -e 's:$: $lt_compiler_flag:'`
    15530    (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
    15531    (eval "$lt_compile" 2>out/conftest.err)
    15532    ac_status=$?
    15533    cat out/conftest.err >&5
    15534    echo "$as_me:$LINENO: \$? = $ac_status" >&5
    15535    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    15536    then
    15537      # The compiler can only warn and ignore the option if not recognized
    15538      # So say no if there are warnings
    15539      $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
    15540      $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
    15541      if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
    15542        lt_cv_prog_compiler_c_o_CXX=yes
    15543      fi
    15544    fi
    15545    chmod u+w . 2>&5
    15546    $RM conftest*
    15547    # SGI C++ compiler will create directory out/ii_files/ for
    15548    # template instantiation
    15549    test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
    15550    $RM out/* && rmdir out
    15551    cd ..
    15552    $RM -r conftest
    15553    $RM conftest*
    15554 
    15555 fi
    15556 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
    15557 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
    15558 
    15559 
    15560 
    15561 
    15562 hard_links=nottested
    15563 if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then
    15564   # do not overwrite the value of need_locks provided by the user
    15565   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
    15566 $as_echo_n "checking if we can lock with hard links... " >&6; }
    15567   hard_links=yes
    15568   $RM conftest*
    15569   ln conftest.a conftest.b 2>/dev/null && hard_links=no
    15570   touch conftest.a
    15571   ln conftest.a conftest.b 2>&5 || hard_links=no
    15572   ln conftest.a conftest.b 2>/dev/null && hard_links=no
    15573   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
    15574 $as_echo "$hard_links" >&6; }
    15575   if test no = "$hard_links"; then
    15576     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
    15577 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
    15578     need_locks=warn
    15579   fi
    15580 else
    15581   need_locks=no
    15582 fi
    15583 
    15584 
    15585 
    15586     { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
    15587 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
    15588 
    15589   export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
    15590   exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
    15591   case $host_os in
    15592   aix[4-9]*)
    15593     # If we're using GNU nm, then we don't want the "-C" option.
    15594     # -C means demangle to GNU nm, but means don't demangle to AIX nm.
    15595     # Without the "-l" option, or with the "-B" option, AIX nm treats
    15596     # weak defined symbols like other global defined symbols, whereas
    15597     # GNU nm marks them as "W".
    15598     # While the 'weak' keyword is ignored in the Export File, we need
    15599     # it in the Import File for the 'aix-soname' feature, so we have
    15600     # to replace the "-B" option with "-P" for AIX nm.
    15601     if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
    15602       export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
    15603     else
    15604       export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
    15605     fi
    15606     ;;
    15607   pw32*)
    15608     export_symbols_cmds_CXX=$ltdll_cmds
    15609     ;;
    15610   cygwin* | mingw* | cegcc*)
    15611     case $cc_basename in
    15612     cl*)
    15613       exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
    15614       ;;
    15615     *)
    15616       export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
    15617       exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
    15618       ;;
    15619     esac
    15620     ;;
    15621   linux* | k*bsd*-gnu | gnu*)
    15622     link_all_deplibs_CXX=no
    15623     ;;
    15624   *)
    15625     export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
    15626     ;;
    15627   esac
    15628 
    15629 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
    15630 $as_echo "$ld_shlibs_CXX" >&6; }
    15631 test no = "$ld_shlibs_CXX" && can_build_shared=no
    15632 
    15633 with_gnu_ld_CXX=$with_gnu_ld
    15634 
    15635 
    15636 
    15637 
    15638 
    15639 
    15640 #
    15641 # Do we need to explicitly link libc?
    15642 #
    15643 case "x$archive_cmds_need_lc_CXX" in
    15644 x|xyes)
    15645   # Assume -lc should be added
    15646   archive_cmds_need_lc_CXX=yes
    15647 
    15648   if test yes,yes = "$GCC,$enable_shared"; then
    15649     case $archive_cmds_CXX in
    15650     *'~'*)
    15651       # FIXME: we may have to deal with multi-command sequences.
    15652       ;;
    15653     '$CC '*)
    15654       # Test whether the compiler implicitly links with -lc since on some
    15655       # systems, -lgcc has to come before -lc. If gcc already passes -lc
    15656       # to ld, don't add -lc before -lgcc.
    15657       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
    15658 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
    15659 if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then :
    15660   $as_echo_n "(cached) " >&6
    15661 else
    15662   $RM conftest*
    15663         echo "$lt_simple_compile_test_code" > conftest.$ac_ext
    15664 
    15665         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
    15666   (eval $ac_compile) 2>&5
    15667   ac_status=$?
    15668   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    15669   test $ac_status = 0; } 2>conftest.err; then
    15670           soname=conftest
    15671           lib=conftest
    15672           libobjs=conftest.$ac_objext
    15673           deplibs=
    15674           wl=$lt_prog_compiler_wl_CXX
    15675           pic_flag=$lt_prog_compiler_pic_CXX
    15676           compiler_flags=-v
    15677           linker_flags=-v
    15678           verstring=
    15679           output_objdir=.
    15680           libname=conftest
    15681           lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
    15682           allow_undefined_flag_CXX=
    15683           if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
    15684   (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
    15685   ac_status=$?
    15686   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
    15687   test $ac_status = 0; }
    15688           then
    15689             lt_cv_archive_cmds_need_lc_CXX=no
    15690           else
    15691             lt_cv_archive_cmds_need_lc_CXX=yes
    15692           fi
    15693           allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
    15694         else
    15695           cat conftest.err 1>&5
    15696         fi
    15697         $RM conftest*
    15698 
    15699 fi
    15700 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
    15701 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
    15702       archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
    15703       ;;
    15704     esac
    15705   fi
    15706   ;;
    15707 esac
    15708 
    15709 
    15710 
    15711 
    15712 
    15713 
    15714 
    15715 
    15716 
    15717 
    15718 
    15719 
    15720 
    15721 
    15722 
    15723 
    15724 
    15725 
    15726 
    15727 
    15728 
    15729 
    15730 
    15731 
    15732 
    15733 
    15734 
    15735 
    15736 
    15737 
    15738 
    15739 
    15740 
    15741 
    15742 
    15743 
    15744 
    15745 
    15746 
    15747 
    15748 
    15749 
    15750 
    15751 
    15752 
    15753 
    15754 
    15755 
    15756 
    15757 
    15758 
    15759 
    15760 
    15761 
    15762 
    15763 
    15764 
    15765 
    15766 
    15767 
    15768 
    15769 
    15770     { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
    15771 $as_echo_n "checking dynamic linker characteristics... " >&6; }
    15772 
    15773 library_names_spec=
    15774 libname_spec='lib$name'
    15775 soname_spec=
    15776 shrext_cmds=.so
    15777 postinstall_cmds=
    15778 postuninstall_cmds=
    15779 finish_cmds=
    15780 finish_eval=
    15781 shlibpath_var=
    15782 shlibpath_overrides_runpath=unknown
    15783 version_type=none
    15784 dynamic_linker="$host_os ld.so"
    15785 sys_lib_dlsearch_path_spec="/lib /usr/lib"
    15786 need_lib_prefix=unknown
    15787 hardcode_into_libs=no
    15788 
    15789 # when you set need_version to no, make sure it does not cause -set_version
    15790 # flags to be left without arguments
    15791 need_version=unknown
    15792 
    15793 
    15794 
    15795 case $host_os in
    15796 aix3*)
    15797   version_type=linux # correct to gnu/linux during the next big refactor
    15798   library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
    15799   shlibpath_var=LIBPATH
    15800 
    15801   # AIX 3 has no versioning support, so we append a major version to the name.
    15802   soname_spec='$libname$release$shared_ext$major'
    15803   ;;
    15804 
    15805 aix[4-9]*)
    15806   version_type=linux # correct to gnu/linux during the next big refactor
    15807   need_lib_prefix=no
    15808   need_version=no
    15809   hardcode_into_libs=yes
    15810   if test ia64 = "$host_cpu"; then
    15811     # AIX 5 supports IA64
    15812     library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
    15813     shlibpath_var=LD_LIBRARY_PATH
    15814   else
    15815     # With GCC up to 2.95.x, collect2 would create an import file
    15816     # for dependence libraries.  The import file would start with
    15817     # the line '#! .'.  This would cause the generated library to
    15818     # depend on '.', always an invalid library.  This was fixed in
    15819     # development snapshots of GCC prior to 3.0.
    15820     case $host_os in
    15821       aix4 | aix4.[01] | aix4.[01].*)
    15822       if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
    15823            echo ' yes '
    15824            echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
    15825         :
    15826       else
    15827         can_build_shared=no
    15828       fi
    15829       ;;
    15830     esac
    15831     # Using Import Files as archive members, it is possible to support
    15832     # filename-based versioning of shared library archives on AIX. While
    15833     # this would work for both with and without runtime linking, it will
    15834     # prevent static linking of such archives. So we do filename-based
    15835     # shared library versioning with .so extension only, which is used
    15836     # when both runtime linking and shared linking is enabled.
    15837     # Unfortunately, runtime linking may impact performance, so we do
    15838     # not want this to be the default eventually. Also, we use the
    15839     # versioned .so libs for executables only if there is the -brtl
    15840     # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
    15841     # To allow for filename-based versioning support, we need to create
    15842     # libNAME.so.V as an archive file, containing:
    15843     # *) an Import File, referring to the versioned filename of the
    15844     #    archive as well as the shared archive member, telling the
    15845     #    bitwidth (32 or 64) of that shared object, and providing the
    15846     #    list of exported symbols of that shared object, eventually
    15847     #    decorated with the 'weak' keyword
    15848     # *) the shared object with the F_LOADONLY flag set, to really avoid
    15849     #    it being seen by the linker.
    15850     # At run time we better use the real file rather than another symlink,
    15851     # but for link time we create the symlink libNAME.so -> libNAME.so.V
    15852 
    15853     case $with_aix_soname,$aix_use_runtimelinking in
    15854     # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
    15855     # soname into executable. Probably we can add versioning support to
    15856     # collect2, so additional links can be useful in future.
    15857     aix,yes) # traditional libtool
    15858       dynamic_linker='AIX unversionable lib.so'
    15859       # If using run time linking (on AIX 4.2 or later) use lib<name>.so
    15860       # instead of lib<name>.a to let people know that these are not
    15861       # typical AIX shared libraries.
    15862       library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    15863       ;;
    15864     aix,no) # traditional AIX only
    15865       dynamic_linker='AIX lib.a(lib.so.V)'
    15866       # We preserve .a as extension for shared libraries through AIX4.2
    15867       # and later when we are not doing run time linking.
    15868       library_names_spec='$libname$release.a $libname.a'
    15869       soname_spec='$libname$release$shared_ext$major'
    15870       ;;
    15871     svr4,*) # full svr4 only
    15872       dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
    15873       library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
    15874       # We do not specify a path in Import Files, so LIBPATH fires.
    15875       shlibpath_overrides_runpath=yes
    15876       ;;
    15877     *,yes) # both, prefer svr4
    15878       dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
    15879       library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
    15880       # unpreferred sharedlib libNAME.a needs extra handling
    15881       postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
    15882       postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
    15883       # We do not specify a path in Import Files, so LIBPATH fires.
    15884       shlibpath_overrides_runpath=yes
    15885       ;;
    15886     *,no) # both, prefer aix
    15887       dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
    15888       library_names_spec='$libname$release.a $libname.a'
    15889       soname_spec='$libname$release$shared_ext$major'
    15890       # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
    15891       postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
    15892       postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
    15893       ;;
    15894     esac
    15895     shlibpath_var=LIBPATH
    15896   fi
    15897   ;;
    15898 
    15899 amigaos*)
    15900   case $host_cpu in
    15901   powerpc)
    15902     # Since July 2007 AmigaOS4 officially supports .so libraries.
    15903     # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
    15904     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    15905     ;;
    15906   m68k)
    15907     library_names_spec='$libname.ixlibrary $libname.a'
    15908     # Create ${libname}_ixlibrary.a entries in /sys/libs.
    15909     finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
    15910     ;;
    15911   esac
    15912   ;;
    15913 
    15914 beos*)
    15915   library_names_spec='$libname$shared_ext'
    15916   dynamic_linker="$host_os ld.so"
    15917   shlibpath_var=LIBRARY_PATH
    15918   ;;
    15919 
    15920 bsdi[45]*)
    15921   version_type=linux # correct to gnu/linux during the next big refactor
    15922   need_version=no
    15923   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    15924   soname_spec='$libname$release$shared_ext$major'
    15925   finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
    15926   shlibpath_var=LD_LIBRARY_PATH
    15927   sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
    15928   sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
    15929   # the default ld.so.conf also contains /usr/contrib/lib and
    15930   # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
    15931   # libtool to hard-code these into programs
    15932   ;;
    15933 
    15934 cygwin* | mingw* | pw32* | cegcc*)
    15935   version_type=windows
    15936   shrext_cmds=.dll
    15937   need_version=no
    15938   need_lib_prefix=no
    15939 
    15940   case $GCC,$cc_basename in
    15941   yes,*)
    15942     # gcc
    15943     library_names_spec='$libname.dll.a'
    15944     # DLL is installed to $(libdir)/../bin by postinstall_cmds
    15945     postinstall_cmds='base_file=`basename \$file`~
    15946       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
    15947       dldir=$destdir/`dirname \$dlpath`~
    15948       test -d \$dldir || mkdir -p \$dldir~
    15949       $install_prog $dir/$dlname \$dldir/$dlname~
    15950       chmod a+x \$dldir/$dlname~
    15951       if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
    15952         eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
    15953       fi'
    15954     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
    15955       dlpath=$dir/\$dldll~
    15956        $RM \$dlpath'
    15957     shlibpath_overrides_runpath=yes
    15958 
    15959     case $host_os in
    15960     cygwin*)
    15961       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
    15962       soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    15963 
    15964       ;;
    15965     mingw* | cegcc*)
    15966       # MinGW DLLs use traditional 'lib' prefix
    15967       soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    15968       ;;
    15969     pw32*)
    15970       # pw32 DLLs use 'pw' prefix rather than 'lib'
    15971       library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    15972       ;;
    15973     esac
    15974     dynamic_linker='Win32 ld.exe'
    15975     ;;
    15976 
    15977   *,cl*)
    15978     # Native MSVC
    15979     libname_spec='$name'
    15980     soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
    15981     library_names_spec='$libname.dll.lib'
    15982 
    15983     case $build_os in
    15984     mingw*)
    15985       sys_lib_search_path_spec=
    15986       lt_save_ifs=$IFS
    15987       IFS=';'
    15988       for lt_path in $LIB
    15989       do
    15990         IFS=$lt_save_ifs
    15991         # Let DOS variable expansion print the short 8.3 style file name.
    15992         lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
    15993         sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
    15994       done
    15995       IFS=$lt_save_ifs
    15996       # Convert to MSYS style.
    15997       sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
    15998       ;;
    15999     cygwin*)
    16000       # Convert to unix form, then to dos form, then back to unix form
    16001       # but this time dos style (no spaces!) so that the unix form looks
    16002       # like /cygdrive/c/PROGRA~1:/cygdr...
    16003       sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
    16004       sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
    16005       sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
    16006       ;;
    16007     *)
    16008       sys_lib_search_path_spec=$LIB
    16009       if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
    16010         # It is most probably a Windows format PATH.
    16011         sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
    16012       else
    16013         sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
    16014       fi
    16015       # FIXME: find the short name or the path components, as spaces are
    16016       # common. (e.g. "Program Files" -> "PROGRA~1")
    16017       ;;
    16018     esac
    16019 
    16020     # DLL is installed to $(libdir)/../bin by postinstall_cmds
    16021     postinstall_cmds='base_file=`basename \$file`~
    16022       dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
    16023       dldir=$destdir/`dirname \$dlpath`~
    16024       test -d \$dldir || mkdir -p \$dldir~
    16025       $install_prog $dir/$dlname \$dldir/$dlname'
    16026     postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
    16027       dlpath=$dir/\$dldll~
    16028        $RM \$dlpath'
    16029     shlibpath_overrides_runpath=yes
    16030     dynamic_linker='Win32 link.exe'
    16031     ;;
    16032 
    16033   *)
    16034     # Assume MSVC wrapper
    16035     library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
    16036     dynamic_linker='Win32 ld.exe'
    16037     ;;
    16038   esac
    16039   # FIXME: first we should search . and the directory the executable is in
    16040   shlibpath_var=PATH
    16041   ;;
    16042 
    16043 darwin* | rhapsody*)
    16044   dynamic_linker="$host_os dyld"
    16045   version_type=darwin
    16046   need_lib_prefix=no
    16047   need_version=no
    16048   library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
    16049   soname_spec='$libname$release$major$shared_ext'
    16050   shlibpath_overrides_runpath=yes
    16051   shlibpath_var=DYLD_LIBRARY_PATH
    16052   shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
    16053 
    16054   sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
    16055   ;;
    16056 
    16057 dgux*)
    16058   version_type=linux # correct to gnu/linux during the next big refactor
    16059   need_lib_prefix=no
    16060   need_version=no
    16061   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16062   soname_spec='$libname$release$shared_ext$major'
    16063   shlibpath_var=LD_LIBRARY_PATH
    16064   ;;
    16065 
    16066 freebsd* | dragonfly*)
    16067   # DragonFly does not have aout.  When/if they implement a new
    16068   # versioning mechanism, adjust this.
    16069   if test -x /usr/bin/objformat; then
    16070     objformat=`/usr/bin/objformat`
    16071   else
    16072     case $host_os in
    16073     freebsd[23].*) objformat=aout ;;
    16074     *) objformat=elf ;;
    16075     esac
    16076   fi
    16077   version_type=freebsd-$objformat
    16078   case $version_type in
    16079     freebsd-elf*)
    16080       library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16081       soname_spec='$libname$release$shared_ext$major'
    16082       need_version=no
    16083       need_lib_prefix=no
    16084       ;;
    16085     freebsd-*)
    16086       library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    16087       need_version=yes
    16088       ;;
    16089   esac
    16090   shlibpath_var=LD_LIBRARY_PATH
    16091   case $host_os in
    16092   freebsd2.*)
    16093     shlibpath_overrides_runpath=yes
    16094     ;;
    16095   freebsd3.[01]* | freebsdelf3.[01]*)
    16096     shlibpath_overrides_runpath=yes
    16097     hardcode_into_libs=yes
    16098     ;;
    16099   freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
    16100   freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
    16101     shlibpath_overrides_runpath=no
    16102     hardcode_into_libs=yes
    16103     ;;
    16104   *) # from 4.6 on, and DragonFly
    16105     shlibpath_overrides_runpath=yes
    16106     hardcode_into_libs=yes
    16107     ;;
    16108   esac
    16109   ;;
    16110 
    16111 haiku*)
    16112   version_type=linux # correct to gnu/linux during the next big refactor
    16113   need_lib_prefix=no
    16114   need_version=no
    16115   dynamic_linker="$host_os runtime_loader"
    16116   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16117   soname_spec='$libname$release$shared_ext$major'
    16118   shlibpath_var=LIBRARY_PATH
    16119   shlibpath_overrides_runpath=no
    16120   sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
    16121   hardcode_into_libs=yes
    16122   ;;
    16123 
    16124 hpux9* | hpux10* | hpux11*)
    16125   # Give a soname corresponding to the major version so that dld.sl refuses to
    16126   # link against other versions.
    16127   version_type=sunos
    16128   need_lib_prefix=no
    16129   need_version=no
    16130   case $host_cpu in
    16131   ia64*)
    16132     shrext_cmds='.so'
    16133     hardcode_into_libs=yes
    16134     dynamic_linker="$host_os dld.so"
    16135     shlibpath_var=LD_LIBRARY_PATH
    16136     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
    16137     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16138     soname_spec='$libname$release$shared_ext$major'
    16139     if test 32 = "$HPUX_IA64_MODE"; then
    16140       sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
    16141       sys_lib_dlsearch_path_spec=/usr/lib/hpux32
    16142     else
    16143       sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
    16144       sys_lib_dlsearch_path_spec=/usr/lib/hpux64
    16145     fi
    16146     ;;
    16147   hppa*64*)
    16148     shrext_cmds='.sl'
    16149     hardcode_into_libs=yes
    16150     dynamic_linker="$host_os dld.sl"
    16151     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
    16152     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
    16153     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16154     soname_spec='$libname$release$shared_ext$major'
    16155     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
    16156     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
    16157     ;;
    16158   *)
    16159     shrext_cmds='.sl'
    16160     dynamic_linker="$host_os dld.sl"
    16161     shlibpath_var=SHLIB_PATH
    16162     shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
    16163     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16164     soname_spec='$libname$release$shared_ext$major'
    16165     ;;
    16166   esac
    16167   # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
    16168   postinstall_cmds='chmod 555 $lib'
    16169   # or fails outright, so override atomically:
    16170   install_override_mode=555
    16171   ;;
    16172 
    16173 interix[3-9]*)
    16174   version_type=linux # correct to gnu/linux during the next big refactor
    16175   need_lib_prefix=no
    16176   need_version=no
    16177   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16178   soname_spec='$libname$release$shared_ext$major'
    16179   dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
    16180   shlibpath_var=LD_LIBRARY_PATH
    16181   shlibpath_overrides_runpath=no
    16182   hardcode_into_libs=yes
    16183   ;;
    16184 
    16185 irix5* | irix6* | nonstopux*)
    16186   case $host_os in
    16187     nonstopux*) version_type=nonstopux ;;
    16188     *)
    16189         if test yes = "$lt_cv_prog_gnu_ld"; then
    16190                 version_type=linux # correct to gnu/linux during the next big refactor
    16191         else
    16192                 version_type=irix
    16193         fi ;;
    16194   esac
    16195   need_lib_prefix=no
    16196   need_version=no
    16197   soname_spec='$libname$release$shared_ext$major'
    16198   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
    16199   case $host_os in
    16200   irix5* | nonstopux*)
    16201     libsuff= shlibsuff=
    16202     ;;
    16203   *)
    16204     case $LD in # libtool.m4 will add one of these switches to LD
    16205     *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
    16206       libsuff= shlibsuff= libmagic=32-bit;;
    16207     *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
    16208       libsuff=32 shlibsuff=N32 libmagic=N32;;
    16209     *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
    16210       libsuff=64 shlibsuff=64 libmagic=64-bit;;
    16211     *) libsuff= shlibsuff= libmagic=never-match;;
    16212     esac
    16213     ;;
    16214   esac
    16215   shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
    16216   shlibpath_overrides_runpath=no
    16217   sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
    16218   sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
    16219   hardcode_into_libs=yes
    16220   ;;
    16221 
    16222 # No shared lib support for Linux oldld, aout, or coff.
    16223 linux*oldld* | linux*aout* | linux*coff*)
    16224   dynamic_linker=no
    16225   ;;
    16226 
    16227 linux*android*)
    16228   version_type=none # Android doesn't support versioned libraries.
    16229   need_lib_prefix=no
    16230   need_version=no
    16231   library_names_spec='$libname$release$shared_ext'
    16232   soname_spec='$libname$release$shared_ext'
    16233   finish_cmds=
    16234   shlibpath_var=LD_LIBRARY_PATH
    16235   shlibpath_overrides_runpath=yes
    16236 
    16237   # This implies no fast_install, which is unacceptable.
    16238   # Some rework will be needed to allow for fast_install
    16239   # before this can be enabled.
    16240   hardcode_into_libs=yes
    16241 
    16242   dynamic_linker='Android linker'
    16243   # Don't embed -rpath directories since the linker doesn't support them.
    16244   hardcode_libdir_flag_spec_CXX='-L$libdir'
    16245   ;;
    16246 
    16247 # This must be glibc/ELF.
    16248 linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
    16249   version_type=linux # correct to gnu/linux during the next big refactor
    16250   need_lib_prefix=no
    16251   need_version=no
    16252   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16253   soname_spec='$libname$release$shared_ext$major'
    16254   finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
    16255   shlibpath_var=LD_LIBRARY_PATH
    16256   shlibpath_overrides_runpath=no
    16257 
    16258   # Some binutils ld are patched to set DT_RUNPATH
    16259   if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
    16260   $as_echo_n "(cached) " >&6
    16261 else
    16262   lt_cv_shlibpath_overrides_runpath=no
    16263     save_LDFLAGS=$LDFLAGS
    16264     save_libdir=$libdir
    16265     eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
    16266          LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
    16267     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    16268 /* end confdefs.h.  */
    16269 
    16270 int
    16271 main ()
    16272 {
    16273 
    16274   ;
    16275   return 0;
    16276 }
    16277 _ACEOF
    16278 if ac_fn_cxx_try_link "$LINENO"; then :
    16279   if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
    16280   lt_cv_shlibpath_overrides_runpath=yes
    16281 fi
    16282 fi
    16283 rm -f core conftest.err conftest.$ac_objext \
    16284     conftest$ac_exeext conftest.$ac_ext
    16285     LDFLAGS=$save_LDFLAGS
    16286     libdir=$save_libdir
    16287 
    16288 fi
    16289 
    16290   shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
    16291 
    16292   # This implies no fast_install, which is unacceptable.
    16293   # Some rework will be needed to allow for fast_install
    16294   # before this can be enabled.
    16295   hardcode_into_libs=yes
    16296 
    16297   # Ideally, we could use ldconfig to report *all* directores which are
    16298   # searched for libraries, however this is still not possible.  Aside from not
    16299   # being certain /sbin/ldconfig is available, command
    16300   # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
    16301   # even though it is searched at run-time.  Try to do the best guess by
    16302   # appending ld.so.conf contents (and includes) to the search path.
    16303   if test -f /etc/ld.so.conf; then
    16304     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[       ]*hwcap[        ]/d;s/[:,      ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
    16305     sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
    16306   fi
    16307 
    16308   # We used to test for /lib/ld.so.1 and disable shared libraries on
    16309   # powerpc, because MkLinux only supported shared libraries with the
    16310   # GNU dynamic linker.  Since this was broken with cross compilers,
    16311   # most powerpc-linux boxes support dynamic linking these days and
    16312   # people can always --disable-shared, the test was removed, and we
    16313   # assume the GNU/Linux dynamic linker is in use.
    16314   dynamic_linker='GNU/Linux ld.so'
    16315   ;;
    16316 
    16317 netbsdelf*-gnu)
    16318   version_type=linux
    16319   need_lib_prefix=no
    16320   need_version=no
    16321   library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
    16322   soname_spec='${libname}${release}${shared_ext}$major'
    16323   shlibpath_var=LD_LIBRARY_PATH
    16324   shlibpath_overrides_runpath=no
    16325   hardcode_into_libs=yes
    16326   dynamic_linker='NetBSD ld.elf_so'
    16327   ;;
    16328 
    16329 netbsd*)
    16330   version_type=sunos
    16331   need_lib_prefix=no
    16332   need_version=no
    16333   if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
    16334     library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    16335     finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
    16336     dynamic_linker='NetBSD (a.out) ld.so'
    16337   else
    16338     library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16339     soname_spec='$libname$release$shared_ext$major'
    16340     dynamic_linker='NetBSD ld.elf_so'
    16341   fi
    16342   shlibpath_var=LD_LIBRARY_PATH
    16343   shlibpath_overrides_runpath=yes
    16344   hardcode_into_libs=yes
    16345   ;;
    16346 
    16347 newsos6)
    16348   version_type=linux # correct to gnu/linux during the next big refactor
    16349   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16350   shlibpath_var=LD_LIBRARY_PATH
    16351   shlibpath_overrides_runpath=yes
    16352   ;;
    16353 
    16354 *nto* | *qnx*)
    16355   version_type=qnx
    16356   need_lib_prefix=no
    16357   need_version=no
    16358   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16359   soname_spec='$libname$release$shared_ext$major'
    16360   shlibpath_var=LD_LIBRARY_PATH
    16361   shlibpath_overrides_runpath=no
    16362   hardcode_into_libs=yes
    16363   dynamic_linker='ldqnx.so'
    16364   ;;
    16365 
    16366 openbsd* | bitrig*)
    16367   version_type=sunos
    16368   sys_lib_dlsearch_path_spec=/usr/lib
    16369   need_lib_prefix=no
    16370   if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
    16371     need_version=no
    16372   else
    16373     need_version=yes
    16374   fi
    16375   library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    16376   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
    16377   shlibpath_var=LD_LIBRARY_PATH
    16378   shlibpath_overrides_runpath=yes
    16379   ;;
    16380 
    16381 os2*)
    16382   libname_spec='$name'
    16383   version_type=windows
    16384   shrext_cmds=.dll
    16385   need_version=no
    16386   need_lib_prefix=no
    16387   # OS/2 can only load a DLL with a base name of 8 characters or less.
    16388   soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
    16389     v=$($ECHO $release$versuffix | tr -d .-);
    16390     n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
    16391     $ECHO $n$v`$shared_ext'
    16392   library_names_spec='${libname}_dll.$libext'
    16393   dynamic_linker='OS/2 ld.exe'
    16394   shlibpath_var=BEGINLIBPATH
    16395   sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
    16396   sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
    16397   postinstall_cmds='base_file=`basename \$file`~
    16398     dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
    16399     dldir=$destdir/`dirname \$dlpath`~
    16400     test -d \$dldir || mkdir -p \$dldir~
    16401     $install_prog $dir/$dlname \$dldir/$dlname~
    16402     chmod a+x \$dldir/$dlname~
    16403     if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
    16404       eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
    16405     fi'
    16406   postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
    16407     dlpath=$dir/\$dldll~
    16408     $RM \$dlpath'
    16409   ;;
    16410 
    16411 osf3* | osf4* | osf5*)
    16412   version_type=osf
    16413   need_lib_prefix=no
    16414   need_version=no
    16415   soname_spec='$libname$release$shared_ext$major'
    16416   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16417   shlibpath_var=LD_LIBRARY_PATH
    16418   sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
    16419   sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
    16420   ;;
    16421 
    16422 rdos*)
    16423   dynamic_linker=no
    16424   ;;
    16425 
    16426 solaris*)
    16427   version_type=linux # correct to gnu/linux during the next big refactor
    16428   need_lib_prefix=no
    16429   need_version=no
    16430   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16431   soname_spec='$libname$release$shared_ext$major'
    16432   shlibpath_var=LD_LIBRARY_PATH
    16433   shlibpath_overrides_runpath=yes
    16434   hardcode_into_libs=yes
    16435   # ldd complains unless libraries are executable
    16436   postinstall_cmds='chmod +x $lib'
    16437   ;;
    16438 
    16439 sunos4*)
    16440   version_type=sunos
    16441   library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
    16442   finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
    16443   shlibpath_var=LD_LIBRARY_PATH
    16444   shlibpath_overrides_runpath=yes
    16445   if test yes = "$with_gnu_ld"; then
    16446     need_lib_prefix=no
    16447   fi
    16448   need_version=yes
    16449   ;;
    16450 
    16451 sysv4 | sysv4.3*)
    16452   version_type=linux # correct to gnu/linux during the next big refactor
    16453   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16454   soname_spec='$libname$release$shared_ext$major'
    16455   shlibpath_var=LD_LIBRARY_PATH
    16456   case $host_vendor in
    16457     sni)
    16458       shlibpath_overrides_runpath=no
    16459       need_lib_prefix=no
    16460       runpath_var=LD_RUN_PATH
    16461       ;;
    16462     siemens)
    16463       need_lib_prefix=no
    16464       ;;
    16465     motorola)
    16466       need_lib_prefix=no
    16467       need_version=no
    16468       shlibpath_overrides_runpath=no
    16469       sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
    16470       ;;
    16471   esac
    16472   ;;
    16473 
    16474 sysv4*MP*)
    16475   if test -d /usr/nec; then
    16476     version_type=linux # correct to gnu/linux during the next big refactor
    16477     library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
    16478     soname_spec='$libname$shared_ext.$major'
    16479     shlibpath_var=LD_LIBRARY_PATH
    16480   fi
    16481   ;;
    16482 
    16483 sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
    16484   version_type=sco
    16485   need_lib_prefix=no
    16486   need_version=no
    16487   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
    16488   soname_spec='$libname$release$shared_ext$major'
    16489   shlibpath_var=LD_LIBRARY_PATH
    16490   shlibpath_overrides_runpath=yes
    16491   hardcode_into_libs=yes
    16492   if test yes = "$with_gnu_ld"; then
    16493     sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
    16494   else
    16495     sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
    16496     case $host_os in
    16497       sco3.2v5*)
    16498         sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
    16499         ;;
    16500     esac
    16501   fi
    16502   sys_lib_dlsearch_path_spec='/usr/lib'
    16503   ;;
    16504 
    16505 tpf*)
    16506   # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
    16507   version_type=linux # correct to gnu/linux during the next big refactor
    16508   need_lib_prefix=no
    16509   need_version=no
    16510   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16511   shlibpath_var=LD_LIBRARY_PATH
    16512   shlibpath_overrides_runpath=no
    16513   hardcode_into_libs=yes
    16514   ;;
    16515 
    16516 uts4*)
    16517   version_type=linux # correct to gnu/linux during the next big refactor
    16518   library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
    16519   soname_spec='$libname$release$shared_ext$major'
    16520   shlibpath_var=LD_LIBRARY_PATH
    16521   ;;
    16522 
    16523 *)
    16524   dynamic_linker=no
    16525   ;;
    16526 esac
    16527 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
    16528 $as_echo "$dynamic_linker" >&6; }
    16529 test no = "$dynamic_linker" && can_build_shared=no
    16530 
    16531 variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
    16532 if test yes = "$GCC"; then
    16533   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
    16534 fi
    16535 
    16536 if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
    16537   sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
    16538 fi
    16539 
    16540 if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
    16541   sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
    16542 fi
    16543 
    16544 # remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
    16545 configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
    16546 
    16547 # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
    16548 func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
    16549 
    16550 # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
    16551 configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
    16552 
    16553 
    16554 
    16555 
    16556 
    16557 
    16558 
    16559 
    16560 
    16561 
    16562 
    16563 
    16564 
    16565 
    16566 
    16567 
    16568 
    16569 
    16570 
    16571 
    16572 
    16573 
    16574 
    16575 
    16576 
    16577 
    16578 
    16579 
    16580 
    16581 
    16582 
    16583 
    16584 
    16585 
    16586 
    16587 
    16588 
    16589 
    16590 
    16591 
    16592     { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
    16593 $as_echo_n "checking how to hardcode library paths into programs... " >&6; }
    16594 hardcode_action_CXX=
    16595 if test -n "$hardcode_libdir_flag_spec_CXX" ||
    16596    test -n "$runpath_var_CXX" ||
    16597    test yes = "$hardcode_automatic_CXX"; then
    16598 
    16599   # We can hardcode non-existent directories.
    16600   if test no != "$hardcode_direct_CXX" &&
    16601      # If the only mechanism to avoid hardcoding is shlibpath_var, we
    16602      # have to relink, otherwise we might link with an installed library
    16603      # when we should be linking with a yet-to-be-installed one
    16604      ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" &&
    16605      test no != "$hardcode_minus_L_CXX"; then
    16606     # Linking always hardcodes the temporary library directory.
    16607     hardcode_action_CXX=relink
    16608   else
    16609     # We can link without hardcoding, and we can hardcode nonexisting dirs.
    16610     hardcode_action_CXX=immediate
    16611   fi
    16612 else
    16613   # We cannot hardcode anything, or else we can only hardcode existing
    16614   # directories.
    16615   hardcode_action_CXX=unsupported
    16616 fi
    16617 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
    16618 $as_echo "$hardcode_action_CXX" >&6; }
    16619 
    16620 if test relink = "$hardcode_action_CXX" ||
    16621    test yes = "$inherit_rpath_CXX"; then
    16622   # Fast installation is not supported
    16623   enable_fast_install=no
    16624 elif test yes = "$shlibpath_overrides_runpath" ||
    16625      test no = "$enable_shared"; then
    16626   # Fast installation is not necessary
    16627   enable_fast_install=needless
    16628 fi
    16629 
    16630 
    16631 
    16632 
    16633 
    16634 
    16635 
    16636   fi # test -n "$compiler"
    16637 
    16638   CC=$lt_save_CC
    16639   CFLAGS=$lt_save_CFLAGS
    16640   LDCXX=$LD
    16641   LD=$lt_save_LD
    16642   GCC=$lt_save_GCC
    16643   with_gnu_ld=$lt_save_with_gnu_ld
    16644   lt_cv_path_LDCXX=$lt_cv_path_LD
    16645   lt_cv_path_LD=$lt_save_path_LD
    16646   lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
    16647   lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
    16648 fi # test yes != "$_lt_caught_CXX_error"
    16649 
    16650 ac_ext=c
    16651 ac_cpp='$CPP $CPPFLAGS'
    16652 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    16653 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    16654 ac_compiler_gnu=$ac_cv_c_compiler_gnu
    16655 
    16656 
    16657 
    16658 
    16659 
    16660 
    16661 
    16662 
    16663 
    16664 
    16665 
    16666 
    16667 
    16668 
    16669 
    16670         ac_config_commands="$ac_config_commands libtool"
    16671 
    16672 
    16673 
    16674 
    16675 # Only expand once:
    16676 
    16677 
    16678 
    16679 
    16680 # Checks for libraries.
    16681 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fibre::yield in -lfibre" >&5
    16682 $as_echo_n "checking for Fibre::yield in -lfibre... " >&6; }
    16683 if ${ac_cv_lib_fibre_Fibre__yield+:} false; then :
    16684   $as_echo_n "(cached) " >&6
    16685 else
    16686   ac_check_lib_save_LIBS=$LIBS
    16687 LIBS="-lfibre  $LIBS"
    16688 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    16689 /* end confdefs.h.  */
    16690 
    16691 /* Override any GCC internal prototype to avoid an error.
    16692    Use char because int might match the return type of a GCC
    16693    builtin and then its argument prototype would still apply.  */
    16694 #ifdef __cplusplus
    16695 extern "C"
    16696 #endif
    16697 char Fibre::yield ();
    16698 int
    16699 main ()
    16700 {
    16701 return Fibre::yield ();
    16702   ;
    16703   return 0;
    16704 }
    16705 _ACEOF
    16706 if ac_fn_c_try_link "$LINENO"; then :
    16707   ac_cv_lib_fibre_Fibre__yield=yes
    16708 else
    16709   ac_cv_lib_fibre_Fibre__yield=no
    16710 fi
    16711 rm -f core conftest.err conftest.$ac_objext \
    16712     conftest$ac_exeext conftest.$ac_ext
    16713 LIBS=$ac_check_lib_save_LIBS
    16714 fi
    16715 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fibre_Fibre__yield" >&5
    16716 $as_echo "$ac_cv_lib_fibre_Fibre__yield" >&6; }
    16717 if test "x$ac_cv_lib_fibre_Fibre__yield" = xyes; then :
    16718   HAVE_LIBFIBRE=1
    16719 else
    16720   HAVE_LIBFIBRE=0
    16721 fi
    16722 
    16723  if test "$HAVE_LIBFIBRE" -eq 1; then
    16724   WITH_LIBFIBRE_TRUE=
    16725   WITH_LIBFIBRE_FALSE='#'
    16726 else
    16727   WITH_LIBFIBRE_TRUE='#'
    16728   WITH_LIBFIBRE_FALSE=
    16729 fi
    16730 
    16731 
    16732 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ProfilingIsEnabledForAllThreads in -lprofiler" >&5
    16733 $as_echo_n "checking for ProfilingIsEnabledForAllThreads in -lprofiler... " >&6; }
    16734 if ${ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads+:} false; then :
    16735   $as_echo_n "(cached) " >&6
    16736 else
    16737   ac_check_lib_save_LIBS=$LIBS
    16738 LIBS="-lprofiler  $LIBS"
    16739 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    16740 /* end confdefs.h.  */
    16741 
    16742 /* Override any GCC internal prototype to avoid an error.
    16743    Use char because int might match the return type of a GCC
    16744    builtin and then its argument prototype would still apply.  */
    16745 #ifdef __cplusplus
    16746 extern "C"
    16747 #endif
    16748 char ProfilingIsEnabledForAllThreads ();
    16749 int
    16750 main ()
    16751 {
    16752 return ProfilingIsEnabledForAllThreads ();
    16753   ;
    16754   return 0;
    16755 }
    16756 _ACEOF
    16757 if ac_fn_c_try_link "$LINENO"; then :
    16758   ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads=yes
    16759 else
    16760   ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads=no
    16761 fi
    16762 rm -f core conftest.err conftest.$ac_objext \
    16763     conftest$ac_exeext conftest.$ac_ext
    16764 LIBS=$ac_check_lib_save_LIBS
    16765 fi
    16766 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads" >&5
    16767 $as_echo "$ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads" >&6; }
    16768 if test "x$ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads" = xyes; then :
    16769   HAVE_LIBPROFILER=1
    16770 else
    16771   HAVE_LIBPROFILER=0
    16772 fi
    16773 
    16774  if test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBPROFILER" -eq 1; then
    16775   WITH_LIBPROFILER_TRUE=
    16776   WITH_LIBPROFILER_FALSE='#'
    16777 else
    16778   WITH_LIBPROFILER_TRUE='#'
    16779   WITH_LIBPROFILER_FALSE=
    16780 fi
    16781 
    16782 
    16783 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for malloc in -ltcmalloc" >&5
    16784 $as_echo_n "checking for malloc in -ltcmalloc... " >&6; }
    16785 if ${ac_cv_lib_tcmalloc_malloc+:} false; then :
    16786   $as_echo_n "(cached) " >&6
    16787 else
    16788   ac_check_lib_save_LIBS=$LIBS
    16789 LIBS="-ltcmalloc  $LIBS"
    16790 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    16791 /* end confdefs.h.  */
    16792 
    16793 /* Override any GCC internal prototype to avoid an error.
    16794    Use char because int might match the return type of a GCC
    16795    builtin and then its argument prototype would still apply.  */
    16796 #ifdef __cplusplus
    16797 extern "C"
    16798 #endif
    16799 char malloc ();
    16800 int
    16801 main ()
    16802 {
    16803 return malloc ();
    16804   ;
    16805   return 0;
    16806 }
    16807 _ACEOF
    16808 if ac_fn_c_try_link "$LINENO"; then :
    16809   ac_cv_lib_tcmalloc_malloc=yes
    16810 else
    16811   ac_cv_lib_tcmalloc_malloc=no
    16812 fi
    16813 rm -f core conftest.err conftest.$ac_objext \
    16814     conftest$ac_exeext conftest.$ac_ext
    16815 LIBS=$ac_check_lib_save_LIBS
    16816 fi
    16817 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tcmalloc_malloc" >&5
    16818 $as_echo "$ac_cv_lib_tcmalloc_malloc" >&6; }
    16819 if test "x$ac_cv_lib_tcmalloc_malloc" = xyes; then :
    16820   HAVE_LIBTCMALLOC=1
    16821 else
    16822   HAVE_LIBTCMALLOC=0
    16823 fi
    16824 
    16825  if test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBTCMALLOC" -eq 1; then
    16826   WITH_LIBTCMALLOC_TRUE=
    16827   WITH_LIBTCMALLOC_FALSE='#'
    16828 else
    16829   WITH_LIBTCMALLOC_TRUE='#'
    16830   WITH_LIBTCMALLOC_FALSE=
    16831 fi
    16832 
    16833 
    16834 # conditionnally build the demangler
    16835 if test "x$enable_demangler" == xyes; then
    16836         LIBDEMANGLE="libdemangle.a"
    16837         DEMANGLER="demangler"
    16838 else
    16839         LIBDEMANGLE=""
    16840         DEMANGLER=""
    16841 fi
    16842 
    16843 
    16844 
    16845 # Checks for header files.
    16846 for ac_header in libintl.h malloc.h unistd.h
     5980if ac_fn_c_try_run "$LINENO"; then :
     5981  ac_cv_c_stack_direction=1
     5982else
     5983  ac_cv_c_stack_direction=-1
     5984fi
     5985rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
     5986  conftest.$ac_objext conftest.beam conftest.$ac_ext
     5987fi
     5988
     5989fi
     5990{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
     5991$as_echo "$ac_cv_c_stack_direction" >&6; }
     5992cat >>confdefs.h <<_ACEOF
     5993#define STACK_DIRECTION $ac_cv_c_stack_direction
     5994_ACEOF
     5995
     5996
     5997fi
     5998
     5999for ac_header in fenv.h float.h inttypes.h libintl.h limits.h malloc.h stddef.h stdlib.h string.h unistd.h
    168476000do :
    168486001  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
     
    168536006_ACEOF
    168546007
    16855 else
    16856   echo "Error: Missing required header"; exit 1
    168576008fi
    168586009
     
    168616012
    168626013# Checks for typedefs, structures, and compiler characteristics.
    16863 ac_fn_c_check_type "$LINENO" "_Float32" "ac_cv_type__Float32" "
    16864 "
    16865 if test "x$ac_cv_type__Float32" = xyes; then :
    16866 
    16867 cat >>confdefs.h <<_ACEOF
    16868 #define HAVE__FLOAT32 1
    16869 _ACEOF
    16870 
    16871 
    16872 $as_echo "#define HAVE_KEYWORDS_FLOATXX /**/" >>confdefs.h
    16873 
    16874 fi
    16875 
    16876 
    16877 # Checks for compiler flags.
    16878 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wcast-function-type" >&5
    16879 $as_echo_n "checking whether C compiler accepts -Wcast-function-type... " >&6; }
    16880 if ${m4cfa_cv_check_cflags___Wcast_function_type+:} false; then :
     6014{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
     6015$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
     6016if ${ac_cv_header_stdbool_h+:} false; then :
    168816017  $as_echo_n "(cached) " >&6
    168826018else
    16883 
    16884         m4cfa_check_save_flags=$CFLAGS
    16885         CFLAGS="$CFLAGS  -Wcast-function-type"
    16886         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     6019  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    168876020/* end confdefs.h.  */
     6021
     6022             #include <stdbool.h>
     6023             #ifndef bool
     6024              "error: bool is not defined"
     6025             #endif
     6026             #ifndef false
     6027              "error: false is not defined"
     6028             #endif
     6029             #if false
     6030              "error: false is not 0"
     6031             #endif
     6032             #ifndef true
     6033              "error: true is not defined"
     6034             #endif
     6035             #if true != 1
     6036              "error: true is not 1"
     6037             #endif
     6038             #ifndef __bool_true_false_are_defined
     6039              "error: __bool_true_false_are_defined is not defined"
     6040             #endif
     6041
     6042             struct s { _Bool s: 1; _Bool t; } s;
     6043
     6044             char a[true == 1 ? 1 : -1];
     6045             char b[false == 0 ? 1 : -1];
     6046             char c[__bool_true_false_are_defined == 1 ? 1 : -1];
     6047             char d[(bool) 0.5 == true ? 1 : -1];
     6048             /* See body of main program for 'e'.  */
     6049             char f[(_Bool) 0.0 == false ? 1 : -1];
     6050             char g[true];
     6051             char h[sizeof (_Bool)];
     6052             char i[sizeof s.t];
     6053             enum { j = false, k = true, l = false * true, m = true * 256 };
     6054             /* The following fails for
     6055                HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
     6056             _Bool n[m];
     6057             char o[sizeof n == m * sizeof n[0] ? 1 : -1];
     6058             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
     6059             /* Catch a bug in an HP-UX C compiler.  See
     6060                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
     6061                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
     6062              */
     6063             _Bool q = true;
     6064             _Bool *pq = &q;
    168886065
    168896066int
     
    168916068{
    168926069
     6070             bool e = &s;
     6071             *pq |= q;
     6072             *pq |= ! q;
     6073             /* Refer to every declared value, to avoid compiler optimizations.  */
     6074             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
     6075                     + !m + !n + !o + !p + !q + !pq);
     6076
    168936077  ;
    168946078  return 0;
     
    168966080_ACEOF
    168976081if ac_fn_c_try_compile "$LINENO"; then :
    16898   m4cfa_cv_check_cflags___Wcast_function_type=yes
    16899 else
    16900   m4cfa_cv_check_cflags___Wcast_function_type=no
     6082  ac_cv_header_stdbool_h=yes
     6083else
     6084  ac_cv_header_stdbool_h=no
    169016085fi
    169026086rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    16903         CFLAGS=$m4cfa_check_save_flags
    16904 fi
    16905 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $m4cfa_cv_check_cflags___Wcast_function_type" >&5
    16906 $as_echo "$m4cfa_cv_check_cflags___Wcast_function_type" >&6; }
    16907 if test "x$m4cfa_cv_check_cflags___Wcast_function_type" = xyes; then :
    16908 
    16909 $as_echo "#define HAVE_CAST_FUNCTION_TYPE /**/" >>confdefs.h
    16910 
    16911 else
    16912   :
    16913 fi
    16914 
    16915 
    16916 #==============================================================================
    16917 # backend compiler implementation
     6087fi
     6088{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
     6089$as_echo "$ac_cv_header_stdbool_h" >&6; }
     6090   ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
     6091if test "x$ac_cv_type__Bool" = xyes; then :
    169186092
    169196093cat >>confdefs.h <<_ACEOF
    16920 #define CFA_BACKEND_CC "${CC}"
    16921 _ACEOF
    16922 
    16923 
    16924 
    16925 #==============================================================================
    16926 ac_config_files="$ac_config_files Makefile driver/Makefile src/Makefile benchmark/Makefile tests/Makefile longrun_tests/Makefile tools/Makefile tools/prettyprinter/Makefile"
    16927 
    16928 
    16929 ac_config_links="$ac_config_links tests/test.py:tests/test.py"
    16930 
    16931 
    16932 ac_config_files="$ac_config_files tests/config.py"
     6094#define HAVE__BOOL 1
     6095_ACEOF
     6096
     6097
     6098fi
     6099
     6100
     6101if test $ac_cv_header_stdbool_h = yes; then
     6102
     6103$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
     6104
     6105fi
     6106
     6107{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
     6108$as_echo_n "checking for inline... " >&6; }
     6109if ${ac_cv_c_inline+:} false; then :
     6110  $as_echo_n "(cached) " >&6
     6111else
     6112  ac_cv_c_inline=no
     6113for ac_kw in inline __inline__ __inline; do
     6114  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     6115/* end confdefs.h.  */
     6116#ifndef __cplusplus
     6117typedef int foo_t;
     6118static $ac_kw foo_t static_foo () {return 0; }
     6119$ac_kw foo_t foo () {return 0; }
     6120#endif
     6121
     6122_ACEOF
     6123if ac_fn_c_try_compile "$LINENO"; then :
     6124  ac_cv_c_inline=$ac_kw
     6125fi
     6126rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     6127  test "$ac_cv_c_inline" != no && break
     6128done
     6129
     6130fi
     6131{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
     6132$as_echo "$ac_cv_c_inline" >&6; }
     6133
     6134case $ac_cv_c_inline in
     6135  inline | yes) ;;
     6136  *)
     6137    case $ac_cv_c_inline in
     6138      no) ac_val=;;
     6139      *) ac_val=$ac_cv_c_inline;;
     6140    esac
     6141    cat >>confdefs.h <<_ACEOF
     6142#ifndef __cplusplus
     6143#define inline $ac_val
     6144#endif
     6145_ACEOF
     6146    ;;
     6147esac
     6148
     6149ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t"
     6150case $ac_cv_c_int16_t in #(
     6151  no|yes) ;; #(
     6152  *)
     6153
     6154cat >>confdefs.h <<_ACEOF
     6155#define int16_t $ac_cv_c_int16_t
     6156_ACEOF
     6157;;
     6158esac
     6159
     6160ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t"
     6161case $ac_cv_c_int32_t in #(
     6162  no|yes) ;; #(
     6163  *)
     6164
     6165cat >>confdefs.h <<_ACEOF
     6166#define int32_t $ac_cv_c_int32_t
     6167_ACEOF
     6168;;
     6169esac
     6170
     6171ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t"
     6172case $ac_cv_c_int8_t in #(
     6173  no|yes) ;; #(
     6174  *)
     6175
     6176cat >>confdefs.h <<_ACEOF
     6177#define int8_t $ac_cv_c_int8_t
     6178_ACEOF
     6179;;
     6180esac
     6181
     6182{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
     6183$as_echo_n "checking for C/C++ restrict keyword... " >&6; }
     6184if ${ac_cv_c_restrict+:} false; then :
     6185  $as_echo_n "(cached) " >&6
     6186else
     6187  ac_cv_c_restrict=no
     6188   # The order here caters to the fact that C++ does not require restrict.
     6189   for ac_kw in __restrict __restrict__ _Restrict restrict; do
     6190     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     6191/* end confdefs.h.  */
     6192typedef int * int_ptr;
     6193        int foo (int_ptr $ac_kw ip) {
     6194        return ip[0];
     6195       }
     6196int
     6197main ()
     6198{
     6199int s[1];
     6200        int * $ac_kw t = s;
     6201        t[0] = 0;
     6202        return foo(t)
     6203  ;
     6204  return 0;
     6205}
     6206_ACEOF
     6207if ac_fn_c_try_compile "$LINENO"; then :
     6208  ac_cv_c_restrict=$ac_kw
     6209fi
     6210rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     6211     test "$ac_cv_c_restrict" != no && break
     6212   done
     6213
     6214fi
     6215{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
     6216$as_echo "$ac_cv_c_restrict" >&6; }
     6217
     6218 case $ac_cv_c_restrict in
     6219   restrict) ;;
     6220   no) $as_echo "#define restrict /**/" >>confdefs.h
     6221 ;;
     6222   *)  cat >>confdefs.h <<_ACEOF
     6223#define restrict $ac_cv_c_restrict
     6224_ACEOF
     6225 ;;
     6226 esac
     6227
     6228ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
     6229if test "x$ac_cv_type_size_t" = xyes; then :
     6230
     6231else
     6232
     6233cat >>confdefs.h <<_ACEOF
     6234#define size_t unsigned int
     6235_ACEOF
     6236
     6237fi
     6238
     6239ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
     6240case $ac_cv_c_uint16_t in #(
     6241  no|yes) ;; #(
     6242  *)
     6243
     6244
     6245cat >>confdefs.h <<_ACEOF
     6246#define uint16_t $ac_cv_c_uint16_t
     6247_ACEOF
     6248;;
     6249  esac
     6250
     6251ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
     6252case $ac_cv_c_uint32_t in #(
     6253  no|yes) ;; #(
     6254  *)
     6255
     6256$as_echo "#define _UINT32_T 1" >>confdefs.h
     6257
     6258
     6259cat >>confdefs.h <<_ACEOF
     6260#define uint32_t $ac_cv_c_uint32_t
     6261_ACEOF
     6262;;
     6263  esac
     6264
     6265ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t"
     6266case $ac_cv_c_uint8_t in #(
     6267  no|yes) ;; #(
     6268  *)
     6269
     6270$as_echo "#define _UINT8_T 1" >>confdefs.h
     6271
     6272
     6273cat >>confdefs.h <<_ACEOF
     6274#define uint8_t $ac_cv_c_uint8_t
     6275_ACEOF
     6276;;
     6277  esac
     6278
     6279
     6280# Checks for library functions.
     6281for ac_func in memset putenv strchr strtol
     6282do :
     6283  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
     6284ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
     6285if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
     6286  cat >>confdefs.h <<_ACEOF
     6287#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
     6288_ACEOF
     6289
     6290fi
     6291done
     6292
     6293
     6294ac_config_files="$ac_config_files Makefile src/driver/Makefile src/Makefile src/benchmark/Makefile src/examples/Makefile src/tests/Makefile src/tests/preempt_longrun/Makefile src/prelude/Makefile src/libcfa/Makefile tools/Makefile tools/prettyprinter/Makefile"
     6295
    169336296
    169346297cat >confcache <<\_ACEOF
     
    170576420fi
    170586421
    17059 if test -z "${ENABLE_DISTCC_TRUE}" && test -z "${ENABLE_DISTCC_FALSE}"; then
    17060   as_fn_error $? "conditional \"ENABLE_DISTCC\" was never defined.
     6422if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
     6423  as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
     6424Usually this means the macro was only invoked conditionally." "$LINENO" 5
     6425fi
     6426if test -z "${BUILD_RELEASE_TRUE}" && test -z "${BUILD_RELEASE_FALSE}"; then
     6427  as_fn_error $? "conditional \"BUILD_RELEASE\" was never defined.
     6428Usually this means the macro was only invoked conditionally." "$LINENO" 5
     6429fi
     6430if test -z "${BUILD_DEBUG_TRUE}" && test -z "${BUILD_DEBUG_FALSE}"; then
     6431  as_fn_error $? "conditional \"BUILD_DEBUG\" was never defined.
     6432Usually this means the macro was only invoked conditionally." "$LINENO" 5
     6433fi
     6434if test -z "${BUILD_NO_LIB_TRUE}" && test -z "${BUILD_NO_LIB_FALSE}"; then
     6435  as_fn_error $? "conditional \"BUILD_NO_LIB\" was never defined.
     6436Usually this means the macro was only invoked conditionally." "$LINENO" 5
     6437fi
     6438if test -z "${BUILD_CONCURRENCY_TRUE}" && test -z "${BUILD_CONCURRENCY_FALSE}"; then
     6439  as_fn_error $? "conditional \"BUILD_CONCURRENCY\" was never defined.
    170616440Usually this means the macro was only invoked conditionally." "$LINENO" 5
    170626441fi
     
    170756454if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
    170766455  as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined.
    17077 Usually this means the macro was only invoked conditionally." "$LINENO" 5
    17078 fi
    17079 if test -z "${WITH_LIBFIBRE_TRUE}" && test -z "${WITH_LIBFIBRE_FALSE}"; then
    17080   as_fn_error $? "conditional \"WITH_LIBFIBRE\" was never defined.
    17081 Usually this means the macro was only invoked conditionally." "$LINENO" 5
    17082 fi
    17083 if test -z "${WITH_LIBPROFILER_TRUE}" && test -z "${WITH_LIBPROFILER_FALSE}"; then
    17084   as_fn_error $? "conditional \"WITH_LIBPROFILER\" was never defined.
    17085 Usually this means the macro was only invoked conditionally." "$LINENO" 5
    17086 fi
    17087 if test -z "${WITH_LIBTCMALLOC_TRUE}" && test -z "${WITH_LIBTCMALLOC_FALSE}"; then
    17088   as_fn_error $? "conditional \"WITH_LIBTCMALLOC\" was never defined.
    170896456Usually this means the macro was only invoked conditionally." "$LINENO" 5
    170906457fi
     
    175136880config_files="$ac_config_files"
    175146881config_headers="$ac_config_headers"
    17515 config_links="$ac_config_links"
    175166882config_commands="$ac_config_commands"
    175176883
     
    175436909Configuration headers:
    175446910$config_headers
    17545 
    17546 Configuration links:
    17547 $config_links
    175486911
    175496912Configuration commands:
     
    176777040AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
    176787041
    17679 
    17680 # The HP-UX ksh and POSIX shell print the target directory to stdout
    17681 # if CDPATH is set.
    17682 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
    17683 
    17684 sed_quote_subst='$sed_quote_subst'
    17685 double_quote_subst='$double_quote_subst'
    17686 delay_variable_subst='$delay_variable_subst'
    17687 macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
    17688 macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
    17689 enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
    17690 enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
    17691 pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
    17692 enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
    17693 shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
    17694 SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
    17695 ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
    17696 PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
    17697 host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
    17698 host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
    17699 host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
    17700 build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
    17701 build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
    17702 build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
    17703 SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
    17704 Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
    17705 GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
    17706 EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
    17707 FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
    17708 LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
    17709 NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
    17710 LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
    17711 max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
    17712 ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
    17713 exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
    17714 lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
    17715 lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
    17716 lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
    17717 lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
    17718 lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
    17719 reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
    17720 reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
    17721 OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
    17722 deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
    17723 file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
    17724 file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
    17725 want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
    17726 DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
    17727 sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
    17728 AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
    17729 AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
    17730 archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
    17731 STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
    17732 RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
    17733 old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
    17734 old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
    17735 old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
    17736 lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
    17737 CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
    17738 CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
    17739 compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
    17740 GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
    17741 lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
    17742 lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
    17743 lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
    17744 lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
    17745 lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
    17746 lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
    17747 nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
    17748 lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
    17749 lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
    17750 objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
    17751 MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
    17752 lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
    17753 lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
    17754 lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
    17755 lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
    17756 lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
    17757 need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
    17758 MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
    17759 DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
    17760 NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
    17761 LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
    17762 OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
    17763 OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
    17764 libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
    17765 shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
    17766 extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
    17767 archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
    17768 enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
    17769 export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
    17770 whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
    17771 compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
    17772 old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
    17773 old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
    17774 archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
    17775 archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
    17776 module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
    17777 module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
    17778 with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
    17779 allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
    17780 no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
    17781 hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
    17782 hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
    17783 hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
    17784 hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
    17785 hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
    17786 hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
    17787 hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
    17788 inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
    17789 link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
    17790 always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
    17791 export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
    17792 exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
    17793 include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
    17794 prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
    17795 postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
    17796 file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
    17797 variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
    17798 need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
    17799 need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
    17800 version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
    17801 runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
    17802 shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
    17803 shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
    17804 libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
    17805 library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
    17806 soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
    17807 install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
    17808 postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
    17809 postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
    17810 finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
    17811 finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
    17812 hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
    17813 sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
    17814 configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
    17815 configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
    17816 hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
    17817 enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
    17818 enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
    17819 enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
    17820 old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
    17821 striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
    17822 compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`'
    17823 predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`'
    17824 postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`'
    17825 predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`'
    17826 postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`'
    17827 compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`'
    17828 LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`'
    17829 reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`'
    17830 reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17831 old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17832 compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
    17833 GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
    17834 lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
    17835 lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
    17836 lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
    17837 lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
    17838 lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
    17839 archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
    17840 enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`'
    17841 export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
    17842 whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
    17843 compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`'
    17844 old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17845 old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17846 archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17847 archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17848 module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17849 module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17850 with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
    17851 allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
    17852 no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
    17853 hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
    17854 hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
    17855 hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
    17856 hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
    17857 hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`'
    17858 hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`'
    17859 hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
    17860 inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
    17861 link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
    17862 always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
    17863 export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17864 exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
    17865 include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
    17866 prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17867 postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
    17868 file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
    17869 hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
    17870 compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
    17871 predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`'
    17872 postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`'
    17873 predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`'
    17874 postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`'
    17875 compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`'
    17876 
    17877 LTCC='$LTCC'
    17878 LTCFLAGS='$LTCFLAGS'
    17879 compiler='$compiler_DEFAULT'
    17880 
    17881 # A function that is used when there is no print builtin or printf.
    17882 func_fallback_echo ()
    17883 {
    17884   eval 'cat <<_LTECHO_EOF
    17885 \$1
    17886 _LTECHO_EOF'
    17887 }
    17888 
    17889 # Quote evaled strings.
    17890 for var in SHELL \
    17891 ECHO \
    17892 PATH_SEPARATOR \
    17893 SED \
    17894 GREP \
    17895 EGREP \
    17896 FGREP \
    17897 LD \
    17898 NM \
    17899 LN_S \
    17900 lt_SP2NL \
    17901 lt_NL2SP \
    17902 reload_flag \
    17903 OBJDUMP \
    17904 deplibs_check_method \
    17905 file_magic_cmd \
    17906 file_magic_glob \
    17907 want_nocaseglob \
    17908 DLLTOOL \
    17909 sharedlib_from_linklib_cmd \
    17910 AR \
    17911 AR_FLAGS \
    17912 archiver_list_spec \
    17913 STRIP \
    17914 RANLIB \
    17915 CC \
    17916 CFLAGS \
    17917 compiler \
    17918 lt_cv_sys_global_symbol_pipe \
    17919 lt_cv_sys_global_symbol_to_cdecl \
    17920 lt_cv_sys_global_symbol_to_import \
    17921 lt_cv_sys_global_symbol_to_c_name_address \
    17922 lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
    17923 lt_cv_nm_interface \
    17924 nm_file_list_spec \
    17925 lt_cv_truncate_bin \
    17926 lt_prog_compiler_no_builtin_flag \
    17927 lt_prog_compiler_pic \
    17928 lt_prog_compiler_wl \
    17929 lt_prog_compiler_static \
    17930 lt_cv_prog_compiler_c_o \
    17931 need_locks \
    17932 MANIFEST_TOOL \
    17933 DSYMUTIL \
    17934 NMEDIT \
    17935 LIPO \
    17936 OTOOL \
    17937 OTOOL64 \
    17938 shrext_cmds \
    17939 export_dynamic_flag_spec \
    17940 whole_archive_flag_spec \
    17941 compiler_needs_object \
    17942 with_gnu_ld \
    17943 allow_undefined_flag \
    17944 no_undefined_flag \
    17945 hardcode_libdir_flag_spec \
    17946 hardcode_libdir_separator \
    17947 exclude_expsyms \
    17948 include_expsyms \
    17949 file_list_spec \
    17950 variables_saved_for_relink \
    17951 libname_spec \
    17952 library_names_spec \
    17953 soname_spec \
    17954 install_override_mode \
    17955 finish_eval \
    17956 old_striplib \
    17957 striplib \
    17958 compiler_lib_search_dirs \
    17959 predep_objects \
    17960 postdep_objects \
    17961 predeps \
    17962 postdeps \
    17963 compiler_lib_search_path \
    17964 LD_CXX \
    17965 reload_flag_CXX \
    17966 compiler_CXX \
    17967 lt_prog_compiler_no_builtin_flag_CXX \
    17968 lt_prog_compiler_pic_CXX \
    17969 lt_prog_compiler_wl_CXX \
    17970 lt_prog_compiler_static_CXX \
    17971 lt_cv_prog_compiler_c_o_CXX \
    17972 export_dynamic_flag_spec_CXX \
    17973 whole_archive_flag_spec_CXX \
    17974 compiler_needs_object_CXX \
    17975 with_gnu_ld_CXX \
    17976 allow_undefined_flag_CXX \
    17977 no_undefined_flag_CXX \
    17978 hardcode_libdir_flag_spec_CXX \
    17979 hardcode_libdir_separator_CXX \
    17980 exclude_expsyms_CXX \
    17981 include_expsyms_CXX \
    17982 file_list_spec_CXX \
    17983 compiler_lib_search_dirs_CXX \
    17984 predep_objects_CXX \
    17985 postdep_objects_CXX \
    17986 predeps_CXX \
    17987 postdeps_CXX \
    17988 compiler_lib_search_path_CXX; do
    17989     case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
    17990     *[\\\\\\\`\\"\\\$]*)
    17991       eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
    17992       ;;
    17993     *)
    17994       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
    17995       ;;
    17996     esac
    17997 done
    17998 
    17999 # Double-quote double-evaled strings.
    18000 for var in reload_cmds \
    18001 old_postinstall_cmds \
    18002 old_postuninstall_cmds \
    18003 old_archive_cmds \
    18004 extract_expsyms_cmds \
    18005 old_archive_from_new_cmds \
    18006 old_archive_from_expsyms_cmds \
    18007 archive_cmds \
    18008 archive_expsym_cmds \
    18009 module_cmds \
    18010 module_expsym_cmds \
    18011 export_symbols_cmds \
    18012 prelink_cmds \
    18013 postlink_cmds \
    18014 postinstall_cmds \
    18015 postuninstall_cmds \
    18016 finish_cmds \
    18017 sys_lib_search_path_spec \
    18018 configure_time_dlsearch_path \
    18019 configure_time_lt_sys_library_path \
    18020 reload_cmds_CXX \
    18021 old_archive_cmds_CXX \
    18022 old_archive_from_new_cmds_CXX \
    18023 old_archive_from_expsyms_cmds_CXX \
    18024 archive_cmds_CXX \
    18025 archive_expsym_cmds_CXX \
    18026 module_cmds_CXX \
    18027 module_expsym_cmds_CXX \
    18028 export_symbols_cmds_CXX \
    18029 prelink_cmds_CXX \
    18030 postlink_cmds_CXX; do
    18031     case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
    18032     *[\\\\\\\`\\"\\\$]*)
    18033       eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
    18034       ;;
    18035     *)
    18036       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
    18037       ;;
    18038     esac
    18039 done
    18040 
    18041 ac_aux_dir='$ac_aux_dir'
    18042 
    18043 # See if we are running on zsh, and set the options that allow our
    18044 # commands through without removal of \ escapes INIT.
    18045 if test -n "\${ZSH_VERSION+set}"; then
    18046    setopt NO_GLOB_SUBST
    18047 fi
    18048 
    18049 
    18050     PACKAGE='$PACKAGE'
    18051     VERSION='$VERSION'
    18052     RM='$RM'
    18053     ofile='$ofile'
    18054 
    18055 
    18056 
    18057 
    18058 
    18059 
    180607042_ACEOF
    180617043
     
    180667048do
    180677049  case $ac_config_target in
    18068     "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:src/config.h.in" ;;
     7050    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
    180697051    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
    18070     "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
    180717052    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
    18072     "driver/Makefile") CONFIG_FILES="$CONFIG_FILES driver/Makefile" ;;
     7053    "src/driver/Makefile") CONFIG_FILES="$CONFIG_FILES src/driver/Makefile" ;;
    180737054    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
    18074     "benchmark/Makefile") CONFIG_FILES="$CONFIG_FILES benchmark/Makefile" ;;
    18075     "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
    18076     "longrun_tests/Makefile") CONFIG_FILES="$CONFIG_FILES longrun_tests/Makefile" ;;
     7055    "src/benchmark/Makefile") CONFIG_FILES="$CONFIG_FILES src/benchmark/Makefile" ;;
     7056    "src/examples/Makefile") CONFIG_FILES="$CONFIG_FILES src/examples/Makefile" ;;
     7057    "src/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/tests/Makefile" ;;
     7058    "src/tests/preempt_longrun/Makefile") CONFIG_FILES="$CONFIG_FILES src/tests/preempt_longrun/Makefile" ;;
     7059    "src/prelude/Makefile") CONFIG_FILES="$CONFIG_FILES src/prelude/Makefile" ;;
     7060    "src/libcfa/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcfa/Makefile" ;;
    180777061    "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
    180787062    "tools/prettyprinter/Makefile") CONFIG_FILES="$CONFIG_FILES tools/prettyprinter/Makefile" ;;
    18079     "tests/test.py") CONFIG_LINKS="$CONFIG_LINKS tests/test.py:tests/test.py" ;;
    18080     "tests/config.py") CONFIG_FILES="$CONFIG_FILES tests/config.py" ;;
    180817063
    180827064  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
     
    180927074  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
    180937075  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
    18094   test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
    180957076  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
    180967077fi
     
    183907371
    183917372
    18392 eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS  :L $CONFIG_LINKS  :C $CONFIG_COMMANDS"
     7373eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
    183937374shift
    183947375for ac_tag
     
    186677648          s/.*/./; q'`/stamp-h$_am_stamp_count
    186687649 ;;
    18669   :L)
    18670   #
    18671   # CONFIG_LINK
    18672   #
    18673 
    18674   if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then
    18675     :
    18676   else
    18677     # Prefer the file from the source tree if names are identical.
    18678     if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then
    18679       ac_source=$srcdir/$ac_source
    18680     fi
    18681 
    18682     { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5
    18683 $as_echo "$as_me: linking $ac_source to $ac_file" >&6;}
    18684 
    18685     if test ! -r "$ac_source"; then
    18686       as_fn_error $? "$ac_source: file not found" "$LINENO" 5
    18687     fi
    18688     rm -f "$ac_file"
    18689 
    18690     # Try a relative symlink, then a hard link, then a copy.
    18691     case $ac_source in
    18692     [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;;
    18693         *) ac_rel_source=$ac_top_build_prefix$ac_source ;;
    18694     esac
    18695     ln -s "$ac_rel_source" "$ac_file" 2>/dev/null ||
    18696       ln "$ac_source" "$ac_file" 2>/dev/null ||
    18697       cp -p "$ac_source" "$ac_file" ||
    18698       as_fn_error $? "cannot link or copy $ac_source to $ac_file" "$LINENO" 5
    18699   fi
    18700  ;;
     7650
    187017651  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
    187027652$as_echo "$as_me: executing $ac_file commands" >&6;}
     
    187997749}
    188007750 ;;
    18801     "libtool":C)
    18802 
    18803     # See if we are running on zsh, and set the options that allow our
    18804     # commands through without removal of \ escapes.
    18805     if test -n "${ZSH_VERSION+set}"; then
    18806       setopt NO_GLOB_SUBST
    18807     fi
    18808 
    18809     cfgfile=${ofile}T
    18810     trap "$RM \"$cfgfile\"; exit 1" 1 2 15
    18811     $RM "$cfgfile"
    18812 
    18813     cat <<_LT_EOF >> "$cfgfile"
    18814 #! $SHELL
    18815 # Generated automatically by $as_me ($PACKAGE) $VERSION
    18816 # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
    18817 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
    18818 
    18819 # Provide generalized library-building support services.
    18820 # Written by Gordon Matzigkeit, 1996
    18821 
    18822 # Copyright (C) 2014 Free Software Foundation, Inc.
    18823 # This is free software; see the source for copying conditions.  There is NO
    18824 # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    18825 
    18826 # GNU Libtool is free software; you can redistribute it and/or modify
    18827 # it under the terms of the GNU General Public License as published by
    18828 # the Free Software Foundation; either version 2 of of the License, or
    18829 # (at your option) any later version.
    18830 #
    18831 # As a special exception to the GNU General Public License, if you
    18832 # distribute this file as part of a program or library that is built
    18833 # using GNU Libtool, you may include this file under the  same
    18834 # distribution terms that you use for the rest of that program.
    18835 #
    18836 # GNU Libtool is distributed in the hope that it will be useful, but
    18837 # WITHOUT ANY WARRANTY; without even the implied warranty of
    18838 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    18839 # GNU General Public License for more details.
    18840 #
    18841 # You should have received a copy of the GNU General Public License
    18842 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18843 
    18844 
    18845 # The names of the tagged configurations supported by this script.
    18846 available_tags='CXX '
    18847 
    18848 # Configured defaults for sys_lib_dlsearch_path munging.
    18849 : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
    18850 
    18851 # ### BEGIN LIBTOOL CONFIG
    18852 
    18853 # Which release of libtool.m4 was used?
    18854 macro_version=$macro_version
    18855 macro_revision=$macro_revision
    18856 
    18857 # Whether or not to build shared libraries.
    18858 build_libtool_libs=$enable_shared
    18859 
    18860 # Whether or not to build static libraries.
    18861 build_old_libs=$enable_static
    18862 
    18863 # What type of objects to build.
    18864 pic_mode=$pic_mode
    18865 
    18866 # Whether or not to optimize for fast installation.
    18867 fast_install=$enable_fast_install
    18868 
    18869 # Shared archive member basename,for filename based shared library versioning on AIX.
    18870 shared_archive_member_spec=$shared_archive_member_spec
    18871 
    18872 # Shell to use when invoking shell scripts.
    18873 SHELL=$lt_SHELL
    18874 
    18875 # An echo program that protects backslashes.
    18876 ECHO=$lt_ECHO
    18877 
    18878 # The PATH separator for the build system.
    18879 PATH_SEPARATOR=$lt_PATH_SEPARATOR
    18880 
    18881 # The host system.
    18882 host_alias=$host_alias
    18883 host=$host
    18884 host_os=$host_os
    18885 
    18886 # The build system.
    18887 build_alias=$build_alias
    18888 build=$build
    18889 build_os=$build_os
    18890 
    18891 # A sed program that does not truncate output.
    18892 SED=$lt_SED
    18893 
    18894 # Sed that helps us avoid accidentally triggering echo(1) options like -n.
    18895 Xsed="\$SED -e 1s/^X//"
    18896 
    18897 # A grep program that handles long lines.
    18898 GREP=$lt_GREP
    18899 
    18900 # An ERE matcher.
    18901 EGREP=$lt_EGREP
    18902 
    18903 # A literal string matcher.
    18904 FGREP=$lt_FGREP
    18905 
    18906 # A BSD- or MS-compatible name lister.
    18907 NM=$lt_NM
    18908 
    18909 # Whether we need soft or hard links.
    18910 LN_S=$lt_LN_S
    18911 
    18912 # What is the maximum length of a command?
    18913 max_cmd_len=$max_cmd_len
    18914 
    18915 # Object file suffix (normally "o").
    18916 objext=$ac_objext
    18917 
    18918 # Executable file suffix (normally "").
    18919 exeext=$exeext
    18920 
    18921 # whether the shell understands "unset".
    18922 lt_unset=$lt_unset
    18923 
    18924 # turn spaces into newlines.
    18925 SP2NL=$lt_lt_SP2NL
    18926 
    18927 # turn newlines into spaces.
    18928 NL2SP=$lt_lt_NL2SP
    18929 
    18930 # convert \$build file names to \$host format.
    18931 to_host_file_cmd=$lt_cv_to_host_file_cmd
    18932 
    18933 # convert \$build files to toolchain format.
    18934 to_tool_file_cmd=$lt_cv_to_tool_file_cmd
    18935 
    18936 # An object symbol dumper.
    18937 OBJDUMP=$lt_OBJDUMP
    18938 
    18939 # Method to check whether dependent libraries are shared objects.
    18940 deplibs_check_method=$lt_deplibs_check_method
    18941 
    18942 # Command to use when deplibs_check_method = "file_magic".
    18943 file_magic_cmd=$lt_file_magic_cmd
    18944 
    18945 # How to find potential files when deplibs_check_method = "file_magic".
    18946 file_magic_glob=$lt_file_magic_glob
    18947 
    18948 # Find potential files using nocaseglob when deplibs_check_method = "file_magic".
    18949 want_nocaseglob=$lt_want_nocaseglob
    18950 
    18951 # DLL creation program.
    18952 DLLTOOL=$lt_DLLTOOL
    18953 
    18954 # Command to associate shared and link libraries.
    18955 sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
    18956 
    18957 # The archiver.
    18958 AR=$lt_AR
    18959 
    18960 # Flags to create an archive.
    18961 AR_FLAGS=$lt_AR_FLAGS
    18962 
    18963 # How to feed a file listing to the archiver.
    18964 archiver_list_spec=$lt_archiver_list_spec
    18965 
    18966 # A symbol stripping program.
    18967 STRIP=$lt_STRIP
    18968 
    18969 # Commands used to install an old-style archive.
    18970 RANLIB=$lt_RANLIB
    18971 old_postinstall_cmds=$lt_old_postinstall_cmds
    18972 old_postuninstall_cmds=$lt_old_postuninstall_cmds
    18973 
    18974 # Whether to use a lock for old archive extraction.
    18975 lock_old_archive_extraction=$lock_old_archive_extraction
    18976 
    18977 # A C compiler.
    18978 LTCC=$lt_CC
    18979 
    18980 # LTCC compiler flags.
    18981 LTCFLAGS=$lt_CFLAGS
    18982 
    18983 # Take the output of nm and produce a listing of raw symbols and C names.
    18984 global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
    18985 
    18986 # Transform the output of nm in a proper C declaration.
    18987 global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
    18988 
    18989 # Transform the output of nm into a list of symbols to manually relocate.
    18990 global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
    18991 
    18992 # Transform the output of nm in a C name address pair.
    18993 global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
    18994 
    18995 # Transform the output of nm in a C name address pair when lib prefix is needed.
    18996 global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
    18997 
    18998 # The name lister interface.
    18999 nm_interface=$lt_lt_cv_nm_interface
    19000 
    19001 # Specify filename containing input files for \$NM.
    19002 nm_file_list_spec=$lt_nm_file_list_spec
    19003 
    19004 # The root where to search for dependent libraries,and where our libraries should be installed.
    19005 lt_sysroot=$lt_sysroot
    19006 
    19007 # Command to truncate a binary pipe.
    19008 lt_truncate_bin=$lt_lt_cv_truncate_bin
    19009 
    19010 # The name of the directory that contains temporary libtool files.
    19011 objdir=$objdir
    19012 
    19013 # Used to examine libraries when file_magic_cmd begins with "file".
    19014 MAGIC_CMD=$MAGIC_CMD
    19015 
    19016 # Must we lock files when doing compilation?
    19017 need_locks=$lt_need_locks
    19018 
    19019 # Manifest tool.
    19020 MANIFEST_TOOL=$lt_MANIFEST_TOOL
    19021 
    19022 # Tool to manipulate archived DWARF debug symbol files on Mac OS X.
    19023 DSYMUTIL=$lt_DSYMUTIL
    19024 
    19025 # Tool to change global to local symbols on Mac OS X.
    19026 NMEDIT=$lt_NMEDIT
    19027 
    19028 # Tool to manipulate fat objects and archives on Mac OS X.
    19029 LIPO=$lt_LIPO
    19030 
    19031 # ldd/readelf like tool for Mach-O binaries on Mac OS X.
    19032 OTOOL=$lt_OTOOL
    19033 
    19034 # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
    19035 OTOOL64=$lt_OTOOL64
    19036 
    19037 # Old archive suffix (normally "a").
    19038 libext=$libext
    19039 
    19040 # Shared library suffix (normally ".so").
    19041 shrext_cmds=$lt_shrext_cmds
    19042 
    19043 # The commands to extract the exported symbol list from a shared archive.
    19044 extract_expsyms_cmds=$lt_extract_expsyms_cmds
    19045 
    19046 # Variables whose values should be saved in libtool wrapper scripts and
    19047 # restored at link time.
    19048 variables_saved_for_relink=$lt_variables_saved_for_relink
    19049 
    19050 # Do we need the "lib" prefix for modules?
    19051 need_lib_prefix=$need_lib_prefix
    19052 
    19053 # Do we need a version for libraries?
    19054 need_version=$need_version
    19055 
    19056 # Library versioning type.
    19057 version_type=$version_type
    19058 
    19059 # Shared library runtime path variable.
    19060 runpath_var=$runpath_var
    19061 
    19062 # Shared library path variable.
    19063 shlibpath_var=$shlibpath_var
    19064 
    19065 # Is shlibpath searched before the hard-coded library search path?
    19066 shlibpath_overrides_runpath=$shlibpath_overrides_runpath
    19067 
    19068 # Format of library name prefix.
    19069 libname_spec=$lt_libname_spec
    19070 
    19071 # List of archive names.  First name is the real one, the rest are links.
    19072 # The last name is the one that the linker finds with -lNAME
    19073 library_names_spec=$lt_library_names_spec
    19074 
    19075 # The coded name of the library, if different from the real name.
    19076 soname_spec=$lt_soname_spec
    19077 
    19078 # Permission mode override for installation of shared libraries.
    19079 install_override_mode=$lt_install_override_mode
    19080 
    19081 # Command to use after installation of a shared archive.
    19082 postinstall_cmds=$lt_postinstall_cmds
    19083 
    19084 # Command to use after uninstallation of a shared archive.
    19085 postuninstall_cmds=$lt_postuninstall_cmds
    19086 
    19087 # Commands used to finish a libtool library installation in a directory.
    19088 finish_cmds=$lt_finish_cmds
    19089 
    19090 # As "finish_cmds", except a single script fragment to be evaled but
    19091 # not shown.
    19092 finish_eval=$lt_finish_eval
    19093 
    19094 # Whether we should hardcode library paths into libraries.
    19095 hardcode_into_libs=$hardcode_into_libs
    19096 
    19097 # Compile-time system search path for libraries.
    19098 sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
    19099 
    19100 # Detected run-time system search path for libraries.
    19101 sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
    19102 
    19103 # Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
    19104 configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
    19105 
    19106 # Whether dlopen is supported.
    19107 dlopen_support=$enable_dlopen
    19108 
    19109 # Whether dlopen of programs is supported.
    19110 dlopen_self=$enable_dlopen_self
    19111 
    19112 # Whether dlopen of statically linked programs is supported.
    19113 dlopen_self_static=$enable_dlopen_self_static
    19114 
    19115 # Commands to strip libraries.
    19116 old_striplib=$lt_old_striplib
    19117 striplib=$lt_striplib
    19118 
    19119 
    19120 # The linker used to build libraries.
    19121 LD=$lt_LD
    19122 
    19123 # How to create reloadable object files.
    19124 reload_flag=$lt_reload_flag
    19125 reload_cmds=$lt_reload_cmds
    19126 
    19127 # Commands used to build an old-style archive.
    19128 old_archive_cmds=$lt_old_archive_cmds
    19129 
    19130 # A language specific compiler.
    19131 CC=$lt_compiler
    19132 
    19133 # Is the compiler the GNU compiler?
    19134 with_gcc=$GCC
    19135 
    19136 # Compiler flag to turn off builtin functions.
    19137 no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
    19138 
    19139 # Additional compiler flags for building library objects.
    19140 pic_flag=$lt_lt_prog_compiler_pic
    19141 
    19142 # How to pass a linker flag through the compiler.
    19143 wl=$lt_lt_prog_compiler_wl
    19144 
    19145 # Compiler flag to prevent dynamic linking.
    19146 link_static_flag=$lt_lt_prog_compiler_static
    19147 
    19148 # Does compiler simultaneously support -c and -o options?
    19149 compiler_c_o=$lt_lt_cv_prog_compiler_c_o
    19150 
    19151 # Whether or not to add -lc for building shared libraries.
    19152 build_libtool_need_lc=$archive_cmds_need_lc
    19153 
    19154 # Whether or not to disallow shared libs when runtime libs are static.
    19155 allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
    19156 
    19157 # Compiler flag to allow reflexive dlopens.
    19158 export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
    19159 
    19160 # Compiler flag to generate shared objects directly from archives.
    19161 whole_archive_flag_spec=$lt_whole_archive_flag_spec
    19162 
    19163 # Whether the compiler copes with passing no objects directly.
    19164 compiler_needs_object=$lt_compiler_needs_object
    19165 
    19166 # Create an old-style archive from a shared archive.
    19167 old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
    19168 
    19169 # Create a temporary old-style archive to link instead of a shared archive.
    19170 old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
    19171 
    19172 # Commands used to build a shared archive.
    19173 archive_cmds=$lt_archive_cmds
    19174 archive_expsym_cmds=$lt_archive_expsym_cmds
    19175 
    19176 # Commands used to build a loadable module if different from building
    19177 # a shared archive.
    19178 module_cmds=$lt_module_cmds
    19179 module_expsym_cmds=$lt_module_expsym_cmds
    19180 
    19181 # Whether we are building with GNU ld or not.
    19182 with_gnu_ld=$lt_with_gnu_ld
    19183 
    19184 # Flag that allows shared libraries with undefined symbols to be built.
    19185 allow_undefined_flag=$lt_allow_undefined_flag
    19186 
    19187 # Flag that enforces no undefined symbols.
    19188 no_undefined_flag=$lt_no_undefined_flag
    19189 
    19190 # Flag to hardcode \$libdir into a binary during linking.
    19191 # This must work even if \$libdir does not exist
    19192 hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
    19193 
    19194 # Whether we need a single "-rpath" flag with a separated argument.
    19195 hardcode_libdir_separator=$lt_hardcode_libdir_separator
    19196 
    19197 # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
    19198 # DIR into the resulting binary.
    19199 hardcode_direct=$hardcode_direct
    19200 
    19201 # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
    19202 # DIR into the resulting binary and the resulting library dependency is
    19203 # "absolute",i.e impossible to change by setting \$shlibpath_var if the
    19204 # library is relocated.
    19205 hardcode_direct_absolute=$hardcode_direct_absolute
    19206 
    19207 # Set to "yes" if using the -LDIR flag during linking hardcodes DIR
    19208 # into the resulting binary.
    19209 hardcode_minus_L=$hardcode_minus_L
    19210 
    19211 # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
    19212 # into the resulting binary.
    19213 hardcode_shlibpath_var=$hardcode_shlibpath_var
    19214 
    19215 # Set to "yes" if building a shared library automatically hardcodes DIR
    19216 # into the library and all subsequent libraries and executables linked
    19217 # against it.
    19218 hardcode_automatic=$hardcode_automatic
    19219 
    19220 # Set to yes if linker adds runtime paths of dependent libraries
    19221 # to runtime path list.
    19222 inherit_rpath=$inherit_rpath
    19223 
    19224 # Whether libtool must link a program against all its dependency libraries.
    19225 link_all_deplibs=$link_all_deplibs
    19226 
    19227 # Set to "yes" if exported symbols are required.
    19228 always_export_symbols=$always_export_symbols
    19229 
    19230 # The commands to list exported symbols.
    19231 export_symbols_cmds=$lt_export_symbols_cmds
    19232 
    19233 # Symbols that should not be listed in the preloaded symbols.
    19234 exclude_expsyms=$lt_exclude_expsyms
    19235 
    19236 # Symbols that must always be exported.
    19237 include_expsyms=$lt_include_expsyms
    19238 
    19239 # Commands necessary for linking programs (against libraries) with templates.
    19240 prelink_cmds=$lt_prelink_cmds
    19241 
    19242 # Commands necessary for finishing linking programs.
    19243 postlink_cmds=$lt_postlink_cmds
    19244 
    19245 # Specify filename containing input files.
    19246 file_list_spec=$lt_file_list_spec
    19247 
    19248 # How to hardcode a shared library path into an executable.
    19249 hardcode_action=$hardcode_action
    19250 
    19251 # The directories searched by this compiler when creating a shared library.
    19252 compiler_lib_search_dirs=$lt_compiler_lib_search_dirs
    19253 
    19254 # Dependencies to place before and after the objects being linked to
    19255 # create a shared library.
    19256 predep_objects=$lt_predep_objects
    19257 postdep_objects=$lt_postdep_objects
    19258 predeps=$lt_predeps
    19259 postdeps=$lt_postdeps
    19260 
    19261 # The library search path used internally by the compiler when linking
    19262 # a shared library.
    19263 compiler_lib_search_path=$lt_compiler_lib_search_path
    19264 
    19265 # ### END LIBTOOL CONFIG
    19266 
    19267 _LT_EOF
    19268 
    19269     cat <<'_LT_EOF' >> "$cfgfile"
    19270 
    19271 # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
    19272 
    19273 # func_munge_path_list VARIABLE PATH
    19274 # -----------------------------------
    19275 # VARIABLE is name of variable containing _space_ separated list of
    19276 # directories to be munged by the contents of PATH, which is string
    19277 # having a format:
    19278 # "DIR[:DIR]:"
    19279 #       string "DIR[ DIR]" will be prepended to VARIABLE
    19280 # ":DIR[:DIR]"
    19281 #       string "DIR[ DIR]" will be appended to VARIABLE
    19282 # "DIRP[:DIRP]::[DIRA:]DIRA"
    19283 #       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
    19284 #       "DIRA[ DIRA]" will be appended to VARIABLE
    19285 # "DIR[:DIR]"
    19286 #       VARIABLE will be replaced by "DIR[ DIR]"
    19287 func_munge_path_list ()
    19288 {
    19289     case x$2 in
    19290     x)
    19291         ;;
    19292     *:)
    19293         eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
    19294         ;;
    19295     x:*)
    19296         eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
    19297         ;;
    19298     *::*)
    19299         eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
    19300         eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
    19301         ;;
    19302     *)
    19303         eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
    19304         ;;
    19305     esac
    19306 }
    19307 
    19308 
    19309 # Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
    19310 func_cc_basename ()
    19311 {
    19312     for cc_temp in $*""; do
    19313       case $cc_temp in
    19314         compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
    19315         distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
    19316         \-*) ;;
    19317         *) break;;
    19318       esac
    19319     done
    19320     func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
    19321 }
    19322 
    19323 
    19324 # ### END FUNCTIONS SHARED WITH CONFIGURE
    19325 
    19326 _LT_EOF
    19327 
    19328   case $host_os in
    19329   aix3*)
    19330     cat <<\_LT_EOF >> "$cfgfile"
    19331 # AIX sometimes has problems with the GCC collect2 program.  For some
    19332 # reason, if we set the COLLECT_NAMES environment variable, the problems
    19333 # vanish in a puff of smoke.
    19334 if test set != "${COLLECT_NAMES+set}"; then
    19335   COLLECT_NAMES=
    19336   export COLLECT_NAMES
    19337 fi
    19338 _LT_EOF
    19339     ;;
    19340   esac
    19341 
    19342 
    19343 ltmain=$ac_aux_dir/ltmain.sh
    19344 
    19345 
    19346   # We use sed instead of cat because bash on DJGPP gets confused if
    19347   # if finds mixed CR/LF and LF-only lines.  Since sed operates in
    19348   # text mode, it properly converts lines to CR/LF.  This bash problem
    19349   # is reportedly fixed, but why not run on old versions too?
    19350   sed '$q' "$ltmain" >> "$cfgfile" \
    19351      || (rm -f "$cfgfile"; exit 1)
    19352 
    19353    mv -f "$cfgfile" "$ofile" ||
    19354     (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
    19355   chmod +x "$ofile"
    19356 
    19357 
    19358     cat <<_LT_EOF >> "$ofile"
    19359 
    19360 # ### BEGIN LIBTOOL TAG CONFIG: CXX
    19361 
    19362 # The linker used to build libraries.
    19363 LD=$lt_LD_CXX
    19364 
    19365 # How to create reloadable object files.
    19366 reload_flag=$lt_reload_flag_CXX
    19367 reload_cmds=$lt_reload_cmds_CXX
    19368 
    19369 # Commands used to build an old-style archive.
    19370 old_archive_cmds=$lt_old_archive_cmds_CXX
    19371 
    19372 # A language specific compiler.
    19373 CC=$lt_compiler_CXX
    19374 
    19375 # Is the compiler the GNU compiler?
    19376 with_gcc=$GCC_CXX
    19377 
    19378 # Compiler flag to turn off builtin functions.
    19379 no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
    19380 
    19381 # Additional compiler flags for building library objects.
    19382 pic_flag=$lt_lt_prog_compiler_pic_CXX
    19383 
    19384 # How to pass a linker flag through the compiler.
    19385 wl=$lt_lt_prog_compiler_wl_CXX
    19386 
    19387 # Compiler flag to prevent dynamic linking.
    19388 link_static_flag=$lt_lt_prog_compiler_static_CXX
    19389 
    19390 # Does compiler simultaneously support -c and -o options?
    19391 compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
    19392 
    19393 # Whether or not to add -lc for building shared libraries.
    19394 build_libtool_need_lc=$archive_cmds_need_lc_CXX
    19395 
    19396 # Whether or not to disallow shared libs when runtime libs are static.
    19397 allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
    19398 
    19399 # Compiler flag to allow reflexive dlopens.
    19400 export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
    19401 
    19402 # Compiler flag to generate shared objects directly from archives.
    19403 whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
    19404 
    19405 # Whether the compiler copes with passing no objects directly.
    19406 compiler_needs_object=$lt_compiler_needs_object_CXX
    19407 
    19408 # Create an old-style archive from a shared archive.
    19409 old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
    19410 
    19411 # Create a temporary old-style archive to link instead of a shared archive.
    19412 old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
    19413 
    19414 # Commands used to build a shared archive.
    19415 archive_cmds=$lt_archive_cmds_CXX
    19416 archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
    19417 
    19418 # Commands used to build a loadable module if different from building
    19419 # a shared archive.
    19420 module_cmds=$lt_module_cmds_CXX
    19421 module_expsym_cmds=$lt_module_expsym_cmds_CXX
    19422 
    19423 # Whether we are building with GNU ld or not.
    19424 with_gnu_ld=$lt_with_gnu_ld_CXX
    19425 
    19426 # Flag that allows shared libraries with undefined symbols to be built.
    19427 allow_undefined_flag=$lt_allow_undefined_flag_CXX
    19428 
    19429 # Flag that enforces no undefined symbols.
    19430 no_undefined_flag=$lt_no_undefined_flag_CXX
    19431 
    19432 # Flag to hardcode \$libdir into a binary during linking.
    19433 # This must work even if \$libdir does not exist
    19434 hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
    19435 
    19436 # Whether we need a single "-rpath" flag with a separated argument.
    19437 hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
    19438 
    19439 # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
    19440 # DIR into the resulting binary.
    19441 hardcode_direct=$hardcode_direct_CXX
    19442 
    19443 # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
    19444 # DIR into the resulting binary and the resulting library dependency is
    19445 # "absolute",i.e impossible to change by setting \$shlibpath_var if the
    19446 # library is relocated.
    19447 hardcode_direct_absolute=$hardcode_direct_absolute_CXX
    19448 
    19449 # Set to "yes" if using the -LDIR flag during linking hardcodes DIR
    19450 # into the resulting binary.
    19451 hardcode_minus_L=$hardcode_minus_L_CXX
    19452 
    19453 # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
    19454 # into the resulting binary.
    19455 hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
    19456 
    19457 # Set to "yes" if building a shared library automatically hardcodes DIR
    19458 # into the library and all subsequent libraries and executables linked
    19459 # against it.
    19460 hardcode_automatic=$hardcode_automatic_CXX
    19461 
    19462 # Set to yes if linker adds runtime paths of dependent libraries
    19463 # to runtime path list.
    19464 inherit_rpath=$inherit_rpath_CXX
    19465 
    19466 # Whether libtool must link a program against all its dependency libraries.
    19467 link_all_deplibs=$link_all_deplibs_CXX
    19468 
    19469 # Set to "yes" if exported symbols are required.
    19470 always_export_symbols=$always_export_symbols_CXX
    19471 
    19472 # The commands to list exported symbols.
    19473 export_symbols_cmds=$lt_export_symbols_cmds_CXX
    19474 
    19475 # Symbols that should not be listed in the preloaded symbols.
    19476 exclude_expsyms=$lt_exclude_expsyms_CXX
    19477 
    19478 # Symbols that must always be exported.
    19479 include_expsyms=$lt_include_expsyms_CXX
    19480 
    19481 # Commands necessary for linking programs (against libraries) with templates.
    19482 prelink_cmds=$lt_prelink_cmds_CXX
    19483 
    19484 # Commands necessary for finishing linking programs.
    19485 postlink_cmds=$lt_postlink_cmds_CXX
    19486 
    19487 # Specify filename containing input files.
    19488 file_list_spec=$lt_file_list_spec_CXX
    19489 
    19490 # How to hardcode a shared library path into an executable.
    19491 hardcode_action=$hardcode_action_CXX
    19492 
    19493 # The directories searched by this compiler when creating a shared library.
    19494 compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX
    19495 
    19496 # Dependencies to place before and after the objects being linked to
    19497 # create a shared library.
    19498 predep_objects=$lt_predep_objects_CXX
    19499 postdep_objects=$lt_postdep_objects_CXX
    19500 predeps=$lt_predeps_CXX
    19501 postdeps=$lt_postdeps_CXX
    19502 
    19503 # The library search path used internally by the compiler when linking
    19504 # a shared library.
    19505 compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
    19506 
    19507 # ### END LIBTOOL TAG CONFIG: CXX
    19508 _LT_EOF
    19509 
    19510  ;;
    195117751
    195127752  esac
     
    195487788
    195497789
     7790if test -z "$BUILD_RELEASE_TRUE"; then :
     7791  if test -z "$BUILD_DEBUG_TRUE"; then :
     7792  { $as_echo "$as_me:${as_lineno-$LINENO}: Building libcfa for target: release & debug" >&5
     7793$as_echo "$as_me: Building libcfa for target: release & debug" >&6;}
     7794else
     7795  { $as_echo "$as_me:${as_lineno-$LINENO}: Building libcfa for target: release" >&5
     7796$as_echo "$as_me: Building libcfa for target: release" >&6;}
     7797fi
     7798else
     7799  if test -z "$BUILD_DEBUG_TRUE"; then :
     7800  { $as_echo "$as_me:${as_lineno-$LINENO}: Building libcfa for target: debug" >&5
     7801$as_echo "$as_me: Building libcfa for target: debug" >&6;}
     7802else
     7803  { $as_echo "$as_me:${as_lineno-$LINENO}: Running cfa without libcfa" >&5
     7804$as_echo "$as_me: Running cfa without libcfa" >&6;}
     7805fi
     7806fi
     7807
    195507808# Final text
    195517809{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Cforall configuraton completed. Type \"make -j 8 install\"." >&5
  • configure.ac

    rb067d9b r7951100  
    55AC_INIT([cfa-cc],[1.0.0.0],[cforall@plg.uwaterloo.ca])
    66AC_CONFIG_AUX_DIR([automake])
    7 AC_CONFIG_MACRO_DIRS([automake])
    87#AC_CONFIG_SRCDIR([src/main.cc])
    9 AC_CONFIG_HEADERS([config.h:src/config.h.in])
    10 AM_SILENT_RULES([yes])
    11 
    12 m4_include([automake/cfa.m4])
    13 
    14 # don't use the default CFLAGS as they unconditonnaly add -O2
    15 : ${CFLAGS=""}
     8AC_CONFIG_HEADERS([config.h])
     9AM_SILENT_RULES([no])
    1610
    1711AM_INIT_AUTOMAKE([subdir-objects])
     12AM_MAINTAINER_MODE(enable)                      # may require auto* software to be installed
    1813
    1914# Allow program name tansformation
     
    2116AC_ARG_PROGRAM
    2217
    23 #==============================================================================
    2418#Trasforming cc1 will break compilation
    25 M4CFA_PROGRAM_NAME
    26 
    27 #==============================================================================
    28 # version information
     19if test "${program_transform_name}" = ""; then
     20    AC_MSG_ERROR([Program transform not supported.
     21                Use --with-cfa-name='[[Desired name here]]' instead])
     22fi
     23
     24AC_ARG_WITH(cfa-name,
     25        [  --with-cfa-name=NAME     NAME too which cfa will be installed],
     26        cfa_name=$withval, cfa_name="cfa")
     27
     28#Define the new name of the installed command
     29AC_SUBST(CFA_NAME, ${cfa_name})
    2930
    3031rm -f version
     
    4647AC_DEFINE_UNQUOTED(CFA_VERSION_FULL, ["${ver_major}.${ver_minor}.${ver_patch}.${ver_build}"], [Major.Minor.Patch.Build])
    4748
    48 #==============================================================================
    49 # HACK to be able to use conditionnals inside makefiles
     49# Installation paths
     50
     51AC_ARG_WITH(backend-compiler,
     52        [  --with-backend-compiler=PROGRAM     PROGRAM that performs the final code compilation (must be gcc-compatible) ],
     53        backendcompiler=$withval, backendcompiler="")
     54if test "x$backendcompiler" != "x"; then
     55        BACKEND_CC=${backendcompiler}
     56else
     57        AC_PATH_PROG(BACKEND_CC, gcc, [])       # check gcc installed
     58        if test "x$BACKEND_CC" = "x"; then
     59                AC_MSG_ERROR(some version of gcc is needed. Get it at ftp://ftp.gnu.org)
     60                exit 1
     61        fi
     62fi
     63AC_DEFINE_UNQUOTED(CFA_BACKEND_CC, "${BACKEND_CC}", [Location of include files.])
     64AC_SUBST(CFA_BACKEND_CC)
     65
     66
     67
     68AC_ARG_ENABLE(target-release, AS_HELP_STRING([--enable-target-release], [Build and install the release target]))
     69AC_ARG_ENABLE(target-debug, AS_HELP_STRING([--enable-target-debug], [Build and install the debug target]))
     70AC_ARG_ENABLE(threading, AS_HELP_STRING([--enable-threading], [Build and install libcfa with threading support (Enabled by default)]),
     71[case "${enableval}" in
     72  yes) build_threading="yes" ;;
     73  no)  build_threading="no" ;;
     74  *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
     75esac],[build_threading="yes"])
     76
     77case "$enable_target_release" in
     78        yes)
     79                case "$enable_target_debug" in
     80                        yes)
     81                                build_release="yes"
     82                                build_debug="yes"
     83                                ;;
     84                        no)
     85                                build_release="yes"
     86                                build_debug="no"
     87                                ;;
     88                        *)
     89                                build_release="yes"
     90                                build_debug="no"
     91                                ;;
     92                esac
     93                ;;
     94        no)
     95                case "$enable_target_debug" in
     96                        yes)
     97                                build_release="no"
     98                                build_debug="yes"
     99                                ;;
     100                        no)
     101                                build_release="no"
     102                                build_debug="no"
     103                                ;;
     104                        *)
     105                                build_release="no"
     106                                build_debug="yes"
     107                                ;;
     108                esac
     109                ;;
     110        *)
     111                case "$enable_target_debug" in
     112                        yes)
     113                                build_release="no"
     114                                build_debug="yes"
     115                                ;;
     116                        no)
     117                                build_release="yes"
     118                                build_debug="no"
     119                                ;;
     120                        *)
     121                                build_release="yes"
     122                                build_debug="yes"
     123                                ;;
     124                esac
     125                ;;
     126esac
     127
     128AM_CONDITIONAL([BUILD_RELEASE], [test "x$build_release" = "xyes"])
     129AM_CONDITIONAL([BUILD_DEBUG], [test "x$build_debug" = "xyes"])
     130AM_CONDITIONAL([BUILD_NO_LIB], [test "x$build_release$build_debug" = "xnono"])
     131AM_CONDITIONAL([BUILD_CONCURRENCY], [test "x$build_threading" = "xyes"])
     132
    50133DOifskipcompile='ifeq ($(skipcompile),yes)
    51134else'
     
    57140AM_SUBST_NOTMAKE([DOendif])
    58141
    59 #==============================================================================
    60 # distcc support
    61 
    62 AC_ARG_ENABLE(distcc,
    63         [  --enable-distcc     whether or not to enable distributed compilation],
    64         enable_distcc=$enableval, enable_distcc=no)
    65 
    66 AM_CONDITIONAL([ENABLE_DISTCC], [test x$enable_distcc = xyes])
    67 HAS_DISTCC="False"
    68 
    69 if test x$enable_distcc = xyes; then
    70         CXX="distcc ${CXX}"
    71         LD="distcc ${LD} -lstdc++"
    72         HAS_DISTCC="True"
    73         echo "Enabling distributed builds"
    74 fi
    75 
    76 AC_SUBST(CXX)
    77 AC_SUBST(LD)
    78 AC_SUBST(HAS_DISTCC)
    79 
    80 #==============================================================================
    81 # Installation paths
    82 M4CFA_PARSE_PREFIX
    83 
    84 #==============================================================================
    85 # Create variables for commonly used targets
    86 
    87 TOP_SRCDIR="$(readlink -m $ac_confdir/)/"
    88 TOP_BUILDDIR="$(readlink -m $ac_pwd/)/"
    89 
    90 AC_DEFINE_UNQUOTED(TOP_SRCDIR, "$TOP_SRCDIR", [Top src directory])
    91 AC_DEFINE_UNQUOTED(TOP_BUILDDIR, "$TOP_BUILDDIR", [Top build directory])
    92 
    93 DRIVER_DIR=${TOP_BUILDDIR}driver/
    94 CFACC=${DRIVER_DIR}cfa
    95 CFACC_INSTALL=${CFA_BINDIR}${CFA_NAME}
    96 CFACPP=${DRIVER_DIR}cfa-cpp
    97 AC_SUBST(DRIVER_DIR)
    98 AC_SUBST(CFACC)
    99 AC_SUBST(CFACC_INSTALL)
    100 AC_SUBST(CFACPP)
    101 
    102 #==============================================================================
    103 # Flag variables needed to build in tree
    104 LIBCFA_SRC='${TOP_SRCDIR}/libcfa/src'
    105 BUILD_IN_TREE_FLAGS="-XCFA -t -B${DRIVER_DIR}"
    106 AC_SUBST(BUILD_IN_TREE_FLAGS)
    107 
    108 #==============================================================================
    109 # handle the list of hosts to build for
    110 for var in $ac_configure_args
    111 do
    112         #strip quotes surrouding values
    113         case $var in
    114                 # skip cross compilation related arguments
    115                 \'--host=*) ;; \'host_alias=*) ;; \'--build=*) ;; \'build_alias=*) ;; \'--target=*) ;; \'target_alias=*) ;;
    116 
    117                 # skip the target hosts
    118                 \'--with-target-hosts=*) ;;
    119 
    120                 # skip gprofiler for libcfa
    121                 \'--enable-gprofiler=*) ;;
    122                 \'--disable-gprofiler) ;;
    123 
    124                 # append all other arguments to the sub configure arguments
    125                 *) LIBCFA_GENERAL_ARGS="${LIBCFA_GENERAL_ARGS} $var";;
    126         esac
    127 done
    128 
    129 #==============================================================================
    130 # handle the list of hosts to build for
     142if test "x$prefix" = "xNONE"; then
     143        cfa_prefix=${ac_default_prefix}
     144else
     145        cfa_prefix=${prefix}
     146fi
     147AC_DEFINE_UNQUOTED(CFA_PREFIX, "${cfa_prefix}", [Location of cfa install.])
     148AC_SUBST(CFA_PREFIX, ${cfa_prefix})
     149
     150if test "$includedir" = '${prefix}/include'; then
     151        cfa_incdir="${cfa_prefix}/include/${cfa_name}"
     152else
     153        cfa_incdir=${includedir}
     154fi
     155AC_DEFINE_UNQUOTED(CFA_INCDIR, "${cfa_incdir}", [Location of include files.])
     156AC_SUBST(CFA_INCDIR, ${cfa_incdir})
     157
     158if test "$bindir" = '${exec_prefix}/bin'; then
     159        cfa_bindir="${cfa_prefix}/bin"
     160else
     161        cfa_bindir=${bindir}
     162fi
     163AC_DEFINE_UNQUOTED(CFA_BINDIR, "${cfa_bindir}", [Location of cfa command.])
     164AC_SUBST(CFA_BINDIR, ${cfa_bindir})
     165
     166if test "$libdir" = '${exec_prefix}/lib'; then
     167        cfa_libdir="${cfa_prefix}/lib/${cfa_name}"
     168else
     169        cfa_libdir=${libdir}
     170fi
     171AC_DEFINE_UNQUOTED(CFA_LIBDIR, "${cfa_libdir}", [Location of cc1 and cfa-cpp commands.])
     172AC_SUBST(CFA_LIBDIR, ${cfa_libdir})
     173
    131174AC_CANONICAL_BUILD
    132175AC_CANONICAL_HOST
     176AC_SUBST([MACHINE_TYPE],[$host_cpu])
    133177
    134178if ! test "$host_cpu" = "$build_cpu"; then
    135179        case $host_cpu in
    136180                i386)
    137                         HOST_FLAGS="-m32"
     181                        CFLAGS+=" -m32 "
     182                        CXXFLAGS+=" -m32 "
     183                        CFAFLAGS+=" -m32 "
     184                        LDFLAGS+=" -m32 "
    138185                        ;;
    139186                i686)
    140                         HOST_FLAGS="-m32"
     187                        CFLAGS+=" -m32 "
     188                  CXXFLAGS+=" -m32 "
     189                  CFAFLAGS+=" -m32 "
     190                  LDFLAGS+=" -m32 "
    141191                        ;;
    142192                x86_64)
    143                         HOST_FLAGS="-m64"
     193                        CFLAGS+=" -m64 "
     194                        CXXFLAGS+=" -m64 "
     195                        CFAFLAGS+=" -m64 "
     196                        LDFLAGS+=" -m64 "
    144197                        ;;
    145198        esac
    146199fi
    147 AC_SUBST(HOST_FLAGS)
    148 
    149 default_target="${host_cpu}:debug, ${host_cpu}:nodebug"
    150 AC_ARG_WITH(target-hosts,
    151         [  --with-target-hosts=HOSTS     HOSTS comma seperated list of hosts to build for, format ARCH:[debug|nodebug|nolib]],
    152         target_hosts=$withval, target_hosts=${default_target})
    153 
    154 AC_ARG_ENABLE(gprofiler,
    155         [  --enable-gprofiler     whether or not to enable gprofiler tools (if available)],
    156         enable_gprofiler=$enableval, enable_gprofiler=yes)
    157 
    158 AC_ARG_ENABLE(demangler,
    159         [  --enable-demangler     whether or not to build the demangler (executable and library)],
    160         enable_demangler=$enableval, enable_demangler=yes)
    161 
    162 AC_SUBST(TARGET_HOSTS, ${target_hosts})
    163 
    164 LIBCFA_PATHS="DRIVER_DIR=${DRIVER_DIR}"
    165 
    166 for i in $(echo $target_hosts | sed "s/,/ /g")
    167 do
    168         # call your procedure/other scripts here below
    169         arch_name=$(echo $i | sed -r "s/:(.*)//g")
    170         lib_config=$(echo $i | sed -r "s/(.*)://g")
    171 
    172         case $lib_config in
    173                 "nodebug") ;;
    174                 "debug") ;;
    175                 "nolib") ;;
    176                 "profile") ;;
    177                 *)
    178                         >&2 echo "Configuration must be 'debug', 'nodebug' or 'nolib'"
    179                         exit 1
    180                 ;;
    181         esac
    182 
    183         M4CFA_CANNON_CPU([${arch_name}])
    184         lib_arch=${cannon_arch_name}
    185         lib_dir="libcfa/${lib_arch}-${lib_config}"
    186 
    187         LIBCFA_TARGET_DIRS="${LIBCFA_TARGET_DIRS} ${lib_dir}"
    188         LIBCFA_TARGET_MAKEFILES="${LIBCFA_TARGET_MAKEFILES} ${lib_dir}/Makefile"
    189 
    190         mkdir -p ${lib_dir}
    191         echo -n "${LIBCFA_GENERAL_ARGS} " > ${lib_dir}/config.data
    192         echo -n "${LIBCFA_PATHS} " >> ${lib_dir}/config.data
    193         echo -n "ARCHITECTURE=${lib_arch} " >> ${lib_dir}/config.data
    194         echo -n "CONFIGURATION=${lib_config} " >> ${lib_dir}/config.data
    195         echo -n "CFA_VERSION=${ver_major}:${ver_minor}:${ver_patch}" >> ${lib_dir}/config.data
    196 done
    197 
    198 AC_SUBST(LIBCFA_TARGET_DIRS)
    199 AC_SUBST(LIBCFA_TARGET_MAKEFILES)
    200 
    201 M4CFA_CANNON_CPU([${host_cpu}])
    202 AC_DEFINE_UNQUOTED(CFA_DEFAULT_CPU, "$cannon_arch_name", [Default cpu to use if neither -m32 or -m64 are defined.])
    203 AC_DEFINE_UNQUOTED(CFA_64_CPU, "x64", [CPU to use if the -m64 flags is given.])
    204 AC_DEFINE_UNQUOTED(CFA_32_CPU, "x86", [CPU to use if the -m32 flags is given.])
    205 
    206 #==============================================================================
    207 # CAFLAGS
     200
    208201AC_DEFINE_UNQUOTED(CFA_FLAGS, "${CFAFLAGS}", [compilation flags for cfa libraries and test programs.])
    209202AC_SUBST(CFA_FLAGS, ${CFAFLAGS})
    210203
    211 #==============================================================================
    212204# Checks for programs.
    213205AC_PROG_CXX
    214206AC_PROG_CC
    215207AM_PROG_AS
     208AM_PROG_CC_C_O  # deprecated
    216209# These are often not installed and people miss seeing the "no", so stop the configure.
    217210AC_PROG_YACC
     
    219212AC_PROG_LEX
    220213if test "${LEX}" = "lex" ; then echo "Error: flex required." ; exit 1 ; fi
    221 AC_PROG_LIBTOOL
    222214AC_PROG_INSTALL
     215AC_PROG_MAKE_SET
     216AC_PROG_RANLIB
    223217
    224218# Checks for libraries.
    225 AC_CHECK_LIB([fibre], [Fibre::yield], [HAVE_LIBFIBRE=1], [HAVE_LIBFIBRE=0])
    226 AM_CONDITIONAL([WITH_LIBFIBRE], [test "$HAVE_LIBFIBRE" -eq 1])
    227 
    228 AC_CHECK_LIB([profiler], [ProfilingIsEnabledForAllThreads], [HAVE_LIBPROFILER=1], [HAVE_LIBPROFILER=0])
    229 AM_CONDITIONAL([WITH_LIBPROFILER], [test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBPROFILER" -eq 1])
    230 
    231 AC_CHECK_LIB([tcmalloc], [malloc], [HAVE_LIBTCMALLOC=1], [HAVE_LIBTCMALLOC=0])
    232 AM_CONDITIONAL([WITH_LIBTCMALLOC], [test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBTCMALLOC" -eq 1])
    233 
    234 # conditionnally build the demangler
    235 if test "x$enable_demangler" == xyes; then
    236         LIBDEMANGLE="libdemangle.a"
    237         DEMANGLER="demangler"
    238 else
    239         LIBDEMANGLE=""
    240         DEMANGLER=""
    241 fi
    242 AC_SUBST([LIBDEMANGLE])
    243 AC_SUBST([DEMANGLER])
    244219
    245220# Checks for header files.
    246 AC_CHECK_HEADERS([libintl.h malloc.h unistd.h], [], [echo "Error: Missing required header"; exit 1])
     221AC_FUNC_ALLOCA
     222AC_CHECK_HEADERS([fenv.h float.h inttypes.h libintl.h limits.h malloc.h stddef.h stdlib.h string.h unistd.h])
    247223
    248224# Checks for typedefs, structures, and compiler characteristics.
    249 AC_CHECK_TYPES([_Float32], AC_DEFINE([HAVE_KEYWORDS_FLOATXX], [], [Have keywords _FloatXX.]), [], [[]])
    250 
    251 # Checks for compiler flags.
    252 M4CFA_CHECK_COMPILE_FLAG([-Wcast-function-type], AC_DEFINE([HAVE_CAST_FUNCTION_TYPE], [], [Have compiler warning cast-function-type.]))
    253 
    254 #==============================================================================
    255 # backend compiler implementation
    256 AC_DEFINE_UNQUOTED(CFA_BACKEND_CC, "${CC}", [Backend compiler to use.])
    257 AC_SUBST(CFA_BACKEND_CC)
    258 
    259 #==============================================================================
     225AC_HEADER_STDBOOL
     226AC_C_INLINE
     227AC_TYPE_INT16_T
     228AC_TYPE_INT32_T
     229AC_TYPE_INT8_T
     230AC_C_RESTRICT
     231AC_TYPE_SIZE_T
     232AC_TYPE_UINT16_T
     233AC_TYPE_UINT32_T
     234AC_TYPE_UINT8_T
     235
     236# Checks for library functions.
     237AC_CHECK_FUNCS([memset putenv strchr strtol])
     238
    260239AC_CONFIG_FILES([
    261240        Makefile
    262         driver/Makefile
     241        src/driver/Makefile
    263242        src/Makefile
    264         benchmark/Makefile
    265         tests/Makefile
    266         longrun_tests/Makefile
     243        src/benchmark/Makefile
     244        src/examples/Makefile
     245        src/tests/Makefile
     246        src/tests/preempt_longrun/Makefile
     247        src/prelude/Makefile
     248        src/libcfa/Makefile
    267249        tools/Makefile
    268250        tools/prettyprinter/Makefile
    269251        ])
    270252
    271 AC_CONFIG_LINKS([tests/test.py:tests/test.py])
    272 
    273 AC_OUTPUT(tests/config.py)
     253AC_OUTPUT
     254
     255AM_COND_IF([BUILD_RELEASE],
     256        [AM_COND_IF([BUILD_DEBUG],
     257                [AC_MSG_NOTICE(Building libcfa for target: release & debug)],
     258                [AC_MSG_NOTICE(Building libcfa for target: release)])],
     259        [AM_COND_IF([BUILD_DEBUG],
     260                [AC_MSG_NOTICE(Building libcfa for target: debug)],
     261                [AC_MSG_NOTICE(Running cfa without libcfa)])])
    274262
    275263# Final text
  • doc/LaTeXmacros/common.tex

    rb067d9b r7951100  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri May 24 07:59:54 2019
    14 %% Update Count     : 382
     13%% Last Modified On : Mon Mar 19 17:18:23 2018
     14%% Update Count     : 379
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5555\setlength{\parindentlnth}{\parindent}
    5656
    57 \newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
    5857\newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
    5958\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
     
    6160\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    6261\newlength{\columnposn}
    63 \setlength{\gcolumnposn}{2.75in}
     62\setlength{\gcolumnposn}{2.5in}
    6463\setlength{\columnposn}{\gcolumnposn}
    6564\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
  • doc/LaTeXmacros/lstlang.sty

    rb067d9b r7951100  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Tue Jan  8 14:40:33 2019
    11 %% Update Count     : 21
     10%% Last Modified On : Fri Apr  6 23:44:50 2018
     11%% Update Count     : 20
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    114114                _Alignas, _Alignof, __alignof, __alignof__, asm, __asm, __asm__, __attribute, __attribute__,
    115115                auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
    116                 coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally,
     116                coroutine, disable, dtype, enable, __extension__, exception, fallthrough, fallthru, finally,
    117117                __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__,
    118118                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
  • doc/bibliography/pl.bib

    rb067d9b r7951100  
    2121%  toplas: ACM Trans. on Prog. Lang. & Sys.
    2222%  tcs: Theoretical Computer Science
    23 
    24 string{ieeepds="IEEE Transactions on Parallel and Distributed Systems"}
    25 @string{ieeepds="IEEE Trans. Parallel Distrib. Syst."}
    26 string{ieeese="IEEE Transactions on Software Engineering"}
    27 @string{ieeese="IEEE Trans. Softw. Eng."}
    28 string{spe="Software---\-Practice and Experience"}
    29 @string{spe="Softw. Pract. Exper."}
    30 string{ccpe="Concurrency and Computation: Practice and Experience"}
    31 @string{ccpe="Concurrency Comput.: Pract. Exper."}
    32 string{sigplan="SIGPLAN Notices"}
    33 @string{sigplan="SIGPLAN Not."}
    34 string{joop="Journal of Object-Oriented Programming"}
    35 @string{joop="J. of Object-Oriented Program."}
     23@string{ieeepds="IEEE Transactions on Parallel and Distributed Systems"}
     24% @string{ieeepds="IEEE Trans. Parallel Distrib. Syst."}
     25@string{ieeese="IEEE Transactions on Software Engineering"}
     26% @string{ieeese="IEEE Trans. Softw. Eng."}
     27@string{spe="Software---\-Practice and Experience"}
     28% @string{spe="Softw. Pract. Exp."}
     29@string{ccpe="Concurrency and Computation: Practice and Experience"}
     30% @string{ccpe="Concurrency Comput: Pract Experience"}
     31@string{sigplan="SIGPLAN Notices"}
     32% @string{sigplan="SIGPLAN Not."}
     33@string{joop="Journal of Object-Oriented Programming"}
     34% @string{joop="J. of Object-Oriented Program."}
    3635@string{popl="Conference Record of the ACM Symposium on Principles of Programming Languages"}
    3736@string{osr="Operating Systems Review"}
    3837@string{pldi="Programming Language Design and Implementation"}
    3938@string{toplas="Transactions on Programming Languages and Systems"}
    40 string{mathann="Mathematische Annalen"}
    41 @string{mathann="Math. Ann."}
     39@string{mathann="Mathematische Annalen"}
     40% @string{mathann="Math. Ann."}
    4241
    4342% A
     
    330329    contributer = {pabuhr@plg},
    331330    author      = {Nissim Francez},
    332     title       = {Another Advantage of Keyword Notation for Parameter Communication with Subprograms},
     331    title       = {Another Advantage of Key word Notation for Parameter Communication with Subprograms},
    333332    journal     = cacm,
    334333    volume      = 20,
     
    567566}
    568567
    569 @inproceedings {Qin18,
    570     author      = {Henry Qin and Qian Li and Jacqueline Speiser and Peter Kraft and John Ousterhout},
    571     title       = {Arachne: Core-Aware Thread Management},
    572     booktitle   = {13th {USENIX} Symp. on Oper. Sys. Design and Impl. ({OSDI} 18)},
    573     year        = {2018},
    574     address     = {Carlsbad, CA},
    575     pages       = {145-160},
    576     publisher   = {{USENIX} Association},
    577     note        = {\href{https://www.usenix.org/conference/osdi18/presentation/qin}{https://\-www.usenix.org/\-conference/\-osdi18/\-presentation/\-qin}},
    578 }
    579 
    580568@article{Kessels82,
    581569    keywords    = {concurrency, critical section},
     
    665653    author      = {Joung, Yuh-Jzer},
    666654    title       = {Asynchronous group mutual exclusion},
    667     journal     = {Dist. Comput.},
    668     optjournal  = {Distributed Computing},
     655    journal     = {Distributed Computing},
    669656    year        = {2000},
    670657    month       = {Nov},
     
    713700
    714701% B
    715 
    716 @article{Michael13,
    717     contributer = {pabuhr@plg},
    718     author      = {Maged M. Michael},
    719     title       = {The Balancing Act of Choosing Nonblocking Features},
    720     journal     = cacm,
    721     volume      = 56,
    722     number      = 9,
    723     month       = sep,
    724     year        = 2013,
    725     pages       = {46--53},
    726     publisher   = {ACM},
    727     address     = {New York, NY, USA},
    728 }
    729702
    730703@incollection{beta:old,
     
    809782        time computable inheritance hierarchy.
    810783    },
    811     comment     = {
     784    comment = {
    812785        Classes are predicates; if object {\tt o} is in class {\tt C}, then
    813786        {\tt C} is true of {\tt o}.  Classes are combined with {\tt :AND},
     
    831804    year        = 2015,
    832805    howpublished= {\href{http://www.boost.org/doc/libs/1_61_0/libs/coroutine/doc/html/index.html}
    833                   {http://www.boost.org/\-doc/\-libs/1\_61\_0/\-libs/\-coroutine/\-doc/\-html/\-index.html}},
    834 }
    835 
    836 @misc{BoostThreads,
    837     keywords    = {Boost Thread Library},
    838     contributer = {pabuhr@plg},
    839     author      = {Anthony Williams and Vicente J. Botet Escriba},
    840     title       = {Boost Thread Library},
    841     year        = 2015,
    842     howpublished= {\href{https://www.boost.org/doc/libs/1_61_0/doc/html/thread.html}
    843                   {https://\-www.boost.org/\-doc/\-libs/\-1\_61\_0/\-doc/\-html/\-thread.html}},
     806                  {{http://www.boost.org/\-doc/\-libs/1\_61\_0/\-libs/\-coroutine/\-doc/\-html/\-index.html}}},
     807    optnote     = {Accessed: 2016-09},
    844808}
    845809
     
    852816    month       = oct,
    853817    type        = {Diplomarbeit},
    854     note        = {\href{https://plg.uwaterloo.ca/~usystem/theses/KrischerThesis.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-theses/\-KrischerThesis.pdf}},
     818    note        = {{\small\textsf{ftp://\-plg.uwaterloo.ca/\-pub/\-theses/\-KrischerThesis.ps.gz}}},
    855819}
    856820
     
    943907}
    944908
    945 @article{Moss18,
    946     keywords    = {type systems, polymorphism, tuples, Cforall},
    947     contributer = {pabuhr@plg},
    948     author      = {Aaron Moss and Robert Schluntz and Peter A. Buhr},
    949     title       = {\textsf{C}$\mathbf{\forall}$ : Adding Modern Programming Language Features to {C}},
    950     journal     = spe,
    951     volume      = 48,
    952     number      = 12,
    953     month       = dec,
    954     year        = 2018,
    955     pages       = {2111-2146},
    956     note        = {\href{http://dx.doi.org/10.1002/spe.2624}{http://\-dx.doi.org/\-10.1002/\-spe.2624}},
    957 }
    958 
    959 @misc{CforallBenchMarks,
    960     contributer = {pabuhr@plg},
    961     key         = {Cforall Benchmarks},
    962     author      = {{\textsf{C}{$\mathbf{\forall}$} Benchmarks}},
    963     howpublished= {\href{https://plg.uwaterloo.ca/~cforall/benchmark.tar}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-benchmark.tar}},
    964 }
    965 
    966909@misc{Cforall,
    967     contributer = {pabuhr@plg},
    968910    key         = {Cforall},
    969     author      = {{\textsf{C}{$\mathbf{\forall}$} Features}},
    970     howpublished= {\href{https://plg.uwaterloo.ca/~cforall/features}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-features}},
    971 }
    972 
    973 @misc{CFAStackEvaluation,
    974     contributer = {a3moss@plg},
    975     author      = {Aaron Moss},
    976     title       = {\textsf{C}$\mathbf{\forall}$ Stack Evaluation Programs},
    977     year        = 2018,
    978     howpublished= {\href{https://cforall.uwaterloo.ca/CFAStackEvaluation.zip}{https://cforall.uwaterloo.ca/\-CFAStackEvaluation.zip}},
     911    title       = {\textsf{C}{$\mathbf{\forall}$} Features},
     912    howpublished= {\url{https://plg.uwaterloo.ca/~cforall/features}},
     913    optnote     = {Accessed: 2018-01-01},
    979914}
    980915
     
    990925}
    991926
    992 @phdthesis{Moss19,
    993     keywords    = {type system, generic type, resolution algorithm, type environment, Cforall},
     927@misc{CFAStackEvaluation,
    994928    author      = {Aaron Moss},
    995     title       = {\textsf{C}$\mathbf{\forall}$ Type System Implementation},
    996     school      = {School of Computer Science, University of Waterloo},
    997     year        = 2019,
    998     optaddress  = {Waterloo, Ontario, Canada, N2L 3G1},
    999     note        = {\href{https://uwspace.uwaterloo.ca/handle/10012/14584}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-14584}},
     929    title       = {\textsf{C}$\mathbf{\forall}$ Stack Evaluation Programs},
     930    year        = 2018,
     931    howpublished= {\href{https://plg.uwaterloo.ca/~cforall/evaluation.zip}{https://plg.uwaterloo.ca/\-\-$\sim$cforall/\-StackEvaluation.zip}},
     932    optnote     = {[Accessed May 2018]},
     933}
     934
     935@article{Moss18,
     936    keywords    = {concurrency, C++},
     937    contributer = {pabuhr@plg},
     938    author      = {Aaron Moss and Robert Schluntz and Peter A. Buhr},
     939    title       = {\textsf{C}$\mathbf{\forall}$ : Adding Modern Programming Language Features to C},
     940    year        = 2018,
     941    journal     = spe,
     942    note        = {Accepted, to appear},
    1000943}
    1001944
     
    1019962    comment     = {
    1020963        The evidence given is thin.
    1021     },
     964        }
    1022965}
    1023966
     
    1029972    journal     = {Dr. Dobb's Journal of Software Tools},
    1030973    year        = 1989,
    1031     month       = feb,
    1032     volume      = 14,
    1033     number      = 2,
    1034     pages       = {45-51},
     974    month       = feb, volume = 14, number = 2, pages = {45-51},
    1035975    comment     = {
    1036976       A light-weight multitasking kernel for MS-DOS.  A task\_control
     
    11081048    year        = 2006,
    11091049    edition     = {4th},
    1110 }
    1111 
    1112 @techreport{Prokopec11,
    1113     keywords    = {ctrie, concurrent map},
    1114     contributer = {a3moss@uwaterloo.ca},
    1115     title       ={Cache-aware lock-free concurrent hash tries},
    1116     author      ={Prokopec, Aleksandar and Bagwell, Phil and Odersky, Martin},
    1117     institution ={EPFL},
    1118     year        ={2011}
    11191050}
    11201051
     
    11531084    month       = oct,
    11541085    year        = 2001,
    1155     note        = {\href{http://plg.uwaterloo.ca/~cforall/cfa.ps}{http://\-plg.uwaterloo.ca/\-$\sim$cforall/\-cfa.ps}},
     1086    note        = {\href{http://plg.uwaterloo.ca/~cforall/cfa.ps}{http://\-plg.uwaterloo.ca/\-\char`\~cforall/\-cfa.ps}},
    11561087}
    11571088
     
    11651096    year        = 1998,
    11661097    note        = {{\small\textsf{ftp://\-plg.uwaterloo.ca/\-pub/\-Cforall/\-refrat.ps.gz}}},
    1167 }
    1168 
    1169 @phdthesis{Norrish98,
    1170     title       = {C formalised in HOL},
    1171     author      = {Norrish, Michael},
    1172     year        = {1998},
    1173     school      = {University of Cambridge}
    1174 }
    1175 
    1176 @inproceedings{Tarditi18,
    1177     keywords    = {Checked C},
    1178     contributer = {a3moss@uwaterloo.ca},
    1179     author      = {Tarditi, David and Elliott, Archibald Samuel and Ruef, Andrew and Hicks, Michael},
    1180     title       = {Checked C: Making C Safe by Extension},
    1181     booktitle   = {2018 IEEE Cybersecurity Development (SecDev)},
    1182     publisher   = {IEEE},
    1183     year        = {2018},
    1184     month       = sep,
    1185     pages       = {53-60},
    1186     url         = {https://www.microsoft.com/en-us/research/publication/checkedc-making-c-safe-by-extension/},
    1187 }
    1188 
    1189 @misc{Clang,
    1190     keywords    = {clang},
    1191     contributer = {a3moss@uwaterloo.ca},
    1192     title       = {Clang: a {C} language family frontend for {LLVM}},
    1193     howpublished= {\href{https://clang.llvm.org/}{https://\-clang.llvm.org/}}
    11941098}
    11951099
     
    12791183        that is ``compiled''.
    12801184    },
     1185    comment     = {
     1186        Imagine the program, including the subroutines, spread out over a
     1187        table, with the compiler dropping Jello on the parts as they are
     1188        compiled.  At first little drops appear in seemingly random places.
     1189        These get bigger and combine with other drops to form growing
     1190        globs.  When two globs meet, ripples will go out through each as
     1191        they adjust to each other's presence, although the parts of the
     1192        globs that formed first are less affected by the ripples.  When
     1193        compilation is complete, there is one congealed mass.
     1194    }
    12811195}
    12821196
     
    12921206    number      = 11,
    12931207    pages       = {853-860},
    1294 }
    1295 
    1296 @inproceedings{Odersky01,
    1297     keywords    = {Scala},
    1298     contributer = {a3moss@uwaterloo.ca},
    1299     author      = {Odersky, Martin and Zenger, Christoph and Zenger, Matthias},
    1300     title       = {Colored Local Type Inference},
    1301     booktitle   = {Proceedings of the 28th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages},
    1302     series      = {POPL '01},
    1303     year        = {2001},
    1304     isbn        = {1-58113-336-7},
    1305     location    = {London, United Kingdom},
    1306     pages       = {41--53},
    1307     numpages    = {13},
    1308     url         = {http://doi.acm.org/10.1145/360204.360207},
    1309     doi         = {10.1145/360204.360207},
    1310     acmid       = {360207},
    1311     publisher   = {ACM},
    1312     address     = {New York, NY, USA},
    13131208}
    13141209
     
    13731268    journal     = sigplan,
    13741269    year        = 1986,
    1375     month       = oct,
    1376     volume      = 21,
    1377     number      = 10,
    1378     pages       = {19-28},
     1270    month       = oct, volume = 21, number = 10, pages = {19-28},
    13791271    note        = {Object Oriented Programming Workshop}
    13801272}
     
    14961388        Process-valued expressions and process variables.  Processes have
    14971389        execution priority: Create {\em process-type-name}(args) [with
    1498         priority(p)], and the priority can be changed on the fly.  Complicated
    1499         guard/screen structure on accept: accept {\em transaction}(param names)
     1390        priority(p)],
     1391        and the priority can be changed on the fly.  Complicated guard/
     1392        screen structure on accept: accept {\em transaction}(param names)
    15001393        [suchthat (exp)] [by (exp)] [compoundstatement].  Accepts cannot
    15011394        appear in functions!  Can specify timeouts on transaction calls.
     
    15321425                Many errors in the two solutions.
    15331426    }
    1534 }
    1535 
    1536 @misc{NThreadCode13,
    1537     keywords    = {N-thread software-solution mutual exclusion},
    1538     contributer = {pabuhr@plg},
    1539     key         = {concurrent locking},
    1540     author      = {Peter A. Buhr and David Dice and Wim H. Hesselink},
    1541     title       = {concurrent-locking},
    1542     howpublished= {\href{https://github.com/pabuhr/concurrent-locking}{https://\-github.com/\-pabuhr/\-concurrent-locking}},
    15431427}
    15441428
     
    16071491}
    16081492
    1609 @manual{uC++,
     1493@techreport{uC++,
    16101494    keywords    = {C++, concurrency, light-weight process, shared memory},
    16111495    contributer = {pabuhr@plg},
    1612     key         = {uC++},
    16131496    author      = {Peter A. Buhr},
    16141497    title       = {$\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Annotated Reference Manual, Version 7.0.0},
    1615     organization= {University of Waterloo},
    1616     month       = sep,
    1617     year        = 2018,
    1618     note        = {\href{https://plg.uwaterloo.ca/~usystem/pub/uSystem/uC++.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-pub/\-uSystem/uC++.pdf}},
     1498    institution = {School of Computer Science, University of Waterloo},
     1499    address     = {Waterloo, Ontario, Canada, N2L 3G1},
     1500    month       = dec,
     1501    year        = 2017,
     1502    note        = {\href{http://plg.uwaterloo.ca/~usystem/pub/uSystem/u++-7.0.0.sh}{http://\-plg.\-uwaterloo.\-ca/\-$\sim$usystem/\-pub/\-uSystem/\-u++-7.0.0.sh}},
    16191503}
    16201504
     
    16831567}
    16841568
    1685 @mastersthesis{Sun15,
    1686     author      = {Sun, Xianda},
    1687     title       = {Concurrent High-performance Persistent Hash Table In {J}ava},
    1688     school      = {School of Computer Sc., University of Waterloo},
    1689     year        = 2015,
    1690     optaddress  = {Waterloo, Ontario, Canada, N2L 3G1},
    1691     note        = {\href{https://uwspace.uwaterloo.ca/handle/10012/10013}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-10013}},
    1692 }
    1693 
    16941569@book{Andrews91:book,
    16951570    keywords    = {concurrency},
     
    17001575    address     = {Redwood City},
    17011576    year        = 1991,
    1702 }
    1703 
    1704 @inproceedings{Prokopec12,
    1705     keywords    = {ctrie, hash trie, concurrent map},
    1706     contributer = {a3moss@uwaterloo.ca},
    1707     title       = {Concurrent tries with efficient non-blocking snapshots},
    1708     author      = {Prokopec, Aleksandar and Bronson, Nathan Grasso and Bagwell, Phil and Odersky, Martin},
    1709     booktitle   = {ACM SIGPLAN Notices},
    1710     volume      = {47},
    1711     number      = {8},
    1712     pages       = {151--160},
    1713     year        = {2012},
    1714     organization={ACM}
    17151577}
    17161578
     
    17291591
    17301592@mastersthesis{Delisle18,
    1731     keywords    = {concurrency, Cforall},
    1732     contributer = {pabuhr@plg},
    1733     author      = {Thierry Delisle},
     1593    author      = {Thierry Delisle },
    17341594    title       = {Concurrency in \textsf{C}$\mathbf{\forall}$},
    17351595    school      = {School of Computer Science, University of Waterloo},
    17361596    year        = 2018,
    1737     optaddress  = {Waterloo, Ontario, Canada, N2L 3G1},
     1597    address     = {Waterloo, Ontario, Canada, N2L 3G1},
    17381598    note        = {\href{https://uwspace.uwaterloo.ca/handle/10012/12888}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-12888}},
    1739 }
    1740 
    1741 @article{Delisle19,
    1742     keywords    = {concurrency, Cforall},
    1743     contributer = {pabuhr@plg},
    1744     author      = {Thierry Delisle and Peter A. Buhr},
    1745     title       = {Advanced Control-flow and Concurrency in \textsf{C}$\mathbf{\forall}$},
    1746     year        = 2019,
    1747     journal     = spe,
    1748     pages       = {1-33},
    1749     note        = {submitted},
    17501599}
    17511600
     
    18411690    howpublished= {\href{https://www.airs.com/blog/archives/428}
    18421691                  {https://www.airs.com/\-blog/\-archives/\-428}},
     1692    optnote     = {Accessed: 2018-05},
    18431693}
    18441694
     
    19211771    author      = {Glen Ditchfield},
    19221772    title       = {Conversions for \textsf{C}$\mathbf{\forall}$},
    1923     note        = {\href{http://plg.uwaterloo.ca/~cforall/Conversions/index.html}{http://\-plg.uwaterloo.ca/\-$\sim$cforall/\-Conversions/\-index.html}},
     1773    note        = {\href{http://plg.uwaterloo.ca/~cforall/Conversions/index.html}{http://\-plg.uwaterloo.ca/\-\textasciitilde cforall/\-Conversions/\-index.html}},
    19241774    month       = {Nov},
    19251775    year        = {2002},
     
    19361786    year        = 1965,
    19371787    note        = {Reprinted in \cite{Genuys68} pp. 43--112.}
    1938 }
    1939 
    1940 @inproceedings{Adya02,
    1941     contributer = {pabuhr@plg},
    1942     author      = {Adya, Atul and Howell, Jon and Theimer, Marvin and Bolosky, William J. and Douceur, John R.},
    1943     title       = {Cooperative Task Management Without Manual Stack Management},
    1944     booktitle   = {Proceedings of the General Track of the Annual Conference on USENIX Annual Technical Conference},
    1945     series      = {ATEC '02},
    1946     year        = {2002},
    1947     pages       = {289-302},
    1948     publisher   = {USENIX Association},
    1949     address     = {Berkeley, CA, USA},
    1950 }
    1951 
    1952 @misc{CoroutineTS,
    1953     keywords    = {Coroutines TS, C++20, working draft},
    1954     contributer = {pabuhr@plg},
    1955     author      = {Gor Nishanov},
    1956     title       = {Merge Coroutines TS into C++20 Working Draft},
    1957     year        = 2019,
    1958     month       = feb,
    1959     howpublished= {\href{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0912r5.html}
    1960                   {http://\-www.open-std.org/\-jtc1/\-sc22/\-wg21/\-docs/\-papers/\-2019/p0912r5.html}},
    1961 }
    1962 
    1963 @manual{C++20Coroutine19,
    1964     keywords    = {coroutine},
    1965     contributer = {pabuhr@plg},
    1966     title       = {Coroutines (C++20)},
    1967     organization= {cppreference.com},
    1968     month       = apr,
    1969     year        = 2019,
    1970     note        = {\href{https://en.cppreference.com/w/cpp/language/coroutines}{https://\-en.cppreference.com/\-w/\-cpp/\-language/\-coroutines}},
    19711788}
    19721789
     
    20161833}
    20171834
    2018 @misc{CS343,
    2019     keywords    = {uC++ teaching},
    2020     contributer = {pabuhr@plg},
    2021     key         = {Peter Buhr},
    2022     title       = {CS343},
    2023     year        = 2018,
    2024     howpublished= {\href{https://www.student.cs.uwaterloo.ca/~cs343}{https://\-www.student.cs.uwaterloo.ca/\-$\sim$cs343}},
     1835@article{Moore75,
     1836    keywords    = {approximation methods, integrated circuits},
     1837    contributer = {pabuhr@plg},
     1838    author      = {Gordon E. Moore},
     1839    title       = {Progress in Digital Integrated Electronics},
     1840    journal     = {Technical Digest, International Electron Devices Meeting, IEEE},
     1841    year        = 1975,
     1842    pages       = {11-13},
    20251843}
    20261844
     
    20811899    note        = {Svensk Standard SS 63 61 14},
    20821900    year        = 1987,
    2083     abstract    = {Standard for the programming language SIMULA. Written in English.}
    2084 }
    2085 
    2086 @article{Galil91,
    2087     keywords    = {union-find},
    2088     contributer = {a3moss@uwaterloo.ca},
    2089     title       = {Data structures and algorithms for disjoint set union problems},
    2090     author      = {Galil, Zvi and Italiano, Giuseppe F},
    2091     journal     = {ACM Computing Surveys (CSUR)},
    2092     volume      = 23,
    2093     number      = 3,
    2094     pages       = {319--344},
    2095     year        = 1991,
    2096     publisher   = {ACM},
     1901    abstract    = {
     1902        Standard for the programming language SIMULA.  Written in English.
     1903    }
    20971904}
    20981905
     
    22342041    year        = {1998},
    22352042    pages       = {393-407},
    2236 }
    2237 
    2238 @book{Aho74,
    2239     keywords    = {algorithms, textbook, union-find},
    2240     contributer = {a3moss@uwaterloo.ca},
    2241     title       = {The Design and Analysis of Computer Algorithms},
    2242     author      = {Aho, Alfred V and Hopcroft, John E and Ullman, Jeffrey D},
    2243     year        = {1974},
    2244     publisher   = {Addison-Wesley},
    2245     address     = {Reading, MA, USA}
    22462043}
    22472044
     
    23972194}
    23982195
    2399 @article{Ritchie93,
    2400     keywords    = {C, history},
    2401     contributer = {pabuhr@plg},
    2402     author      = {Ritchie, Dennis M.},
    2403     title       = {The Development of the {C} Language},
    2404     journal     = sigplan,
    2405     volume      = 28,
    2406     number      = 3,
    2407     month       = mar,
    2408     year        = 1993,
    2409     pages       = {201--208},
    2410     url         = {http://doi.acm.org/10.1145/155360.155580},
    2411     publisher   = {ACM},
    2412     address     = {New York, NY, USA},
    2413 }
    2414 
    24152196@article{design,
    24162197    keywords    = {Smalltalk, designing classes},
     
    24202201    journal     = joop,
    24212202    year        = 1988,
    2422     volume      = 1,
    2423     number      = 2,
    2424     pages       = {22-35},
     2203    volume      = 1, number = 2, pages = {22-35},
    24252204    comment     = {
    24262205        Abstract classes represent standard protocols.  ``It is better to
     
    25072286    year        = 1990,
    25082287    pages       = {315-323}
    2509 }
    2510 
    2511 @misc{Dotty-github,
    2512     keywords    = {dotty,scala},
    2513     contributer = {a3moss@uwaterloo.ca},
    2514     author      = {Martin Odersky},
    2515     title       = {Dotty},
    2516     howpublished= {\href{https://github.com/lampepfl/dotty}{https://\-github.com/\-lampepfl/\-dotty}},
    2517     note        = {Acessed: 2019-02-22}
    25182288}
    25192289
     
    26242394}
    26252395
    2626 @article{Tarjan75,
    2627     keywords    = {union-find},
    2628     contributer = {a3moss@uwaterloo.ca},
    2629     author      = {Tarjan, Robert Endre},
    2630     title       = {Efficiency of a Good But Not Linear Set Union Algorithm},
    2631     journal     = {J. ACM},
    2632     issue_date  = {April 1975},
    2633     volume      = {22},
    2634     number      = {2},
    2635     month       = apr,
    2636     year        = {1975},
    2637     issn        = {0004-5411},
    2638     pages       = {215--225},
    2639     numpages    = {11},
    2640     url         = {http://doi.acm.org/10.1145/321879.321884},
    2641     doi         = {10.1145/321879.321884},
    2642     acmid       = {321884},
    2643     publisher   = {ACM},
    2644     address     = {New York, NY, USA},
    2645 }
    2646 
    26472396@book{Eiffel,
    26482397    keywords    = {Eiffel},
     
    26632412    journal     = ipl,
    26642413    year        = 1980,
    2665     month       = apr,
    2666     volume      = 10,
    2667     number      = 3,
    2668     pages       = {120-123},
     2414    month       = apr, volume = 10, number = 3, pages = {120-123},
    26692415    comment     = {
    26702416        The ``two-pass'' algorithm.  An upward pass over a parse tree
     
    27002446}
    27012447
    2702 @inproceedings{chambers89a,
     2448@InProceedings{chambers89a,
    27032449    keywords    = {maps, delegation},
    27042450    author      = "Craig Chambers and David Ungar and Elgin Lee",
    2705     title       = "An Efficient Implementation of {SELF}, a Dynamically-Typed Object-Oriented Language Based on Prototypes",
     2451    title       = "An Efficient Implementation of {SELF}, a Dynamically-Typed
     2452                 Object-Oriented Language Based on Prototypes",
    27062453    crossref    = "OOPSLA89",
    27072454    pages       = {49-70}
    27082455}
    27092456
    2710 @misc{Turley99,
    2711     keywords    = {embedded system, micrprocessor},
    2712     contributer = {pabuhr@plg},
    2713     author      = {Jim Turley},
    2714     title       = {Embedded Processors by the Numbers},
    2715     year        = 1999,
    2716     month       = may,
    2717     note        = {Electronic Engineering Times},
    2718     howpublished= {\href{https://www.eetimes.com/author.asp?sectionid=36&doc_id=1287712}
    2719                   {https://\-www.eetimes.com/\-author.asp?sectionid=\-36&doc_id=1287712}},
    2720 }
    2721 
    27222457@article{oop:encapsulation,
    27232458    keywords    = {Encapsulation, Inheritance, Subclasses, Multiple Inheritance},
    27242459    contributer = {gjditchfield@plg},
    27252460    author      = {Alan Snyder},
    2726     title       = {Encapsulation and Inheritance in Object-Oriented Programming Languages},
     2461    title       = {Encapsulation and Inheritance in Object-Oriented Programming
     2462        Languages},
    27272463    journal     = sigplan,
    27282464    volume      = {21},    number = {11},
     
    27592495    title       = {Encapsulators: A New Software Paradigm in Smalltalk-80},
    27602496    journal     = sigplan,
    2761     volume      = {21},
    2762     number      = {11},
     2497    volume      = {21},    number       = {11},
    27632498    pages       = {341-346},
    2764     month       = nov,
    2765     year        = 1986,
     2499    month       = nov, year = 1986,
    27662500    comment     = {
    27672501        Encapsulators are objects that surround other objects.
     
    28342568    year        = 1979,
    28352569    pages       = {24-32}
    2836 }
    2837 
    2838 @inproceedings{XaaS,
    2839     keywords    = {Everything as a Service, Anything as a Service, Cloud computing, SOA},
    2840     contributer = {pabuhr@plg},
    2841     author      = {Duan, Yucong and Fu, Guohua and Zhou, Nianjun and Sun, Xiaobing and Narendra, Nanjangud C. and Hu, Bo},
    2842     title       = {Everything As a Service (XaaS) on the Cloud: Origins, Current and Future Trends},
    2843     booktitle   = {Proceedings of the 2015 IEEE 8th International Conference on Cloud Computing},
    2844     series      = {CLOUD'15},
    2845     year        = {2015},
    2846     pages       = {621--628},
    2847     publisher   = {IEEE Computer Society},
    2848     address     = {Washington, DC, USA},
    28492570}
    28502571
     
    30582779    title       = {Extending Modula-2 to Build Large, Integrated Systems},
    30592780    journal     = {IEEE Software},
    3060     month       = nov,
    3061     year        = 1986,
    3062     volume      = 3,
    3063     number      = 6,
    3064     pages       = {46-57},
     2781    month       = nov, year = 1986,
     2782    volume      = 3, number = 6, pages = {46-57},
    30652783    comment     = {
    30662784        Exceptions can have a parameter.  Procedures can declare the
     
    30952813    year        = 2014,
    30962814    howpublished= {\href{https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/C-Extensions.html}{https://\-gcc.gnu.org/\-onlinedocs/\-gcc-4.7.2/\-gcc/\-C\-Extensions.html}},
     2815    optnote     = {Accessed: 2017-04-02},
    30972816}
    30982817
     
    31062825    year        = 1988,
    31072826    pages       = {143-149}
    3108 }
    3109 
    3110 @inproceedings{Patwary10,
    3111     keywords    = {union-find},
    3112     contributer = {a3moss@uwaterloo.ca},
    3113     author      = {Patwary, Md. Mostofa Ali and Blair, Jean and Manne, Fredrik},
    3114     editor      = {Festa, Paola},
    3115     title       = {Experiments on Union-Find Algorithms for the Disjoint-Set Data Structure},
    3116     booktitle   = {Experimental Algorithms},
    3117     year        = 2010,
    3118     publisher   = {Springer Berlin Heidelberg},
    3119     address     = {Berlin, Heidelberg},
    3120     pages       = {411--423},
    3121     isbn        = {978-3-642-13193-6}
    31222827}
    31232828
     
    31552860    keywords    = {concurrency, mutual exclusion, performance experiment, software solutions},
    31562861    title       = {Fast mutual exclusion by the {T}riangle algorithm},
    3157     author      = {Wim H. Hesselink and Peter A. Buhr and David Dice},
     2862    author      = {Wim H. Hesselink and Peter Buhr and David Dice},
    31582863    journal     = ccpe,
    31592864    volume      = 30,
     
    31622867    month       = feb,
    31632868    publisher   = {John Wiley \& Sons},
    3164     note        = {\href{https://doi.org/10.1002/cpe.4183}{https://\-doi.org/\-10.1002/\-cpe.4183}}
     2869    note        = {\url{https://doi.org/10.1002/cpe.4183}}
    31652870}
    31662871
     
    31782883}
    31792884
    3180 @manual{WindowsFibers,
    3181     keywords    = {threads, fibers},
    3182     contributer = {pabuhr@plg},
    3183     author      = {Windows},
    3184     title       = {Fibers},
    3185     organization= {Microsoft, Windows Development Center},
    3186     address     = {\href{https://docs.microsoft.com/en-us/windows/desktop/ProcThread/fibers}{https://\-docs.microsoft.com/\-en-us/\-windows/\-desktop/\-ProcThread/\-fibers}},
    3187     year        = 2018,
    3188 }
    3189 
    31902885@inproceedings{F-bound,
    31912886    keywords    = {},
     
    32352930}
    32362931
    3237 @manual{Folly,
    3238     keywords    = {Folly},
    3239     contributer = {pabuhr@plg},
    3240     author      = {Folly},
    3241     title       = {Facebook Open-source Library},
    3242     organization= {Facebook},
    3243     address     = {\href{https://github.com/facebook/folly}{https://\-github.com/\-facebook/\-folly}},
    3244     year        = 2018,
    3245 }
    3246 
    3247 @article{Leroy09,
    3248     keywords    = {C formalization},
    3249     contributer = {a3moss@uwaterloo.ca},
    3250     author      = {Leroy, Xavier},
    3251     title       = {Formal Verification of a Realistic Compiler},
    3252     journal     = {Commun. ACM},
    3253     issue_date  = {July 2009},
    3254     volume      = {52},
    3255     number      = {7},
    3256     month       = jul,
    3257     year        = {2009},
    3258     issn        = {0001-0782},
    3259     pages       = {107--115},
    3260     numpages    = {9},
    3261     url         = {http://doi.acm.org/10.1145/1538788.1538814},
    3262     doi         = {10.1145/1538788.1538814},
    3263     acmid       = {1538814},
    3264     publisher   = {ACM},
    3265     address     = {New York, NY, USA},
    3266 }
    3267 
    32682932@manual{Fortran95,
    32692933    keywords    = {Fortran 95},
     
    32862950    address     = {\href{https://www.iso.org/standard/50459.html}{https://\-www.iso.org/\-standard/\-50459.html}},
    32872951    year        = 2010,
    3288 }
    3289 
    3290 @manual{Fortran18,
    3291     keywords    = {ISO/IEC Fortran 10},
    3292     contributer = {pabuhr@plg},
    3293     author      = {Fortran18},
    3294     title       = {Programming Languages -- {Fortran} Part 1:Base Language ISO/IEC 1539-1:2018},
    3295     edition     = {4rd},
    3296     publisher   = {International Standard Organization},
    3297     address     = {\href{https://www.iso.org/standard/72320.html}{https://\-www.iso.org/\-standard/\-72320.html}},
    3298     year        = 2018,
    32992952}
    33002953
     
    35173170    keywords    = {Go programming language},
    35183171    contributer = {pabuhr@plg},
     3172    title       = {{Go} Programming Language},
    35193173    author      = {Robert Griesemer and Rob Pike and Ken Thompson},
    3520     title       = {{Go} Programming Language},
    35213174    organization= {Google},
    35223175    year        = 2009,
     
    35463199    year        = 2014,
    35473200    howpublished= {https://developer.gnome.org/gobject/stable/},
     3201    optnote     = {Accessed: 2017-04},
    35483202}
    35493203
     
    36253279    edition     = {{S}imon {M}arlow},
    36263280    year        = 2010,
    3627     note        = {\href{https://haskell.org/definition/haskell2010.pdf}{https://\-haskell.org/\-definition/\-haskell2010.pdf}},
     3281    note        = {\href{https://haskell.org/definition/haskell2010.pdf}{https://haskell.org/\-definition/\-haskell2010.pdf}},
    36283282}
    36293283
     
    36993353}
    37003354
    3701 @article{Hesselink17b,
    3702     keywords    = {concurrency, mutual exclusion, performance experiment, software solutions},
    3703     title       = {High-Contention Mutual Exclusion by Elevator Algorithms},
    3704     author      = {Peter A. Buhr and David Dice and Wim H. Hesselink},
    3705     journal     = ccpe,
    3706     volume      = 30,
    3707     number      = 18,
    3708     year        = 2018,
    3709     month       = sep,
    3710     publisher   = {John Wiley \& Sons},
    3711     note        = {\href{https://doi.org/10.1002/cpe.4475}{https://\-doi.org/\-10.1002/\-cpe.4475}},
    3712 }
    3713 
    37143355@article{Buhr15a,
    37153356    keywords    = {software solution, mutual exclusion, performance experiment},
     
    38473488    publisher   = {ACM Press},
    38483489    address     = {New York, NY, USA},
    3849 }
    3850 
    3851 @article{Galler64,
    3852     keywords    = {union-find, original},
    3853     contributer = {a3moss@uwaterloo.ca},
    3854     title       = {An improved equivalence algorithm},
    3855     author      = {Galler, Bernard A and Fisher, Michael J},
    3856     journal     = {Communications of the ACM},
    3857     volume      = {7},
    3858     number      = {5},
    3859     pages       = {301--303},
    3860     year        = {1964},
    3861     publisher   = {ACM}
    3862 }
    3863 
    3864 @phdthesis{Barghi18,
    3865     keywords    = {concurrency, user threads, actors},
    3866     contributer = {pabuhr@plg},
    3867     author      = {Saman Barghi},
    3868     title       = {Improving the Performance of User-level Runtime Systems for Concurrent Applications},
    3869     school      = {School of Computer Science, University of Waterloo},
    3870     year        = 2018,
    3871     month       = sep,
    3872     optaddress  = {Waterloo, Ontario, Canada, N2L 3G1},
    3873     note        = {\href{https://uwspace.uwaterloo.ca/handle/10012/13935}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-13935}},
    3874 }
    3875 
    3876 @article{Swift05,
    3877    contributer  = {pabuhr@plg},
    3878    author       = {Michael M. Swift and Brian N. Bershad and Henry M. Levy},
    3879    title        = {Improving the Reliability of Commodity Operating Systems},
    3880    journal      = tocs,
    3881    volume       = 23,
    3882    number       = 1,
    3883    month        = feb,
    3884    year         = 2005,
    3885    pages        = {77-110},
    38863490}
    38873491
     
    41903794}
    41913795
    4192 @article{Morgado13,
    4193     keywords    = {expression resolution},
    4194     contributer = {a3moss@uwaterloo.ca},
    4195     title       = {Iterative and core-guided {MaxSAT} solving: A survey and assessment},
    4196     author      = {Morgado, Antonio and Heras, Federico and Liffiton, Mark and Planes, Jordi and Marques-Silva, Joao},
    4197     journal     = {Constraints},
    4198     volume      = {18},
    4199     number      = {4},
    4200     pages       = {478--534},
    4201     year        = {2013},
    4202     publisher   = {Springer}
    4203 }
    4204 
    42053796% J
    42063797                 
     
    42263817}
    42273818
    4228 @manual{Java11,
    4229     keywords    = {Java SE 11},
    4230     contributer = {pabuhr@plg},
    4231     author      = {James Gosling and Bill Joy and Guy Steele and Gilad Bracha and Alex Buckley and Daniel Smith},
    4232     title       = {{Java} Language Specification},
    4233     publisher   = {Oracle},
    4234     month       = sep,
    4235     year        = 2018,
    4236     edition     = {{J}ava {SE} 11},
    4237 }
    4238 
    4239 @manual{JDK1.1,
    4240     keywords    = {JDK 1.1},
    4241     contributer = {pabuhr@plg},
    4242     author      = {{Multithreading Models}},
    4243     title       = {JDK 1.1 for Solaris Developer's Guide},
    4244     publisher   = {Oracle},
    4245     address     = {\href{https://docs.oracle.com/cd/E19455-01/806-3461/6jck06gqk/index.html#ch2mt-41}{https://\-docs.oracle.com/\-cd/\-E19455-01/\-806-3461/\-6jck06gqk/\-index.html\#ch2mt-41}},
    4246     year        = 2010,
    4247 }
    4248 
    42493819@manual{JUC,
    42503820    keywords    = {Java concurrency library},
     
    42593829% K
    42603830
    4261 @inproceedings{Buhr96b,
    4262     author      = {Peter A. Buhr and Martin Karsten and Jun Shih},
    4263     title       = {{\small\textsf{KDB}}: A Multi-threaded Debugger for Multi-threaded Applications},
    4264     booktitle   = {Proc. of SPDT'96: SIGMETRICS Symp. on Parallel and Distributed Tools},
    4265     publisher   = {ACM Press},
    4266     address     = {Philadelphia, Pennsylvania, U.S.A.},
    4267     month       = may,
    4268     year        = 1996,
    4269     pages       = {80-87},
    4270 }
    4271 
    42723831@article{Duggan96,
    42733832    keywords    = {concurrency, critical section},
    42743833    contributer = {pabuhr@plg},
    4275     author      = {Dominic Duggan and Gordon V. Cormack and John Ophel},
     3834    author      = {Dominic Duggan and G. V. Cormack and John Ophel},
    42763835    title       = {Kinded Type Inference for Parametric Overloading},
    42773836    journal     = acta,
     
    44133972}
    44143973
    4415 @misc{libdill,
    4416     keywords    = {libdill/libmill Thread Library},
    4417     contributer = {pabuhr@plg},
    4418     author      = {Alex Cornejo, et al},
    4419     title       = {libdill Thread Library},
    4420     year        = 2019,
    4421     howpublished= {\href{http://libdill.org/libdill-2.14.tar.gz}
    4422                   {http://\-libdill.org/\-libdill-2.14.tar.gz}},
    4423 }
    4424 
    44253974@article{Linda,
    44263975    keywords    = {Linda, concurrency},
     
    44363985}
    44373986
    4438 @manual{libmill,
    4439     keywords    = {libmill},
    4440     contributer = {pabuhr@plg},
    4441     author      = {libmill},
    4442     title       = {{G}o-style concurrency in {C}, Version 1.18},
    4443     organization= {libmill},
    4444     address     = {\href{http://libmill.org/documentation.html}{http://\-libmill.org/\-documentation.html}},
    4445     month       = jan,
    4446     year        = 2017,
    4447 }
    4448 
    44493987@book{Weissman67,
    44503988    keywords    = {lisp},
     
    44563994}
    44573995
    4458 @article{Pierce00,
    4459     keywords    = {Scala},
    4460     contributer = {a3moss@uwaterloo.ca},
    4461     author      = {Pierce, Benjamin C. and Turner, David N.},
    4462     title       = {Local Type Inference},
    4463     journal     = {ACM Trans. Program. Lang. Syst.},
    4464     issue_date  = {Jan. 2000},
    4465     volume      = {22},
    4466     number      = {1},
    4467     month       = jan,
    4468     year        = {2000},
    4469     issn        = {0164-0925},
    4470     pages       = {1--44},
    4471     numpages    = {44},
    4472     url         = {http://doi.acm.org/10.1145/345099.345100},
    4473     doi         = {10.1145/345099.345100},
    4474     acmid       = {345100},
    4475     publisher   = {ACM},
    4476     address     = {New York, NY, USA},
    4477     keywords    = {polymorphism, subtyping, type inference},
    4478 }
    4479 
    44803996@article{Sundell08,
    44813997    keywords    = {lock free, deque},
     
    44884004    year        = 2008,
    44894005    pages       = {1008-1020},
    4490 }
    4491 
    4492 @misc{Matsakis17,
    4493     keywords    = {Rust, Chalk, PROLOG},
    4494     contributer = {a3moss@uwaterloo.ca},
    4495     author      = {Nicholas Matsakis},
    4496     title       = {Lowering {Rust} traits to logic},
    4497     month       = jan,
    4498     year        = 2017,
    4499     howpublished= {\href{http://smallcultfollowing.com/babysteps/blog/2017/01/26/lowering-rust-traits-to-logic/}
    4500                   {http://smallcultfollowing.com/\-babysteps/\-blog/\-2017/\-01/\-26/\-lowering-rust-traits-to-logic/}},
    4501     optnote     = {Accessed: 2019-01},
    45024006}
    45034007
     
    45164020}
    45174021
    4518 @manual{Lua,
    4519     keywords    = {Lua},
    4520     contributer = {pabuhr@plg},
    4521     author      = {Lua},
    4522     title       = {Lua 5.3 Reference Manual},
    4523     address     = {\href{https://www.lua.org/manual/5.3}{https://\-www.lua.org/\-manual/\-5.3}},
    4524     year        = 2018,
    4525 }
    4526 
    45274022% M
    45284023
     
    45344029    publisher   = {Motorola},
    45354030    year        = 1992,
    4536 }
    4537 
    4538 @misc{Haberman16,
    4539     keywords    = {C++ template expansion},
    4540     contributer = {a3moss@uwaterloo.ca},
    4541     author      = {Josh Haberman},
    4542     title       = {Making arbitrarily-large binaries from fixed-size {C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} code},
    4543     year        = 2016,
    4544     howpublished= {\href{http://blog.reverberate.org/2016/01/making-arbitrarily-large-binaries-from.html}
    4545                   {http://blog.reverberate.org/\-2016/\-01/\-making-arbitrarily-large-binaries-from.html}},
    4546     optnote     = {Accessed: 2016-09},
    45474031}
    45484032
     
    45674051}
    45684052
    4569 @misc{Marcel,
    4570     keywords    = {Marcel Thread Library},
    4571     contributer = {pabuhr@plg},
    4572     author      = {Gabriel Antoniu, et al},
    4573     title       = {Marcel Thread Library},
    4574     year        = 2011,
    4575     howpublished= {\href{https://gforge.inria.fr/frs/download.php/file/28643/marcel-2.99.3.tar.gz}
    4576                   {https://\-gforge.inria.fr/\-frs/\-download.php/\-file/\-28643/\-marcel-2.99.3.tar.gz}},
    4577 }
    4578 
    45794053@inproceedings{mprof,
    45804054    keywords    = {malloc},
     
    45934067    month       = sep,
    45944068    year        = 2006,
    4595     note        = {\textsf{http://cs.anu.edu.au/\-$\sim$Robin.Garner/\-mmtk-guide.pdf}},
     4069    note        = {\textsf{http://cs.anu.edu.au/\-\char`\~Robin.Garner/\-mmtk-guide.pdf}},
    45964070}
    45974071
     
    46974171    month       = sep,
    46984172    year        = 1994,
    4699     note        = {\href{https://plg.uwaterloo.ca/~usystem/pub/uSystem/uSystem.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-pub/\-uSystem/\-uSystem.pdf}},
     4173    note        = {{\small\textsf{ftp://\-plg.uwaterloo.ca/\-pub/\-uSystem/\-uSystem.ps.gz}}},
    47004174}
    47014175
     
    48734347}
    48744348%    editor     = {Allen Kent and James G. Williams},
    4875 
    4876 @incollection{MPC,
    4877     keywords    = {user-level threading},
    4878     contributer = {pabuhr@plg},
    4879     author      = {Marc P\'erache and Herv\'e Jourdren and Raymond Namyst},
    4880     title       = {MPC: A Unified Parallel Runtime for Clusters of {NUMA} Machines},
    4881     booktitle   = {Euro-Par 2008},
    4882     pages       = {329-342},
    4883     publisher   = {Springer},
    4884     address     = {Berlin, Heidelberg},
    4885     year        = 2008,
    4886     volume      = 5168,
    4887     series      = {Lecture Notes in Computer Science},
    4888 }
    48894349
    48904350@manual{MPI,
     
    50554515
    50564516% N
    5057 
    5058 @techreport{Drepper03,
    5059     keywords    = {NPTL, threading, 1:1 model},
    5060     contributer = {pabuhr@plg},
    5061     author      = {Ulrich Drepper and Ingo Molnar},
    5062     title       = {The Native POSIX Thread Library for Linux},
    5063     institution = {Red Hat},
    5064     year        = 2003,
    5065     note        = {\href{http://www.cs.utexas.edu/~witchel/372/lectures/POSIX_Linux_Threading.pdf}{http://www.cs.utexas.edu/\-$\sim$witchel/\-372/\-lectures/\-POSIX\_Linux\_Threading.pdf}},
    5066 }
    50674517
    50684518@article{Haddon77,
     
    51914641}
    51924642
    5193 @misc{nginx,
    5194     key         = {nginx},
    5195     author      = {{NGINX}},
    5196     howpublished= {\href{https://www.nginx.com}{https://\-www.nginx.com}},
    5197 }
    5198 
    51994643@article{Herlihy05,
    52004644    keywords    = {Multiprocessors, concurrent data structures, dynamic data structures, memory management, nonblocking synchronization},
     
    52534697    year        = 1995,
    52544698    number      = 31,
    5255     note        = {{\small\textsf{http://\-www.cs.wustl.edu/\-$\sim$schmidt/\-PDF/\-IPC\_SAP-92.pdf}}},
     4699    note        = {{\small\textsf{http://\-www.cs.wustl.edu/\-\char`\~schmidt/\-PDF/\-IPC\_SAP-92.pdf}}},
    52564700}
    52574701
     
    53074751@misc{obj-c-book,
    53084752    keywords    = {objective-c},
    5309     contributor = {pabuhr@plg},
     4753    contributor = {a3moss@uwaterloo.ca},
    53104754    key         = {Objective-C},
    5311     author      = {Objective-C},
     4755    title       = {Objective-C},
    53124756    publisher   = {Apple Inc.},
    5313     year        = 2014,
    5314     howpublished= {\href{https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC}{https://\-developer.apple.com/\-library/archive/\-documentation/\-Cocoa/\-Conceptual/\-ProgrammingWithObjectiveC}},
     4757    year        = 2015,
     4758    howpublished= {\href{https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/ObjectiveC.html}{https://developer.apple.com/\-library/\-content/\-documentation/\-General/\-Conceptual/\-DevPedia-\-CocoaCore/\-ObjectiveC.html}},
     4759    optnote     = {Accessed: 2018-03}
    53154760}
    53164761
     
    53214766    title       = {{X}code 7 Release Notes},
    53224767    year        = 2015,
    5323     howpublished= {\href{https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc7_release_notes.html}{https://\-developer.apple.com/\-library/\-content/\-documentation/\-Xcode/\-Conceptual/\-RN-Xcode-Archive/\-Chapters/\-xc7\_release\_notes.html}},
     4768    howpublished= {\href{https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc7_release_notes.html}{https://developer.apple.com/\-library/\-content/\-documentation/\-Xcode/\-Conceptual/\-RN-Xcode-Archive/\-Chapters/\-xc7\_release\_notes.html}},
     4769    optnote     = {Accessed: 2017-04}
    53244770}
    53254771
     
    54474893}
    54484894
    5449 @manual{OpenMP,
     4895@techreport{OpenMP,
    54504896    keywords    = {concurrency, openmp, spmd},
    54514897    contributer = {pabuhr@plg},
    5452     key         = {OpenMP},
    5453     title       = {OpenMP Application Program Interface, Version 4.5},
    5454     month       = nov,
    5455     year        = 2015,
    5456     note        = {\href{https://www.openmp.org/wp-content/uploads/openmp-4.5.pdf}{https://\-www.openmp.org/\-wp-content/\-uploads/\-openmp-4.5.pdf}},
    5457 }
    5458 
    5459 @inproceedings{Krebbers14,
    5460     keywords    = {c formalization},
    5461     contributer = {a3moss@uwaterloo.ca},
    5462     author      = {Krebbers, Robbert},
    5463     title       = {An Operational and Axiomatic Semantics for Non-determinism and Sequence Points in C},
    5464     booktitle   = {Proceedings of the 41st ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages},
    5465     series      = {POPL '14},
    5466     year        = {2014},
    5467     isbn        = {978-1-4503-2544-8},
    5468     location    = {San Diego, California, USA},
    5469     pages       = {101--112},
    5470     numpages    = {12},
    5471     url         = {http://doi.acm.org/10.1145/2535838.2535878},
    5472     doi         = {10.1145/2535838.2535878},
    5473     acmid       = {2535878},
    5474     publisher   = {ACM},
    5475     address     = {New York, NY, USA},
    5476 }
     4898    author      = {OpenMP Architecture Review Board},
     4899    title       = {OpenMP Application Program Interface, Version 4.0},
     4900    month       = jul,
     4901    year        = 2013,
     4902    note        = {\href{http://www.openmp.org/mp-documents/OpenMP4.0.0.pdf}{http://\-www.openmp.org/\-mp-documents/\-OpenMP4.0.0.pdf}},
     4903}
    54774904
    54784905@book{Deitel04,
     
    58395266}
    58405267
    5841 @misc{perf,
    5842     contributer = {pabuhr@plg},
    5843     key         = {perf},
    5844     author      = {perf},
    5845     howpublished= {\href{https://perf.wiki.kernel.org/index.php/Tutorial}{https://\-perf.wiki.kernel.org/\-index.php/\-Tutorial}},
    5846 }
    5847 
    5848 @misc{Verch12,
    5849     contributer = {pabuhr@plg},
    5850     author      = {Shaun Verch},
    5851     title       = {Performance Analysis of 64-Bit Capriccio},
    5852     month       = may,
    5853     year        = 2012,
    5854     howpublished= {\href{http://cs.brown.edu/research/pubs/theses/masters/2012/verch.pdf}{http://cs.brown.edu/\-research/\-pubs/\-theses/\-masters/\-2012/\-verch.pdf}},
    5855 }
    5856 
    58575268@article{Anderson90,
    58585269    keywords    = {spin locks, back off, performance},
     
    58665277    number      = 1,
    58675278    pages       = {6-16},
    5868 }
    5869 
    5870 @inproceedings{Conchon07,
    5871     keywords    = {persistent array, union-find},
    5872     contributer = {a3moss@uwaterloo.ca},
    5873     title       = {A persistent union-find data structure},
    5874     author      = {Conchon, Sylvain and Filli{\^a}tre, Jean-Christophe},
    5875     booktitle   = {Proceedings of the 2007 workshop on Workshop on ML},
    5876     pages       = {37--46},
    5877     year        = {2007},
    5878     organization= {ACM}
    58795279}
    58805280
     
    60885488}
    60895489
    6090 @inproceedings{Buhr98,
    6091     keywords    = {profiling, monitoring, visualization},
    6092     contributer = {pabuhr@plg},
    6093     author      = {Peter A. Buhr and Robert Denda},
    6094     title       = {{$\mu$Profiler} : Profiling User-Level Threads in a Shared-Memory Programming Environment},
    6095     booktitle   = {Proc. of 2nd Inter. Symp. on Computing in Object-Oriented Parallel Environments},
    6096     series      = {Lecture Notes in Computer Science},
    6097     publisher   = {Springer-Verlag},
    6098     volume      = 1505,
    6099     opteditor   = {Dennis Caromel and Rodney R. Oldehoeft and Marydell Tholburn},
    6100     address     = {Santa Fe, New Mexico, U.S.A.},
    6101     month       = dec,
    6102     year        = 1998,
    6103     pages       = {159-166},
    6104 }
    6105 
    61065490@book{PowerPC,
    61075491    key         = {PowerPC processor},
     
    61765560    address     = {\href{https://www.iso.org/standard/64029.html}{https://\-www.iso.org/\-standard/\-64029.html}},
    61775561    year        = 2014,
    6178 }
    6179 
    6180 @manual{C++17,
    6181     keywords    = {ISO/IEC C++ 17},
    6182     contributer = {pabuhr@plg},
    6183     key         = {C++17},
    6184     title       = {{C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Programming Language ISO/IEC 14882:2017},
    6185     edition     = {5th},
    6186     publisher   = {International Standard Organization},
    6187     address     = {\href{https://www.iso.org/standard/68564.html}{https://\-www.iso.org/\-standard/\-68564.html}},
    6188     year        = 2017,
    61895562}
    61905563
     
    63405713    institution = {Carnegie Mellon University},
    63415714    year        = 1991,
    6342     month       = feb,
    6343     number      = {CMU-CS-91-106},
     5715    month       = feb, number = "CMU-CS-91-106",
    63445716    annote      = {
    63455717        Discusses a typed lambda calculus with
     
    63815753}
    63825754
    6383 @article{Moore75,
    6384     keywords    = {approximation methods, integrated circuits},
    6385     contributer = {pabuhr@plg},
    6386     author      = {Gordon E. Moore},
    6387     title       = {Progress in Digital Integrated Electronics},
    6388     journal     = {Technical Digest, International Electron Devices Meeting, IEEE},
    6389     year        = 1975,
    6390     pages       = {11-13},
    6391 }
    6392 
    63935755@article{promises,
    63945756    keywords    = {futures, Argus, call streams, rpc},
    63955757    contributer = {gjditchfield@plg},
    63965758    author      = {Barbara Liskov and Liuba Shrira},
    6397     title       = {Promises: Linguistic Support for Efficient Asynchronous Procedure Calls in Distributed Systems},
     5759    title       = {Promises: Linguistic Support for Efficient Asynchronous
     5760          Procedure Calls in Distributed Systems},
    63985761    journal     = sigplan,
    63995762    year        = 1988,
    6400     month       = jul,
    6401     volume      = 23,
    6402     number      = 7,
    6403     pages       = {260-267},
    6404     note        = {Proceedings of the SIGPLAN '88 Conference on Programming Language Design and Implementation},
     5763    month       = jul, volume = 23, number = 7, pages = {260-267},
     5764    note        = {Proceedings of the SIGPLAN '88 Conference on Programming Language
     5765         Design and Implementation},
    64055766    abstract    = {
    64065767        This paper deals with the integration of an efficient asynchronous
     
    64525813}
    64535814
    6454 @misc{Pthreads,
    6455     keywords    = {pthreads, C concurrency},
    6456     contributer = {pabuhr@plg},
    6457     key         = {pthreads},
    6458     title       = {{Pthread}.h, Specifications Issue 7, {IEEE} Std 1003.1-2017},
    6459     author      = {IEEE and {The Open Group}},
    6460     year        = 2018,
    6461     howpublished= {\href{http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html}
    6462                   {http://\-pubs.opengroup.org/\-onlinepubs/\-9699919799/\-basedefs/\-pthread.h.html}},
    6463 }
    6464 
    64655815@manual{Python,
    64665816    keywords    = {Python},
    64675817    contributer = {pabuhr@plg},
    6468     author      = {Python},
    6469     title       = {Python Language Reference, Release 3.7.2},
     5818    title       = {Python Reference Manual, Release 2.5},
     5819    author      = {Guido van Rossum},
    64705820    organization= {Python Software Foundation},
    6471     address     = {\href{https://docs.python.org/3/reference/index.html}{https://\-docs.python.org/\-3/\-reference/\-index.html}},
    6472     year        = 2018,
     5821    month       = sep,
     5822    year        = 2006,
     5823    note        = {Fred L. Drake, Jr., editor},
    64735824}
    64745825
    64755826% Q
    6476 
    6477 @inproceedings{Qthreads,
    6478     keywords    = {user-level threading},
    6479     author      = {Kyle B. Wheeler and Richard C. Murphy and Douglas Thain},
    6480     title       = {Qthreads: An API for Programming with Millions of Lightweight Threads},
    6481     booktitle   = {International Symposium on Parallel and Distributed Processing},
    6482     organization= {IEEE},
    6483     address     = {Miami, FL, USA},
    6484     month       = apr,
    6485     year        = 2008,
    6486 }
    64875827
    64885828@article{Grossman06,
    64895829    keywords    = {Cyclone, existential types, polymorphism, type variables},
    64905830    contributer = {a3moss@plg},
    6491     author      = {Dan Grossman},
     5831    author      = {D. Grossman},
    64925832    title       = {Quantified Types in an Imperative Language},
    64935833    journal     = toplas,
     
    64995839    issn        = {0164-0925},
    65005840    pages       = {429-475},
    6501     url         = {http://doi.acm.org/10.1145/1133651.1133653},
     5841    url         = {http://doi.acm.org.proxy.lib.uwaterloo.ca/10.1145/1133651.1133653},
    65025842    doi         = {10.1145/1133651.1133653},
    65035843    acmid       = {1133653},
     
    65215861}
    65225862
    6523 @manual{Quasar,
    6524     keywords    = {Quasar},
    6525     contributer = {pabuhr@plg},
    6526     author      = {Quasar},
    6527     title       = {Quasar Documentation, Release 0.8.0},
    6528     organization= {Parallel Universe},
    6529     address     = {\href{http://docs.paralleluniverse.co/quasar}{http://\-docs.paralleluniverse.co/\-quasar}},
    6530     year        = 2018,
    6531 }
    6532 
    65335863% R
    65345864
     
    66085938}
    66095939
    6610 @article{Ronsse03,
    6611     keywords    = {profiling, replay},
    6612     contributer = {pabuhr@plg},
    6613     author      = {Michiel Ronsse and De Bosschere, Koen and Mark Christiaens and Jacques Chassin de Kergommeaux and Dieter Kranzlm\"{u}ller},
    6614     title       = {Record/Replay for Nondeterministic Program Executions},
    6615     journal     = cacm,
    6616     month       = sep,
    6617     year        = 2003,
    6618     volume      = 46,
    6619     number      = 9,
    6620     pages       = {62-67},
    6621 }
    6622 
    66235940@article{Robinson48,
    66245941    keywords    = {recursion, Ackermann function},
     
    66465963}
    66475964
    6648 @article{Hesselink06,
    6649     author      = {Wim H. Hesselink},
    6650     title       = {Refinement Verification of the Lazy Caching Algorithm},
    6651     journal     = acta,
    6652     year        = 2006,
    6653     month       = oct,
    6654     volume      = 43,
    6655     number      = 3,
    6656     pages       = {195--222},
    6657 }
    6658 
    66595965@article{RemoteRendezvous,
    66605966    keywords    = {rendezvous, concurrency},
     
    66705976}
    66715977
    6672 @mastersthesis{Schuster99,
    6673     author      = {Oliver Schuster},
    6674     title       = {Replay of Concurrent Shared-Memory Programs},
    6675     school      = {Universit\"at Mannheim},
    6676     address     = {Mannheim, Deutschland},
    6677     year        = 1999,
    6678     month       = apr,
    6679     type        = {Diplomarbeit},
    6680     note        = {\href{https://plg.uwaterloo.ca/~usystem/theses/SchusterThesis.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-theses/\-SchusterThesis.pdf}},
    6681 }
    6682 
    66835978@article{Euclid,
    66845979    keywords    = {Euclid},
     
    67126007    school      = {School of Computer Science, University of Waterloo},
    67136008    year        = 2017,
    6714     optaddress  = {Waterloo, Ontario, Canada, N2L 3G1},
     6009    address     = {Waterloo, Ontario, Canada, N2L 3G1},
    67156010    note        = {\href{https://uwspace.uwaterloo.ca/handle/10012/11830}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-11830}},
    67166011}
     
    67876082    contributer = {pabuhr@plg},
    67886083    key         = {Rust},
    6789     title       = {{R}ust Programming Language},
    6790     optaddress  = {Rust Project Developers},
     6084    title       = {The {R}ust Programming Language},
     6085    address     = {The Rust Project Developers},
    67916086    year        = 2015,
    67926087    note        = {\href{https://doc.rust-lang.org/reference.html}{https://\-doc.rust-lang\-.org/\-reference.html}},
    6793 }
    6794 
    6795 @manual{Ruby,
    6796     keywords    = {Ruby},
    6797     contributer = {pabuhr@plg},
    6798     author      = {Ruby},
    6799     title       = {Ruby Documentation, Release 2.6.0},
    6800     organization= {Python Software Foundation},
    6801     address     = {\href{https://www.ruby-lang.org/en/documentation}{https://\-www.ruby-lang.org/\-en/\-documentation}},
    6802     year        = 2018,
    68036088}
    68046089
     
    68646149    publisher   = {Springer},
    68656150    note        = {Lecture Notes in Computer Science v. 173},
    6866 }
    6867 
    6868 @article{Baker78,
    6869     keywords    = {Algol display, FUNARG's, Lisp 1.5, deep binding, environment trees, multiprogramming, shallow binding},
    6870     contributer = {a3moss@uwaterloo.ca},
    6871     author      = {Baker,Jr., Henry G.},
    6872     title       = {Shallow Binding in Lisp 1.5},
    6873     journal     = {Commun. ACM},
    6874     issue_date  = {July 1978},
    6875     volume      = 21,
    6876     number      = 7,
    6877     month       = jul,
    6878     year        = 1978,
    6879     issn        = {0001-0782},
    6880     pages       = {565--569},
    6881     numpages    = {5},
    6882     url         = {http://doi.acm.org/10.1145/359545.359566},
    6883     doi         = {10.1145/359545.359566},
    6884     acmid       = {359566},
    6885     publisher   = {ACM},
    6886     address     = {New York, NY, USA}
    6887 }
    6888 
    6889 @article{Baker91,
    6890     keywords    = {shallow binding, functional arrays},
    6891     contributer = {a3moss@uwaterloo.ca},
    6892     author      = {Baker, Henry G.},
    6893     title       = {Shallow Binding Makes Functional Arrays Fast},
    6894     journal     = {SIGPLAN Not.},
    6895     issue_date  = {Aug. 1991},
    6896     volume      = 26,
    6897     number      = 8,
    6898     month       = aug,
    6899     year        = 1991,
    6900     issn        = {0362-1340},
    6901     pages       = {145--147},
    6902     numpages    = {3},
    6903     url         = {http://doi.acm.org/10.1145/122598.122614},
    6904     doi         = {10.1145/122598.122614},
    6905     acmid       = {122614},
    6906     publisher   = {ACM},
    6907     address     = {New York, NY, USA},
    69086151}
    69096152
     
    75396782}
    75406783
    7541 @article{SysVABI,
    7542     keywords    =  {System V ABI},
    7543     contributer =  {a3moss@uwaterloo.ca},
    7544     title       = {System {V} application binary interface},
    7545     author      = {Matz, Michael and Hubicka, Jan and Jaeger, Andreas and Mitchell, Mark},
    7546     journal     = {AMD64 Architecture Processor Supplement, Draft v0},
    7547     volume      = {99},
    7548     year        = {2013}
    7549 }
    7550 
    75516784% T
    75526785
     
    76016834    contributer = {pabuhr@plg},
    76026835    key         = {TIOBE Index},
    7603     author      = {{TIOBE Index}},
     6836    title       = {{TIOBE} Index},
    76046837    howpublished= {\href{http://www.tiobe.com/tiobe_index}{http://\-www.tiobe.com/\-tiobe\_index}},
    7605 }
    7606 
    7607 @misc{ThreadModel,
    7608     contributer = {pabuhr@plg},
    7609     key         = {ThreadModel},
    7610     title       = {Thread (computing)},
    7611     author      = {{Threading Model}},
    7612     howpublished= {\href{https://en.wikipedia.org/wiki/Thread_(computing)}{https://\-en.wikipedia.org/\-wiki/\-Thread\_(computing)}},
     6838    optnote     = {Accessed: 2018-09},
    76136839}
    76146840
     
    77486974    year        = 1980
    77496975}
    7750 
    7751 @misc{TraceCompass,
    7752     contributer = {pabuhr@plg},
    7753     key         = {Trace Compass},
    7754     author      = {{T}race {C}ompass},
    7755     howpublished= {\href{https://projects.eclipse.org/proposals/trace-compass}{https://\-projects.eclipse.org/\-proposals/\-trace-compass}},
    7756 }
    77576976 
    77586977@article{Leroy00,
     
    77706989        Argues against declaring exceptions on routine definitions.
    77716990    },
    7772 }
    7773 
    7774 @techreport{Black90,
    7775     title       = {Typechecking polymorphism in {Emerald}},
    7776     author      = {Black, Andrew P and Hutchinson, Norman C},
    7777     year        = {1990},
    7778     institution = {Cambridge Research Laboratory, Digital Equipment Corporation}
    77796991}
    77806992
     
    78977109    title       = {Usability Challenges in Exception Handling},
    78987110    booktitle   = {5th International Workshop on Exception Handling (WEH)},
    7899     optorganization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)},
     7111    organization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)},
    79007112    address     = {Zurich, Switzerland},
    79017113    month       = jun,
     
    79497161    year        = 2017,
    79507162    howpublished= {\url{https://wiki.gnome.org/Projects/Vala/Manual}},
     7163    optnote     = {Accessed: 2017-04}
    79517164}
    79527165
     
    80407253}
    80417254
    8042 @inproceedings{vonBehren03,
    8043     keywords    = {threads, events, web server},
    8044     contributer = {pabuhr@plg},
    8045     author      = {Rob von Behren and Jeremy Condit and Eric Brewer},
    8046     title       = {Why Events Are a Bad Idea (for high-concurrency servers)},
    8047     booktitle   = {HotOS IX: The 9th Workshop on Hot Topics in Operating Systems},
    8048     publisher   = {USENIX Association},
    8049     address     = {Lihue, Hawaii, U.S.A.},
    8050     month       = may,
    8051     year        = 2003,
    8052     pages       = {19-24},
    8053 }
    8054 
    80557255@techreport{Moss90,
    80567256    keywords    = {Swizzling, database},
     
    80977297}
    80987298
    8099 @article{Tarjan84,
    8100     keywords    = {union-find},
    8101     contributer = {a3moss@uwaterloo.ca},
    8102     author      = {Tarjan, Robert E. and van Leeuwen, Jan},
    8103     title       = {Worst-case Analysis of Set Union Algorithms},
    8104     journal     = {J. ACM},
    8105     issue_date  = {April 1984},
    8106     volume      = 31,
    8107     number      = 2,
    8108     month       = mar,
    8109     year        = 1984,
    8110     issn        = {0004-5411},
    8111     pages       = {245--281},
    8112     numpages    = {37},
    8113     url         = {http://doi.acm.org/10.1145/62.2160},
    8114     doi         = {10.1145/62.2160},
    8115     acmid       = {2160},
    8116     publisher   = {ACM},
    8117     address     = {New York, NY, USA},
    8118 }
    8119 
    81207299% X
    81217300
    81227301% Y
    8123 
    8124 @article{Boehm12,
    8125     keywords    = {memory model, race condition},
    8126     contributer = {pabuhr@plg},
    8127     author      = {Boehm, Hans-J. and Adve, Sarita V.},
    8128     title       = {You Don'T Know Jack About Shared Variables or Memory Models},
    8129     journal     = cacm,
    8130     volume      = 55,
    8131     number      = 2,
    8132     month       = feb,
    8133     year        = 2012,
    8134     pages       = {48--54},
    8135     publisher   = {ACM},
    8136     address     = {New York, NY, USA},
    8137 }
    81387302
    81397303% Z
     
    81537317    year        = 1986,
    81547318    editor      = {Norman Meyrowitz},
    8155     publisher   = sigplan,
     7319    publisher   = sigplan # " 21(11)",
    81567320    organization= {Association for Computing Machinery},
    81577321    address     = {Portland, Oregon},
    8158     month       = sep,
     7322    month       = sep # { 29}
    81597323}
    81607324
     
    81657329    year        = 1987,
    81667330    editor      = {Norman Meyrowitz},
    8167     publisher   = sigplan,
     7331    publisher   = sigplan # " 22(12)",
    81687332    organization= {Association for Computing Machinery},
    81697333    address     = {Orlando, Florida},
    8170     month       = oct,
     7334    month       = oct # { 4--8}
    81717335}
    81727336
     
    81777341    year        = 1988,
    81787342    editor      = {Norman Meyrowitz},
    8179     publisher   = sigplan,
     7343    publisher   = sigplan # " 23(11)",
    81807344    organization= {Association for Computing Machinery},
    81817345    address     = {San Diego, California},
    8182     month       = sep,
     7346    month       = sep # { 25--30}
    81837347}
    81847348
     
    81897353    year        = 1989,
    81907354    editor      = {Norman Meyrowitz},
    8191     publisher   = sigplan,
     7355    publisher   = sigplan # " 24(10)",
    81927356    organization= {Association for Computing Machinery},
    81937357    address     = {New Orleans, Louisiana},
    8194     month       = oct,
     7358    month       = oct # { 1--6}
    81957359}
    81967360
     
    82017365    year        = 1990,
    82027366    editor      = {Norman Meyrowitz},
    8203     publisher   = sigplan,
     7367    publisher   = sigplan # " 25(10)",
    82047368    organization= {Association for Computing Machinery},
    82057369    address     = {Ottawa, Canada},
    8206     month       = oct,
     7370    month       = oct # { 21--25}
    82077371}
    82087372
     
    82137377    year        = 1991,
    82147378    editor      = {Andreas Paepcke},
    8215     publisher   = sigplan,
     7379    publisher   = sigplan # " 26(11)",
    82167380    organization= {Association for Computing Machinery},
    82177381    address     = {Phoenix, Arizona},
    8218     month       = oct,
    8219 }
     7382    month       = oct # { 6--11}
     7383}
  • doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls

    rb067d9b r7951100  
    18541854    \vspace*{8.5\p@}%
    18551855    \rightskip0pt\raggedright\hspace*{7\p@}\hbox{\reset@font\abstractfont{\absheadfont#1}}\par\vskip3pt% LN20feb2016
    1856     {\abstractfont\baselineskip15pt\ifFWabstract\hsize\textwidth\fi\hsize0.68\textwidth#2\par\vspace*{0\p@}}%
     1856    {\abstractfont\baselineskip15pt\ifFWabstract\hsize\textwidth\fi#2\par\vspace*{0\p@}}%
    18571857    \addcontentsline{toc}{section}{\abstractname}%
    18581858}}%\abstract{}%
     
    18821882}%
    18831883%
    1884 \def\fundinginfohead#1{\gdef\@fundinginfo@head{#1}}\fundinginfohead{Funding information}%
     1884\def\fundinginfohead#1{\gdef\@fundinginfo@head{#1}}\fundinginfohead{Funding Information}%
    18851885\def\fundinginfoheadtext#1{\gdef\@fundinginfo@head@text{#1}}\fundinginfoheadtext{}%
    18861886\gdef\@fundinginfo{{%
     
    23192319%% Keywords %%
    23202320
    2321 \def\keywords#1{\def\@keywords{{\keywordsheadfont\textbf{KEYWORDS}\par\removelastskip\nointerlineskip\vskip6pt \keywordsfont#1\par}}}\def\@keywords{}%
     2321\def\keywords#1{\def\@keywords{{\keywordsheadfont\textbf{KEYWORDS:}\par\removelastskip\nointerlineskip\vskip6pt \keywordsfont#1\par}}}\def\@keywords{}%
    23222322
    23232323\def\@fnsymbol#1{\ifcase#1\or \dagger\or \ddagger\or
     
    24442444     \@afterheading}
    24452445
    2446 \renewcommand\section{\@startsection{section}{1}{\z@}{-25pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}%
    2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-22pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}%
     2446\renewcommand\section{\@startsection{section}{1}{\z@}{-27pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}%
     2447\renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-23pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}%
    24482448\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}{-20pt \@plus -2pt \@minus -2pt}{2\p@}{\subsubsectionfont}}%
    24492449%
     
    34063406\hskip-\parindentvalue\fbox{\vbox{\noindent\@jnlcitation}}}%
    34073407
    3408 %\AtEndDocument{\ifappendixsec\else\printjnlcitation\fi}%
     3408\AtEndDocument{\ifappendixsec\else\printjnlcitation\fi}%
    34093409
    34103410%% Misc math macros %%
  • doc/papers/OOPSLA17/Makefile

    rb067d9b r7951100  
    3333
    3434DOCUMENT = generic_types.pdf
    35 BASE = ${basename ${DOCUMENT}}
    3635
    3736# Directives #
     
    4241
    4342clean :
    44         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     43        @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
    4544
    4645# File Dependencies #
    4746
    48 ${DOCUMENT} : ${BASE}.ps
     47${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    4948        ps2pdf $<
    5049
    51 ${BASE}.ps : ${BASE}.dvi
     50${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    5251        dvips ${Build}/$< -o $@
    5352
    54 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    55                 ../../bibliography/pl.bib | ${Build}
     53${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ../../bibliography/pl.bib
    5654        # Must have *.aux file containing citations for bibtex
    5755        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    6563## Define the default recipes.
    6664
    67 ${Build} :
     65${Build}:
    6866        mkdir -p ${Build}
    6967
     
    7169        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    7270
    73 %.tex : %.fig | ${Build}
     71%.tex : %.fig
    7472        fig2dev -L eepic $< > ${Build}/$@
    7573
    76 %.ps : %.fig | ${Build}
     74%.ps : %.fig
    7775        fig2dev -L ps $< > ${Build}/$@
    7876
    79 %.pstex : %.fig | ${Build}
     77%.pstex : %.fig
    8078        fig2dev -L pstex $< > ${Build}/$@
    8179        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/concurrency/Makefile

    rb067d9b r7951100  
    44Figures = figures
    55Macros = ../AMA/AMA-stix/ama
    6 TeXLIB = .:../../LaTeXmacros:${Macros}:${Build}:
     6TeXLIB = .:annex:../../LaTeXmacros:${Macros}:${Build}:../../bibliography:
    77LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    8 BibTeX = BIBINPUTS=annex:../../bibliography: && export BIBINPUTS && bibtex
     8BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
    99
    1010MAKEFLAGS = --no-print-directory # --silent
     
    1515SOURCES = ${addsuffix .tex, \
    1616Paper \
     17style/style \
     18style/cfa-format \
    1719}
    1820
    1921FIGURES = ${addsuffix .tex, \
     22monitor \
     23ext_monitor \
    2024int_monitor \
    2125dependency \
    22 RunTimeStructure \
    2326}
    2427
    2528PICTURES = ${addsuffix .pstex, \
    26 FullProdConsStack \
    27 FullCoroutinePhases \
    28 corlayout \
    29 CondSigWait \
    30 monitor \
    31 ext_monitor \
    3229system \
    3330monitor_structs \
     
    6259        dvips ${Build}/$< -o $@
    6360
    64 ${BASE}.dvi : Makefile ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    65                 annex/local.bib ../../bibliography/pl.bib | ${Build}
     61${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     62                annex/local.bib ../../bibliography/pl.bib
    6663        # Must have *.aux file containing citations for bibtex
    6764        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    68         -${BibTeX} ${Build}/${basename $@}
     65        ${BibTeX} ${Build}/${basename $@}
    6966        # Some citations reference others so run again to resolve these citations
    7067        ${LaTeX} ${basename $@}.tex
    71         -${BibTeX} ${Build}/${basename $@}
     68        ${BibTeX} ${Build}/${basename $@}
    7269        # Run again to finish citations
    7370        ${LaTeX} ${basename $@}.tex
     
    7572## Define the default recipes.
    7673
    77 ${Build} :
     74${Build}:
    7875        mkdir -p ${Build}
    7976
    80 ${BASE}.out.ps : | ${Build}
     77${BASE}.out.ps: ${Build}
    8178        ln -fs ${Build}/Paper.out.ps .
    8279
    83 WileyNJD-AMA.bst :
     80WileyNJD-AMA.bst:
    8481        ln -fs ../AMA/AMA-stix/ama/WileyNJD-AMA.bst .
    8582
    86 %.tex : %.fig | ${Build}
     83%.tex : %.fig ${Build}
    8784        fig2dev -L eepic $< > ${Build}/$@
    8885
    89 %.ps : %.fig | ${Build}
     86%.ps : %.fig ${Build}
    9087        fig2dev -L ps $< > ${Build}/$@
    9188
    92 %.pstex : %.fig | ${Build}
     89%.pstex : %.fig ${Build}
    9390        fig2dev -L pstex $< > ${Build}/$@
    9491        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/concurrency/Paper.tex

    rb067d9b r7951100  
    33\articletype{RESEARCH ARTICLE}%
    44
    5 % Referees
    6 % Doug Lea, dl@cs.oswego.edu, SUNY Oswego
    7 % Herb Sutter, hsutter@microsoft.com, Microsoft Corp
    8 % Gor Nishanov, gorn@microsoft.com, Microsoft Corp
    9 % James Noble, kjx@ecs.vuw.ac.nz, Victoria University of Wellington, School of Engineering and Computer Science
    10 
    11 \received{XXXXX}
    12 \revised{XXXXX}
    13 \accepted{XXXXX}
     5\received{26 April 2016}
     6\revised{6 June 2016}
     7\accepted{6 June 2016}
    148
    159\raggedbottom
     
    2115\usepackage{epic,eepic}
    2216\usepackage{xspace}
    23 \usepackage{enumitem}
    2417\usepackage{comment}
    2518\usepackage{upquote}                                            % switch curled `'" to straight
     
    2821\renewcommand{\thesubfigure}{(\Alph{subfigure})}
    2922\captionsetup{justification=raggedright,singlelinecheck=false}
    30 \usepackage{dcolumn}                                            % align decimal points in tables
    31 \usepackage{capt-of}
    32 \setlength{\multicolsep}{6.0pt plus 2.0pt minus 1.5pt}
     23\usepackage{siunitx}
     24\sisetup{binary-units=true}
    3325
    3426\hypersetup{breaklinks=true}
     
    4032\renewcommand{\linenumberfont}{\scriptsize\sffamily}
    4133
    42 \renewcommand{\topfraction}{0.8}                        % float must be greater than X of the page before it is forced onto its own page
    43 \renewcommand{\bottomfraction}{0.8}                     % float must be greater than X of the page before it is forced onto its own page
    44 \renewcommand{\floatpagefraction}{0.8}          % float must be greater than X of the page before it is forced onto its own page
    4534\renewcommand{\textfraction}{0.0}                       % the entire page maybe devoted to floats with no text on the page at all
    4635
     
    143132\makeatother
    144133
    145 \newenvironment{cquote}
    146                {\list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=3pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}%
    147                 \item\relax}
    148                {\endlist}
    149 
    150 %\newenvironment{cquote}{%
    151 %\list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=3pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}%
    152 %\item\relax%
    153 %}{%
    154 %\endlist%
    155 %}% cquote
     134\newenvironment{cquote}{%
     135        \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=3pt\parsep=0pt\leftmargin=\parindentlnth\rightmargin\leftmargin}%
     136        \item\relax
     137}{%
     138        \endlist
     139}% cquote
    156140
    157141% CFA programming language, based on ANSI C (with some gcc additions)
     
    161145                auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
    162146                coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally,
    163                 __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__,
     147                __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__,
    164148                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
    165149                otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread,
    166150                _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,
    167151                virtual, __volatile, __volatile__, waitfor, when, with, zero_t},
    168         moredirectives={defined,include_next},
    169         % replace/adjust listing characters that look bad in sanserif
    170         literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    171                 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    172                 {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
    173                 {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textrm{\textgreater}}}2,
     152        moredirectives={defined,include_next}%
    174153}
    175154
     
    188167aboveskip=4pt,                                                                                  % spacing above/below code block
    189168belowskip=3pt,
     169% replace/adjust listing characters that look bad in sanserif
     170literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
     171        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
     172        {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
     173        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textrm{\textgreater}}}2,
    190174moredelim=**[is][\color{red}]{`}{`},
    191175}% lstset
     
    213197}
    214198
    215 % Go programming language: https://github.com/julienc91/listings-golang/blob/master/listings-golang.sty
    216 \lstdefinelanguage{Golang}{
    217         morekeywords=[1]{package,import,func,type,struct,return,defer,panic,recover,select,var,const,iota,},
    218         morekeywords=[2]{string,uint,uint8,uint16,uint32,uint64,int,int8,int16,int32,int64,
    219                 bool,float32,float64,complex64,complex128,byte,rune,uintptr, error,interface},
    220         morekeywords=[3]{map,slice,make,new,nil,len,cap,copy,close,true,false,delete,append,real,imag,complex,chan,},
    221         morekeywords=[4]{for,break,continue,range,goto,switch,case,fallthrough,if,else,default,},
    222         morekeywords=[5]{Println,Printf,Error,},
    223         sensitive=true,
    224         morecomment=[l]{//},
    225         morecomment=[s]{/*}{*/},
    226         morestring=[b]',
    227         morestring=[b]",
    228         morestring=[s]{`}{`},
    229         % replace/adjust listing characters that look bad in sanserif
    230         literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    231                 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    232                 {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
    233                 {<-}{\makebox[2ex][c]{\textrm{\textless}\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}}2,
    234 }
    235 
    236199\lstnewenvironment{cfa}[1][]
    237200{\lstset{#1}}
     
    244207{}
    245208\lstnewenvironment{Go}[1][]
    246 {\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
    247 {}
    248 \lstnewenvironment{python}[1][]
    249 {\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     209{\lstset{#1}}
    250210{}
    251211
     
    262222}
    263223
    264 \newbox\myboxA
    265 \newbox\myboxB
    266 \newbox\myboxC
    267 \newbox\myboxD
    268 
    269 \title{\texorpdfstring{Advanced Control-flow and Concurrency in \protect\CFA}{Advanced Control-flow in Cforall}}
     224\title{\texorpdfstring{Concurrency in \protect\CFA}{Concurrency in Cforall}}
    270225
    271226\author[1]{Thierry Delisle}
     
    277232\corres{*Peter A. Buhr, Cheriton School of Computer Science, University of Waterloo, 200 University Avenue West, Waterloo, ON, N2L 3G1, Canada. \email{pabuhr{\char`\@}uwaterloo.ca}}
    278233
    279 % \fundingInfo{Natural Sciences and Engineering Research Council of Canada}
     234\fundingInfo{Natural Sciences and Engineering Research Council of Canada}
    280235
    281236\abstract[Summary]{
    282 \CFA is a polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language.
    283 This paper discusses the design philosophy and implementation of its advanced control-flow and concurrent/parallel features, along with the supporting runtime written in \CFA.
    284 These features are created from scratch as ISO C has only low-level and/or unimplemented concurrency, so C programmers continue to rely on library features like pthreads.
    285 \CFA introduces modern language-level control-flow mechanisms, like generators, coroutines, user-level threading, and monitors for mutual exclusion and synchronization.
    286 % Library extension for executors, futures, and actors are built on these basic mechanisms.
    287 The runtime provides significant programmer simplification and safety by eliminating spurious wakeup and monitor barging.
    288 The runtime also ensures multiple monitors can be safely acquired \emph{simultaneously} (deadlock free), and this feature is fully integrated with all monitor synchronization mechanisms.
    289 All control-flow features integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers.
    290 Experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming languages.
     237\CFA is a modern, polymorphic, \emph{non-object-oriented} extension of the C programming language.
     238This paper discusses the design of the concurrency and parallelism features in \CFA, and the concurrent runtime-system.
     239These features are created from scratch as ISO C lacks concurrency, relying largely on the pthreads library.
     240Coroutines and lightweight (user) threads are introduced into the language.
     241In addition, monitors are added as a high-level mechanism for mutual exclusion and synchronization.
     242A unique contribution is allowing multiple monitors to be safely acquired simultaneously.
     243All features respect the expectations of C programmers, while being fully integrate with the \CFA polymorphic type-system and other language features.
     244Finally, experimental results are presented to compare the performance of the new features with similar mechanisms in other concurrent programming-languages.
    291245}%
    292246
    293 \keywords{generator, coroutine, concurrency, parallelism, thread, monitor, runtime, C, \CFA (Cforall)}
     247\keywords{concurrency, parallelism, coroutines, threads, monitors, runtime, C, Cforall}
    294248
    295249
     
    302256\section{Introduction}
    303257
    304 This paper discusses the design philosophy and implementation of advanced language-level control-flow and concurrent/parallel features in \CFA~\cite{Moss18,Cforall} and its runtime, which is written entirely in \CFA.
    305 \CFA is a modern, polymorphic, non-object-oriented\footnote{
    306 \CFA has features often associated with object-oriented programming languages, such as constructors, destructors, virtuals and simple inheritance.
    307 However, functions \emph{cannot} be nested in structures, so there is no lexical binding between a structure and set of functions (member/method) implemented by an implicit \lstinline@this@ (receiver) parameter.},
    308 backwards-compatible extension of the C programming language.
    309 In many ways, \CFA is to C as Scala~\cite{Scala} is to Java, providing a \emph{research vehicle} for new typing and control-flow capabilities on top of a highly popular programming language allowing immediate dissemination.
    310 Within the \CFA framework, new control-flow features are created from scratch because ISO \Celeven defines only a subset of the \CFA extensions, where the overlapping features are concurrency~\cite[\S~7.26]{C11}.
    311 However, \Celeven concurrency is largely wrappers for a subset of the pthreads library~\cite{Butenhof97,Pthreads}, and \Celeven and pthreads concurrency is simple, based on thread fork/join in a function and mutex/condition locks, which is low-level and error-prone;
    312 no high-level language concurrency features are defined.
    313 Interestingly, almost a decade after publication of the \Celeven standard, neither gcc-8, clang-9 nor msvc-19 (most recent versions) support the \Celeven include @threads.h@, indicating little interest in the C11 concurrency approach (possibly because the effort to add concurrency to \CC).
    314 Finally, while the \Celeven standard does not state a threading model, the historical association with pthreads suggests implementations would adopt kernel-level threading (1:1)~\cite{ThreadModel}.
    315 
    316 In contrast, there has been a renewed interest during the past decade in user-level (M:N, green) threading in old and new programming languages.
    317 As multi-core hardware became available in the 1980/90s, both user and kernel threading were examined.
    318 Kernel threading was chosen, largely because of its simplicity and fit with the simpler operating systems and hardware architectures at the time, which gave it a performance advantage~\cite{Drepper03}.
    319 Libraries like pthreads were developed for C, and the Solaris operating-system switched from user (JDK 1.1~\cite{JDK1.1}) to kernel threads.
    320 As a result, languages like Java, Scala, Objective-C~\cite{obj-c-book}, \CCeleven~\cite{C11}, and C\#~\cite{Csharp} adopt the 1:1 kernel-threading model, with a variety of presentation mechanisms.
    321 From 2000 onwards, languages like Go~\cite{Go}, Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, D~\cite{D}, and \uC~\cite{uC++,uC++book} have championed the M:N user-threading model, and many user-threading libraries have appeared~\cite{Qthreads,MPC,Marcel}, including putting green threads back into Java~\cite{Quasar}.
    322 The main argument for user-level threading is that it is lighter weight than kernel threading (locking and context switching do not cross the kernel boundary), so there is less restriction on programming styles that encourage large numbers of threads performing medium work units to facilitate load balancing by the runtime~\cite{Verch12}.
    323 As well, user-threading facilitates a simpler concurrency approach using thread objects that leverage sequential patterns versus events with call-backs~\cite{Adya02,vonBehren03}.
    324 Finally, performant user-threading implementations (both time and space) meet or exceed direct kernel-threading implementations, while achieving the programming advantages of high concurrency levels and safety.
    325 
    326 A further effort over the past two decades is the development of language memory models to deal with the conflict between language features and compiler/hardware optimizations, \ie some language features are unsafe in the presence of aggressive sequential optimizations~\cite{Buhr95a,Boehm05}.
    327 The consequence is that a language must provide sufficient tools to program around safety issues, as inline and library code is all sequential to the compiler.
    328 One solution is low-level qualifiers and functions (\eg @volatile@ and atomics) allowing \emph{programmers} to explicitly write safe (race-free~\cite{Boehm12}) programs.
    329 A safer solution is high-level language constructs so the \emph{compiler} knows the optimization boundaries, and hence, provides implicit safety.
    330 This problem is best known with respect to concurrency, but applies to other complex control-flow, like exceptions\footnote{
    331 \CFA exception handling will be presented in a separate paper.
    332 The key feature that dovetails with this paper is nonlocal exceptions allowing exceptions to be raised across stacks, with synchronous exceptions raised among coroutines and asynchronous exceptions raised among threads, similar to that in \uC~\cite[\S~5]{uC++}
    333 } and coroutines.
    334 Finally, language solutions allow matching constructs with language paradigm, \ie imperative and functional languages often have different presentations of the same concept to fit their programming model.
    335 
    336 Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety for performance when necessary.
    337 Two concurrency violations of this philosophy are \emph{spurious wakeup} (random wakeup~\cite[\S~8]{Buhr05a}) and \emph{barging}\footnote{
    338 The notion of competitive succession instead of direct handoff, \ie a lock owner releases the lock and an arriving thread acquires it ahead of preexisting waiter threads.
    339 } (signals-as-hints~\cite[\S~8]{Buhr05a}), where one is a consequence of the other, \ie once there is spurious wakeup, signals-as-hints follow.
    340 However, spurious wakeup is \emph{not} a foundational concurrency property~\cite[\S~8]{Buhr05a}, it is a performance design choice.
    341 Similarly, signals-as-hints are often a performance decision.
    342 We argue removing spurious wakeup and signals-as-hints make concurrent programming significantly safer because it removes local non-determinism and matches with programmer expectation.
    343 (Author experience teaching concurrency is that students are highly confused by these semantics.)
    344 Clawing back performance, when local non-determinism is unimportant, should be an option not the default.
    345 
    346 \begin{comment}
    347 Most augmented traditional (Fortran 18~\cite{Fortran18}, Cobol 14~\cite{Cobol14}, Ada 12~\cite{Ada12}, Java 11~\cite{Java11}) and new languages (Go~\cite{Go}, Rust~\cite{Rust}, and D~\cite{D}), except \CC, diverge from C with different syntax and semantics, only interoperate indirectly with C, and are not systems languages, for those with managed memory.
    348 As a result, there is a significant learning curve to move to these languages, and C legacy-code must be rewritten.
    349 While \CC, like \CFA, takes an evolutionary approach to extend C, \CC's constantly growing complex and interdependent features-set (\eg objects, inheritance, templates, etc.) mean idiomatic \CC code is difficult to use from C, and C programmers must expend significant effort learning \CC.
    350 Hence, rewriting and retraining costs for these languages, even \CC, are prohibitive for companies with a large C software-base.
    351 \CFA with its orthogonal feature-set, its high-performance runtime, and direct access to all existing C libraries circumvents these problems.
    352 \end{comment}
    353 
    354 \CFA embraces user-level threading, language extensions for advanced control-flow, and safety as the default.
    355 We present comparative examples so the reader can judge if the \CFA control-flow extensions are better and safer than those in other concurrent, imperative programming languages, and perform experiments to show the \CFA runtime is competitive with other similar mechanisms.
    356 The main contributions of this work are:
    357 \begin{itemize}[topsep=3pt,itemsep=1pt]
    358 \item
    359 language-level generators, coroutines and user-level threading, which respect the expectations of C programmers.
    360 \item
    361 monitor synchronization without barging, and the ability to safely acquiring multiple monitors \emph{simultaneously} (deadlock free), while seamlessly integrating these capabilities with all monitor synchronization mechanisms.
    362 \item
    363 providing statically type-safe interfaces that integrate with the \CFA polymorphic type-system and other language features.
    364 % \item
    365 % library extensions for executors, futures, and actors built on the basic mechanisms.
    366 \item
    367 a runtime system with no spurious wakeup.
    368 \item
    369 a dynamic partitioning mechanism to segregate the execution environment for specialized requirements.
    370 % \item
    371 % a non-blocking I/O library
    372 \item
    373 experimental results showing comparable performance of the new features with similar mechanisms in other programming languages.
    374 \end{itemize}
    375 
    376 Section~\ref{s:StatefulFunction} begins advanced control by introducing sequential functions that retain data and execution state between calls, which produces constructs @generator@ and @coroutine@.
    377 Section~\ref{s:Concurrency} begins concurrency, or how to create (fork) and destroy (join) a thread, which produces the @thread@ construct.
    378 Section~\ref{s:MutualExclusionSynchronization} discusses the two mechanisms to restricted nondeterminism when controlling shared access to resources (mutual exclusion) and timing relationships among threads (synchronization).
    379 Section~\ref{s:Monitor} shows how both mutual exclusion and synchronization are safely embedded in the @monitor@ and @thread@ constructs.
    380 Section~\ref{s:CFARuntimeStructure} describes the large-scale mechanism to structure (cluster) threads and virtual processors (kernel threads).
    381 Section~\ref{s:Performance} uses a series of microbenchmarks to compare \CFA threading with pthreads, Java OpenJDK-9, Go 1.12.6 and \uC 7.0.0.
    382 
    383 
    384 \section{Stateful Function}
    385 \label{s:StatefulFunction}
    386 
    387 The stateful function is an old idea~\cite{Conway63,Marlin80} that is new again~\cite{C++20Coroutine19}, where execution is temporarily suspended and later resumed, \eg plugin, device driver, finite-state machine.
    388 Hence, a stateful function may not end when it returns to its caller, allowing it to be restarted with the data and execution location present at the point of suspension.
    389 This capability is accomplished by retaining a data/execution \emph{closure} between invocations.
    390 If the closure is fixed size, we call it a \emph{generator} (or \emph{stackless}), and its control flow is restricted, \eg suspending outside the generator is prohibited.
    391 If the closure is variable size, we call it a \emph{coroutine} (or \emph{stackful}), and as the names implies, often implemented with a separate stack with no programming restrictions.
    392 Hence, refactoring a stackless coroutine may require changing it to stackful.
    393 A foundational property of all \emph{stateful functions} is that resume/suspend \emph{do not} cause incremental stack growth, \ie resume/suspend operations are remembered through the closure not the stack.
    394 As well, activating a stateful function is \emph{asymmetric} or \emph{symmetric}, identified by resume/suspend (no cycles) and resume/resume (cycles).
    395 A fixed closure activated by modified call/return is faster than a variable closure activated by context switching.
    396 Additionally, any storage management for the closure (especially in unmanaged languages, \ie no garbage collection) must also be factored into design and performance.
    397 Therefore, selecting between stackless and stackful semantics is a tradeoff between programming requirements and performance, where stackless is faster and stackful is more general.
    398 Note, creation cost is amortized across usage, so activation cost is usually the dominant factor.
     258This paper provides a minimal concurrency \newterm{Application Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
     259While the simplest concurrency system is a thread and a lock, this low-level approach is hard to master.
     260An easier approach for programmers is to support higher-level constructs as the basis of concurrency.
     261Indeed, for highly productive concurrent programming, high-level approaches are much more popular~\cite{Hochstein05}.
     262Examples of high-level approaches are task (work) based~\cite{TBB}, implicit threading~\cite{OpenMP}, monitors~\cite{Java}, channels~\cite{CSP,Go}, and message passing~\cite{Erlang,MPI}.
     263
     264The following terminology is used.
     265A \newterm{thread} is a fundamental unit of execution that runs a sequence of code and requires a stack to maintain state.
     266Multiple simultaneous threads give rise to \newterm{concurrency}, which requires locking to ensure safe communication and access to shared data.
     267% Correspondingly, concurrency is defined as the concepts and challenges that occur when multiple independent (sharing memory, timing dependencies, \etc) concurrent threads are introduced.
     268\newterm{Locking}, and by extension \newterm{locks}, are defined as a mechanism to prevent progress of threads to provide safety.
     269\newterm{Parallelism} is running multiple threads simultaneously.
     270Parallelism implies \emph{actual} simultaneous execution, where concurrency only requires \emph{apparent} simultaneous execution.
     271As such, parallelism only affects performance, which is observed through differences in space and/or time at runtime.
     272
     273Hence, there are two problems to be solved: concurrency and parallelism.
     274While these two concepts are often combined, they are distinct, requiring different tools~\cite[\S~2]{Buhr05a}.
     275Concurrency tools handle synchronization and mutual exclusion, while parallelism tools handle performance, cost and resource utilization.
     276
     277The proposed concurrency API is implemented in a dialect of C, called \CFA.
     278The paper discusses how the language features are added to the \CFA translator with respect to parsing, semantic, and type checking, and the corresponding high-performance runtime-library to implement the concurrency features.
     279
     280
     281\section{\CFA Overview}
     282
     283The following is a quick introduction to the \CFA language, specifically tailored to the features needed to support concurrency.
     284Extended versions and explanation of the following code examples are available at the \CFA website~\cite{Cforall} or in Moss~\etal~\cite{Moss18}.
     285
     286\CFA is an extension of ISO-C, and hence, supports all C paradigms.
     287%It is a non-object-oriented system-language, meaning most of the major abstractions have either no runtime overhead or can be opted out easily.
     288Like C, the basics of \CFA revolve around structures and routines.
     289Virtually all of the code generated by the \CFA translator respects C memory layouts and calling conventions.
     290While \CFA is not an object-oriented language, lacking the concept of a receiver (\eg @this@) and nominal inheritance-relationships, C does have a notion of objects: ``region of data storage in the execution environment, the contents of which can represent values''~\cite[3.15]{C11}.
     291While some \CFA features are common in object-oriented programming-languages, they are an independent capability allowing \CFA to adopt them while retaining a procedural paradigm.
     292
     293
     294\subsection{References}
     295
     296\CFA provides multi-level rebindable references, as an alternative to pointers, which significantly reduces syntactic noise.
     297\begin{cfa}
     298int x = 1, y = 2, z = 3;
     299int * p1 = &x, ** p2 = &p1,  *** p3 = &p2,      $\C{// pointers to x}$
     300        `&` r1 = x,  `&&` r2 = r1,  `&&&` r3 = r2;      $\C{// references to x}$
     301int * p4 = &z, `&` r4 = z;
     302
     303*p1 = 3; **p2 = 3; ***p3 = 3;       // change x
     304r1 =  3;     r2 = 3;      r3 = 3;        // change x: implicit dereferences *r1, **r2, ***r3
     305**p3 = &y; *p3 = &p4;                // change p1, p2
     306`&`r3 = &y; `&&`r3 = &`&`r4;             // change r1, r2: cancel implicit dereferences (&*)**r3, (&(&*)*)*r3, &(&*)r4
     307\end{cfa}
     308A reference is a handle to an object, like a pointer, but is automatically dereferenced by the specified number of levels.
     309Referencing (address-of @&@) a reference variable cancels one of the implicit dereferences, until there are no more implicit references, after which normal expression behaviour applies.
     310
     311
     312\subsection{\texorpdfstring{\protect\lstinline{with} Statement}{with Statement}}
     313\label{s:WithStatement}
     314
     315Heterogeneous data is aggregated into a structure/union.
     316To reduce syntactic noise, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate field-qualification by opening a scope containing the field identifiers.
     317\begin{cquote}
     318\vspace*{-\baselineskip}%???
     319\lstDeleteShortInline@%
     320\begin{cfa}
     321struct S { char c; int i; double d; };
     322struct T { double m, n; };
     323// multiple aggregate parameters
     324\end{cfa}
     325\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
     326\begin{cfa}
     327void f( S & s, T & t ) {
     328        `s.`c; `s.`i; `s.`d;
     329        `t.`m; `t.`n;
     330}
     331\end{cfa}
     332&
     333\begin{cfa}
     334void f( S & s, T & t ) `with ( s, t )` {
     335        c; i; d;                // no qualification
     336        m; n;
     337}
     338\end{cfa}
     339\end{tabular}
     340\lstMakeShortInline@%
     341\end{cquote}
     342Object-oriented programming languages only provide implicit qualification for the receiver.
     343
     344In detail, the @with@ statement has the form:
     345\begin{cfa}
     346$\emph{with-statement}$:
     347        'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$
     348\end{cfa}
     349and may appear as the body of a routine or nested within a routine body.
     350Each expression in the expression-list provides a type and object.
     351The type must be an aggregate type.
     352(Enumerations are already opened.)
     353The object is the implicit qualifier for the open structure-fields.
     354All expressions in the expression list are open in parallel within the compound statement, which is different from Pascal, which nests the openings from left to right.
     355
     356
     357\subsection{Overloading}
     358
     359\CFA maximizes the ability to reuse names via overloading to aggressively address the naming problem.
     360Both variables and routines may be overloaded, where selection is based on types, and number of returns (as in Ada~\cite{Ada}) and arguments.
     361\begin{cquote}
     362\vspace*{-\baselineskip}%???
     363\lstDeleteShortInline@%
     364\begin{cfa}
     365// selection based on type
     366\end{cfa}
     367\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
     368\begin{cfa}
     369const short int `MIN` = -32768;
     370const int `MIN` = -2147483648;
     371const long int `MIN` = -9223372036854775808L;
     372\end{cfa}
     373&
     374\begin{cfa}
     375short int si = `MIN`;
     376int i = `MIN`;
     377long int li = `MIN`;
     378\end{cfa}
     379\end{tabular}
     380\begin{cfa}
     381// selection based on type and number of parameters
     382\end{cfa}
     383\begin{tabular}{@{}l@{\hspace{2.7\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
     384\begin{cfa}
     385void `f`( void );
     386void `f`( char );
     387void `f`( int, double );
     388\end{cfa}
     389&
     390\begin{cfa}
     391`f`();
     392`f`( 'a' );
     393`f`( 3, 5.2 );
     394\end{cfa}
     395\end{tabular}
     396\begin{cfa}
     397// selection based on type and number of returns
     398\end{cfa}
     399\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
     400\begin{cfa}
     401char `f`( int );
     402double `f`( int );
     403[char, double] `f`( int );
     404\end{cfa}
     405&
     406\begin{cfa}
     407char c = `f`( 3 );
     408double d = `f`( 3 );
     409[d, c] = `f`( 3 );
     410\end{cfa}
     411\end{tabular}
     412\lstMakeShortInline@%
     413\end{cquote}
     414Overloading is important for \CFA concurrency since the runtime system relies on creating different types to represent concurrency objects.
     415Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions to prevent name clashes.
     416As seen in Section~\ref{basics}, routine @main@ is heavily overloaded.
     417
     418Variable overloading is useful in the parallel semantics of the @with@ statement for fields with the same name:
     419\begin{cfa}
     420struct S { int `i`; int j; double m; } s;
     421struct T { int `i`; int k; int m; } t;
     422with ( s, t ) {
     423        j + k;                                                                  $\C{// unambiguous, s.j + t.k}$
     424        m = 5.0;                                                                $\C{// unambiguous, s.m = 5.0}$
     425        m = 1;                                                                  $\C{// unambiguous, t.m = 1}$
     426        int a = m;                                                              $\C{// unambiguous, a = t.m }$
     427        double b = m;                                                   $\C{// unambiguous, b = s.m}$
     428        int c = `s.i` + `t.i`;                                  $\C{// unambiguous, qualification}$
     429        (double)m;                                                              $\C{// unambiguous, cast s.m}$
     430}
     431\end{cfa}
     432For parallel semantics, both @s.i@ and @t.i@ are visible the same type, so only @i@ is ambiguous without qualification.
     433
     434
     435\subsection{Operators}
     436
     437Overloading also extends to operators.
     438Operator-overloading syntax creates a routine name with an operator symbol and question marks for the operands:
     439\begin{cquote}
     440\lstDeleteShortInline@%
     441\begin{tabular}{@{}ll@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
     442\begin{cfa}
     443int ++? (int op);
     444int ?++ (int op);
     445int `?+?` (int op1, int op2);
     446int ?<=?(int op1, int op2);
     447int ?=? (int & op1, int op2);
     448int ?+=?(int & op1, int op2);
     449\end{cfa}
     450&
     451\begin{cfa}
     452// unary prefix increment
     453// unary postfix increment
     454// binary plus
     455// binary less than
     456// binary assignment
     457// binary plus-assignment
     458\end{cfa}
     459&
     460\begin{cfa}
     461struct S { int i, j; };
     462S `?+?`( S op1, S op2) { // add two structures
     463        return (S){op1.i + op2.i, op1.j + op2.j};
     464}
     465S s1 = {1, 2}, s2 = {2, 3}, s3;
     466s3 = s1 `+` s2;         // compute sum: s3 == {2, 5}
     467\end{cfa}
     468\end{tabular}
     469\lstMakeShortInline@%
     470\end{cquote}
     471While concurrency does not use operator overloading directly, it provides an introduction for the syntax of constructors.
     472
     473
     474\subsection{Parametric Polymorphism}
     475\label{s:ParametricPolymorphism}
     476
     477The signature feature of \CFA is parametric-polymorphic routines~\cite{} with routines generalized using a @forall@ clause (giving the language its name), which allow separately compiled routines to support generic usage over multiple types.
     478For example, the following sum routine works for any type that supports construction from 0 and addition \commenttd{constructors have not been introduced yet.}:
     479\begin{cfa}
     480forall( otype T | { void `?{}`( T *, zero_t ); T `?+?`( T, T ); } ) // constraint type, 0 and +
     481T sum( T a[$\,$], size_t size ) {
     482        `T` total = { `0` };                                    $\C{// initialize by 0 constructor}$
     483        for ( size_t i = 0; i < size; i += 1 )
     484                total = total `+` a[i];                         $\C{// select appropriate +}$
     485        return total;
     486}
     487S sa[5];
     488int i = sum( sa, 5 );                                           $\C{// use S's 0 construction and +}$
     489\end{cfa}
     490
     491\CFA provides \newterm{traits} to name a group of type assertions, where the trait name allows specifying the same set of assertions in multiple locations, preventing repetition mistakes at each routine declaration:
     492\begin{cfa}
     493trait `sumable`( otype T ) {
     494        void `?{}`( T &, zero_t );                              $\C{// 0 literal constructor}$
     495        T `?+?`( T, T );                                                $\C{// assortment of additions}$
     496        T ?+=?( T &, T );
     497        T ++?( T & );
     498        T ?++( T & );
     499};
     500forall( otype T `| sumable( T )` )                      $\C{// use trait}$
     501T sum( T a[$\,$], size_t size );
     502\end{cfa}
     503
     504Assertions can be @otype@ or @dtype@.
     505@otype@ refers to a ``complete'' object, \ie an object has a size, default constructor, copy constructor, destructor and an assignment operator.
     506@dtype@ only guarantees an object has a size and alignment.
     507
     508Using the return type for discrimination, it is possible to write a type-safe @alloc@ based on the C @malloc@:
     509\begin{cfa}
     510forall( dtype T | sized(T) ) T * alloc( void ) { return (T *)malloc( sizeof(T) ); }
     511int * ip = alloc();                                                     $\C{// select type and size from left-hand side}$
     512double * dp = alloc();
     513struct S {...} * sp = alloc();
     514\end{cfa}
     515where the return type supplies the type/size of the allocation, which is impossible in most type systems.
     516
     517
     518\subsection{Constructors / Destructors}
     519
     520Object lifetime is a challenge in non-managed programming languages.
     521\CFA responds with \CC-like constructors and destructors:
     522\begin{cfa}
     523struct VLA { int len, * data; };                        $\C{// variable length array of integers}$
     524void ?{}( VLA & vla ) with ( vla ) { len = 10;  data = alloc( len ); }  $\C{// default constructor}$
     525void ?{}( VLA & vla, int size, char fill ) with ( vla ) { len = size;  data = alloc( len, fill ); } // initialization
     526void ?{}( VLA & vla, VLA other ) { vla.len = other.len;  vla.data = other.data; } $\C{// copy, shallow}$
     527void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$
     528{
     529        VLA  x,            y = { 20, 0x01 },     z = y; $\C{// z points to y}$
     530        //    x{};         y{ 20, 0x01 };          z{ z, y };
     531        ^x{};                                                                   $\C{// deallocate x}$
     532        x{};                                                                    $\C{// reallocate x}$
     533        z{ 5, 0xff };                                                   $\C{// reallocate z, not pointing to y}$
     534        ^y{};                                                                   $\C{// deallocate y}$
     535        y{ x };                                                                 $\C{// reallocate y, points to x}$
     536        x{};                                                                    $\C{// reallocate x, not pointing to y}$
     537        //  ^z{};  ^y{};  ^x{};
     538}
     539\end{cfa}
     540Like \CC, construction is implicit on allocation (stack/heap) and destruction is implicit on deallocation.
     541The object and all their fields are constructed/destructed.
     542\CFA also provides @new@ and @delete@, which behave like @malloc@ and @free@, in addition to constructing and destructing objects:
     543\begin{cfa}
     544{       struct S s = {10};                                              $\C{// allocation, call constructor}$
     545        ...
     546}                                                                                       $\C{// deallocation, call destructor}$
     547struct S * s = new();                                           $\C{// allocation, call constructor}$
     548...
     549delete( s );                                                            $\C{// deallocation, call destructor}$
     550\end{cfa}
     551\CFA concurrency uses object lifetime as a means of synchronization and/or mutual exclusion.
     552
     553
     554\section{Concurrency Basics}\label{basics}
     555
     556At its core, concurrency is based on multiple call-stacks and scheduling threads executing on these stacks.
     557Multiple call stacks (or contexts) and a single thread of execution, called \newterm{coroutining}~\cite{Conway63,Marlin80}, does \emph{not} imply concurrency~\cite[\S~2]{Buhr05a}.
     558In coroutining, the single thread is self-scheduling across the stacks, so execution is deterministic, \ie given fixed inputs, the execution path to the outputs is fixed and predictable.
     559A \newterm{stackless} coroutine executes on the caller's stack~\cite{Python} but this approach is restrictive, \eg preventing modularization and supporting only iterator/generator-style programming;
     560a \newterm{stackfull} coroutine executes on its own stack, allowing full generality.
     561Only stackfull coroutines are a stepping-stone to concurrency.
     562
     563The transition to concurrency, even for execution with a single thread and multiple stacks, occurs when coroutines also context switch to a scheduling oracle, introducing non-determinism from the coroutine perspective~\cite[\S~3]{Buhr05a}.
     564Therefore, a minimal concurrency system is possible using coroutines (see Section \ref{coroutine}) in conjunction with a scheduler to decide where to context switch next.
     565The resulting execution system now follows a cooperative threading-model, called \newterm{non-preemptive scheduling}.
     566
     567Because the scheduler is special, it can either be a stackless or stackfull coroutine. \commenttd{I dislike this sentence, it seems imply 1-step vs 2-step but also seems to say that some kind of coroutine is required, which is not the case.}
     568For stackless, the scheduler performs scheduling on the stack of the current coroutine and switches directly to the next coroutine, so there is one context switch.
     569For stackfull, the current coroutine switches to the scheduler, which performs scheduling, and it then switches to the next coroutine, so there are two context switches.
     570A stackfull scheduler is often used for simplicity and security, even through there is a slightly higher runtime-cost. \commenttd{I'm not a fan of the fact that we don't quantify this but yet imply it is negligeable.}
     571
     572Regardless of the approach used, a subset of concurrency related challenges start to appear.
     573For the complete set of concurrency challenges to occur, the missing feature is \newterm{preemption}, where context switching occurs randomly between any two instructions, often based on a timer interrupt, called \newterm{preemptive scheduling}.
     574While a scheduler introduces uncertainty in the order of execution, preemption introduces uncertainty where context switches occur.
     575Interestingly, uncertainty is necessary for the runtime (operating) system to give the illusion of parallelism on a single processor and increase performance on multiple processors.
     576The reason is that only the runtime has complete knowledge about resources and how to best utilized them.
     577However, the introduction of unrestricted non-determinism results in the need for \newterm{mutual exclusion} and \newterm{synchronization} to restrict non-determinism for correctness;
     578otherwise, it is impossible to write meaningful programs.
     579Optimal performance in concurrent applications is often obtained by having as much non-determinism as correctness allows.
     580
     581
     582\subsection{\protect\CFA's Thread Building Blocks}
     583
     584An important missing feature in C is threading\footnote{While the C11 standard defines a ``threads.h'' header, it is minimal and defined as optional.
     585As such, library support for threading is far from widespread.
     586At the time of writing the paper, neither \protect\lstinline|gcc| nor \protect\lstinline|clang| support ``threads.h'' in their standard libraries.}.
     587In modern programming languages, a lack of threading is unacceptable~\cite{Sutter05, Sutter05b}, and therefore existing and new programming languages must have tools for writing efficient concurrent programs to take advantage of parallelism.
     588As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers familiar with imperative languages.
     589Furthermore, because C is a system-level language, programmers expect to choose precisely which features they need and which cost they are willing to pay.
     590Hence, concurrent programs should be written using high-level mechanisms, and only step down to lower-level mechanisms when performance bottlenecks are encountered.
     591
     592
     593\subsection{Coroutines: A Stepping Stone}\label{coroutine}
     594
     595While the focus of this discussion is concurrency and parallelism, it is important to address coroutines, which are a significant building block of a concurrency system.
     596Coroutines are generalized routines allowing execution to be temporarily suspend and later resumed.
     597Hence, unlike a normal routine, a coroutine may not terminate when it returns to its caller, allowing it to be restarted with the values and execution location present at the point of suspension.
     598This capability is accomplish via the coroutine's stack, where suspend/resume context switch among stacks.
     599Because threading design-challenges are present in coroutines, their design effort is relevant, and this effort can be easily exposed to programmers giving them a useful new programming paradigm because a coroutine handles the class of problems that need to retain state between calls, \eg plugins, device drivers, and finite-state machines.
     600Therefore, the core \CFA coroutine-API for has two fundamental features: independent call-stacks and @suspend@/@resume@ operations.
     601
     602For example, a problem made easier with coroutines is unbounded generators, \eg generating an infinite sequence of Fibonacci numbers, where Figure~\ref{f:C-fibonacci} shows conventional approaches for writing a Fibonacci generator in C.
     603\begin{displaymath}
     604\mathsf{fib}(n) = \left \{
     605\begin{array}{ll}
     6060                                       & n = 0         \\
     6071                                       & n = 1         \\
     608\mathsf{fib}(n-1) + \mathsf{fib}(n-2)   & n \ge 2       \\
     609\end{array}
     610\right.
     611\end{displaymath}
     612Figure~\ref{f:GlobalVariables} illustrates the following problems:
     613unique unencapsulated global variables necessary to retain state between calls;
     614only one Fibonacci generator;
     615execution state must be explicitly retained via explicit state variables.
     616Figure~\ref{f:ExternalState} addresses these issues:
     617unencapsulated program global variables become encapsulated structure variables;
     618unique global variables are replaced by multiple Fibonacci objects;
     619explicit execution state is removed by precomputing the first two Fibonacci numbers and returning $\mathsf{fib}(n-2)$.
    399620
    400621\begin{figure}
    401622\centering
     623\newbox\myboxA
    402624\begin{lrbox}{\myboxA}
    403625\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    404 typedef struct {
    405         int fn1, fn;
    406 } Fib;
    407 #define FibCtor { 1, 0 }
    408 int fib( Fib * f ) {
    409 
    410 
    411 
    412         int fn = f->fn; f->fn = f->fn1;
    413                 f->fn1 = f->fn + fn;
     626`int f1, f2, state = 1;`   // single global variables
     627int fib() {
     628        int fn;
     629        `switch ( state )` {  // explicit execution state
     630          case 1: fn = 0;  f1 = fn;  state = 2;  break;
     631          case 2: fn = 1;  f2 = f1;  f1 = fn;  state = 3;  break;
     632          case 3: fn = f1 + f2;  f2 = f1;  f1 = fn;  break;
     633        }
    414634        return fn;
    415 
    416635}
    417636int main() {
    418         Fib f1 = FibCtor, f2 = FibCtor;
    419         for ( int i = 0; i < 10; i += 1 )
    420                 printf( "%d %d\n",
    421                            fib( &f1 ), fib( &f2 ) );
     637
     638        for ( int i = 0; i < 10; i += 1 ) {
     639                printf( "%d\n", fib() );
     640        }
    422641}
    423642\end{cfa}
    424643\end{lrbox}
    425644
     645\newbox\myboxB
    426646\begin{lrbox}{\myboxB}
    427647\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    428 `generator` Fib {
    429         int fn1, fn;
    430 };
    431 
    432 void `main(Fib & fib)` with(fib) {
    433 
    434         [fn1, fn] = [1, 0];
    435         for () {
    436                 `suspend;`
    437                 [fn1, fn] = [fn, fn + fn1];
    438 
     648#define FIB_INIT `{ 0, 1 }`
     649typedef struct { int f2, f1; } Fib;
     650int fib( Fib * f ) {
     651
     652        int ret = f->f2;
     653        int fn = f->f1 + f->f2;
     654        f->f2 = f->f1; f->f1 = fn;
     655
     656        return ret;
     657}
     658int main() {
     659        Fib f1 = FIB_INIT, f2 = FIB_INIT;
     660        for ( int i = 0; i < 10; i += 1 ) {
     661                printf( "%d %d\n", fib( &f1 ), fib( &f2 ) );
    439662        }
     663}
     664\end{cfa}
     665\end{lrbox}
     666
     667\subfloat[3 States: global variables]{\label{f:GlobalVariables}\usebox\myboxA}
     668\qquad
     669\subfloat[1 State: external variables]{\label{f:ExternalState}\usebox\myboxB}
     670\caption{C Fibonacci Implementations}
     671\label{f:C-fibonacci}
     672
     673\bigskip
     674
     675\newbox\myboxA
     676\begin{lrbox}{\myboxA}
     677\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     678`coroutine` Fib { int fn; };
     679void main( Fib & fib ) with( fib ) {
     680        int f1, f2;
     681        fn = 0;  f1 = fn;  `suspend()`;
     682        fn = 1;  f2 = f1;  f1 = fn;  `suspend()`;
     683        for ( ;; ) {
     684                fn = f1 + f2;  f2 = f1;  f1 = fn;  `suspend()`;
     685        }
     686}
     687int next( Fib & fib ) with( fib ) {
     688        `resume( fib );`
     689        return fn;
    440690}
    441691int main() {
    442692        Fib f1, f2;
    443         for ( 10 )
    444                 sout | `resume( f1 )`.fn
    445                          | `resume( f2 )`.fn;
     693        for ( int i = 1; i <= 10; i += 1 ) {
     694                sout | next( f1 ) | next( f2 ) | endl;
     695        }
    446696}
    447697\end{cfa}
    448698\end{lrbox}
    449 
    450 \begin{lrbox}{\myboxC}
    451 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    452 typedef struct {
    453         int fn1, fn;  void * `next`;
    454 } Fib;
    455 #define FibCtor { 1, 0, NULL }
    456 Fib * comain( Fib * f ) {
    457         if ( f->next ) goto *f->next;
    458         f->next = &&s1;
    459         for ( ;; ) {
    460                 return f;
    461           s1:; int fn = f->fn + f->fn1;
    462                         f->fn1 = f->fn; f->fn = fn;
    463         }
    464 }
    465 int main() {
    466         Fib f1 = FibCtor, f2 = FibCtor;
    467         for ( int i = 0; i < 10; i += 1 )
    468                 printf("%d %d\n",comain(&f1)->fn,
    469                                  comain(&f2)->fn);
    470 }
    471 \end{cfa}
    472 \end{lrbox}
    473 
    474 \subfloat[C asymmetric generator]{\label{f:CFibonacci}\usebox\myboxA}
    475 \hspace{3pt}
    476 \vrule
    477 \hspace{3pt}
    478 \subfloat[\CFA asymmetric generator]{\label{f:CFAFibonacciGen}\usebox\myboxB}
    479 \hspace{3pt}
    480 \vrule
    481 \hspace{3pt}
    482 \subfloat[C generator implementation]{\label{f:CFibonacciSim}\usebox\myboxC}
    483 \caption{Fibonacci (output) asymmetric generator}
    484 \label{f:FibonacciAsymmetricGenerator}
    485 
    486 \bigskip
    487 
    488 \begin{lrbox}{\myboxA}
    489 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    490 `generator Fmt` {
    491         char ch;
    492         int g, b;
    493 };
    494 void ?{}( Fmt & fmt ) { `resume(fmt);` } // constructor
    495 void ^?{}( Fmt & f ) with(f) { $\C[1.75in]{// destructor}$
    496         if ( g != 0 || b != 0 ) sout | nl; }
    497 void `main( Fmt & f )` with(f) {
    498         for () { $\C{// until destructor call}$
    499                 for ( ; g < 5; g += 1 ) { $\C{// groups}$
    500                         for ( ; b < 4; b += 1 ) { $\C{// blocks}$
    501                                 `suspend;` $\C{// wait for character}$
    502                                 while ( ch == '\n' ) `suspend;` // ignore
    503                                 sout | ch;                                              // newline
    504                         } sout | " ";  // block spacer
    505                 } sout | nl; // group newline
    506         }
    507 }
    508 int main() {
    509         Fmt fmt; $\C{// fmt constructor called}$
    510         for () {
    511                 sin | fmt.ch; $\C{// read into generator}$
    512           if ( eof( sin ) ) break;
    513                 `resume( fmt );`
    514         }
    515 
    516 } $\C{// fmt destructor called}\CRT$
    517 \end{cfa}
    518 \end{lrbox}
    519 
     699\newbox\myboxB
    520700\begin{lrbox}{\myboxB}
    521701\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    522 typedef struct {
    523         void * next;
    524         char ch;
    525         int g, b;
    526 } Fmt;
    527 void comain( Fmt * f ) {
    528         if ( f->next ) goto *f->next;
    529         f->next = &&s1;
     702`coroutine` Fib { int ret; };
     703void main( Fib & f ) with( fib ) {
     704        int fn, f1 = 1, f2 = 0;
    530705        for ( ;; ) {
    531                 for ( f->g = 0; f->g < 5; f->g += 1 ) {
    532                         for ( f->b = 0; f->b < 4; f->b += 1 ) {
    533                                 return;
    534                           s1:;  while ( f->ch == '\n' ) return;
    535                                 printf( "%c", f->ch );
    536                         } printf( " " );
    537                 } printf( "\n" );
     706                ret = f2;
     707
     708                fn = f1 + f2;  f2 = f1;  f1 = fn; `suspend();`
    538709        }
    539710}
    540 int main() {
    541         Fmt fmt = { NULL };  comain( &fmt ); // prime
    542         for ( ;; ) {
    543                 scanf( "%c", &fmt.ch );
    544           if ( feof( stdin ) ) break;
    545                 comain( &fmt );
    546         }
    547         if ( fmt.g != 0 || fmt.b != 0 ) printf( "\n" );
    548 }
     711int next( Fib & fib ) with( fib ) {
     712        `resume( fib );`
     713        return ret;
     714}
     715
     716
     717
     718
     719
     720
    549721\end{cfa}
    550722\end{lrbox}
    551 
    552 \subfloat[\CFA asymmetric generator]{\label{f:CFAFormatGen}\usebox\myboxA}
    553 \hspace{3pt}
    554 \vrule
    555 \hspace{3pt}
    556 \subfloat[C generator simulation]{\label{f:CFormatSim}\usebox\myboxB}
    557 \hspace{3pt}
    558 \caption{Formatter (input) asymmetric generator}
    559 \label{f:FormatterAsymmetricGenerator}
     723\subfloat[3 States, internal variables]{\label{f:Coroutine3States}\usebox\myboxA}
     724\qquad\qquad
     725\subfloat[1 State, internal variables]{\label{f:Coroutine1State}\usebox\myboxB}
     726\caption{\CFA Coroutine Fibonacci Implementations}
     727\label{f:fibonacci-cfa}
    560728\end{figure}
    561729
    562 Stateful functions appear as generators, coroutines, and threads, where presentations are based on function objects or pointers~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
    563 For example, Python presents generators as a function object:
    564 \begin{python}
    565 def Gen():
    566         ... `yield val` ...
    567 gen = Gen()
    568 for i in range( 10 ):
    569         print( next( gen ) )
    570 \end{python}
    571 Boost presents coroutines in terms of four functor object-types:
    572 \begin{cfa}
    573 asymmetric_coroutine<>::pull_type
    574 asymmetric_coroutine<>::push_type
    575 symmetric_coroutine<>::call_type
    576 symmetric_coroutine<>::yield_type
    577 \end{cfa}
    578 and many languages present threading using function pointers, @pthreads@~\cite{Butenhof97}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}, \eg pthreads:
    579 \begin{cfa}
    580 void * rtn( void * arg ) { ... }
    581 int i = 3, rc;
    582 pthread_t t; $\C{// thread id}$
    583 `rc = pthread_create( &t, rtn, (void *)i );` $\C{// create and initialized task, type-unsafe input parameter}$
    584 \end{cfa}
    585 % void mycor( pthread_t cid, void * arg ) {
    586 %       int * value = (int *)arg;                               $\C{// type unsafe, pointer-size only}$
    587 %       // thread body
    588 % }
    589 % int main() {
    590 %       int input = 0, output;
    591 %       coroutine_t cid = coroutine_create( &mycor, (void *)&input ); $\C{// type unsafe, pointer-size only}$
    592 %       coroutine_resume( cid, (void *)input, (void **)&output ); $\C{// type unsafe, pointer-size only}$
    593 % }
    594 \CFA's preferred presentation model for generators/coroutines/threads is a hybrid of objects and functions, with an object-oriented flavour.
    595 Essentially, the generator/coroutine/thread function is semantically coupled with a generator/coroutine/thread custom type.
    596 The custom type solves several issues, while accessing the underlying mechanisms used by the custom types is still allowed.
    597 
    598 
    599 \subsection{Generator}
    600 
    601 Stackless generators have the potential to be very small and fast, \ie as small and fast as function call/return for both creation and execution.
    602 The \CFA goal is to achieve this performance target, possibly at the cost of some semantic complexity.
    603 A series of different kinds of generators and their implementation demonstrate how this goal is accomplished.
    604 
    605 Figure~\ref{f:FibonacciAsymmetricGenerator} shows an unbounded asymmetric generator for an infinite sequence of Fibonacci numbers written in C and \CFA, with a simple C implementation for the \CFA version.
    606 This generator is an \emph{output generator}, producing a new result on each resumption.
    607 To compute Fibonacci, the previous two values in the sequence are retained to generate the next value, \ie @fn1@ and @fn@, plus the execution location where control restarts when the generator is resumed, \ie top or middle.
    608 An additional requirement is the ability to create an arbitrary number of generators (of any kind), \ie retaining one state in global variables is insufficient;
    609 hence, state is retained in a closure between calls.
    610 Figure~\ref{f:CFibonacci} shows the C approach of manually creating the closure in structure @Fib@, and multiple instances of this closure provide multiple Fibonacci generators.
    611 The C version only has the middle execution state because the top execution state is declaration initialization.
    612 Figure~\ref{f:CFAFibonacciGen} shows the \CFA approach, which also has a manual closure, but replaces the structure with a custom \CFA @generator@ type.
    613 This generator type is then connected to a function that \emph{must be named \lstinline|main|},\footnote{
    614 The name \lstinline|main| has special meaning in C, specifically the function where a program starts execution.
    615 Hence, overloading this name for other starting points (generator/coroutine/thread) is a logical extension.}
    616 called a \emph{generator main},which takes as its only parameter a reference to the generator type.
    617 The generator main contains @suspend@ statements that suspend execution without ending the generator versus @return@.
    618 For the Fibonacci generator-main,\footnote{
    619 The \CFA \lstinline|with| opens an aggregate scope making its fields directly accessible, like Pascal \lstinline|with|, but using parallel semantics.
    620 Multiple aggregates may be opened.}
    621 the top initialization state appears at the start and the middle execution state is denoted by statement @suspend@.
    622 Any local variables in @main@ \emph{are not retained} between calls;
    623 hence local variables are only for temporary computations \emph{between} suspends.
    624 All retained state \emph{must} appear in the generator's type.
    625 As well, generator code containing a @suspend@ cannot be refactored into a helper function called by the generator, because @suspend@ is implemented via @return@, so a return from the helper function goes back to the current generator not the resumer.
    626 The generator is started by calling function @resume@ with a generator instance, which begins execution at the top of the generator main, and subsequent @resume@ calls restart the generator at its point of last suspension.
    627 Resuming an ended (returned) generator is undefined.
    628 Function @resume@ returns its argument generator so it can be cascaded in an expression, in this case to print the next Fibonacci value @fn@ computed in the generator instance.
    629 Figure~\ref{f:CFibonacciSim} shows the C implementation of the \CFA generator only needs one additional field, @next@, to handle retention of execution state.
    630 The computed @goto@ at the start of the generator main, which branches after the previous suspend, adds very little cost to the resume call.
    631 Finally, an explicit generator type provides both design and performance benefits, such as multiple type-safe interface functions taking and returning arbitrary types.\footnote{
    632 The \CFA operator syntax uses \lstinline|?| to denote operands, which allows precise definitions for pre, post, and infix operators, \eg \lstinline|++?|, \lstinline|?++|, and \lstinline|?+?|, in addition \lstinline|?\{\}| denotes a constructor, as in \lstinline|foo `f` = `\{`...`\}`|, \lstinline|^?\{\}| denotes a destructor, and \lstinline|?()| is \CC function call \lstinline|operator()|.
    633 }%
    634 \begin{cfa}
    635 int ?()( Fib & fib ) { return `resume( fib )`.fn; } $\C[3.9in]{// function-call interface}$
    636 int ?()( Fib & fib, int N ) { for ( N - 1 ) `fib()`; return `fib()`; } $\C{// use function-call interface to skip N values}$
    637 double ?()( Fib & fib ) { return (int)`fib()` / 3.14159; } $\C{// different return type, cast prevents recursive call}\CRT$
    638 sout | (int)f1() | (double)f1() | f2( 2 ); // alternative interface, cast selects call based on return type, step 2 values
    639 \end{cfa}
    640 Now, the generator can be a separately compiled opaque-type only accessed through its interface functions.
    641 For contrast, Figure~\ref{f:PythonFibonacci} shows the equivalent Python Fibonacci generator, which does not use a generator type, and hence only has a single interface, but an implicit closure.
    642 
    643 Having to manually create the generator closure by moving local-state variables into the generator type is an additional programmer burden.
    644 (This restriction is removed by the coroutine in Section~\ref{s:Coroutine}.)
    645 This requirement follows from the generality of variable-size local-state, \eg local state with a variable-length array requires dynamic allocation because the array size is unknown at compile time.
    646 However, dynamic allocation significantly increases the cost of generator creation/destruction and is a showstopper for embedded real-time programming.
    647 But more importantly, the size of the generator type is tied to the local state in the generator main, which precludes separate compilation of the generator main, \ie a generator must be inlined or local state must be dynamically allocated.
    648 With respect to safety, we believe static analysis can discriminate local state from temporary variables in a generator, \ie variable usage spanning @suspend@, and generate a compile-time error.
    649 Finally, our current experience is that most generator problems have simple data state, including local state, but complex execution state, so the burden of creating the generator type is small.
    650 As well, C programmers are not afraid of this kind of semantic programming requirement, if it results in very small, fast generators.
    651 
    652 Figure~\ref{f:CFAFormatGen} shows an asymmetric \newterm{input generator}, @Fmt@, for restructuring text into groups of characters of fixed-size blocks, \ie the input on the left is reformatted into the output on the right, where newlines are ignored.
    653 \begin{center}
     730Using a coroutine, it is possible to express the Fibonacci formula directly without any of the C problems.
     731Figure~\ref{f:Coroutine3States} creates a @coroutine@ type:
     732\begin{cfa}
     733`coroutine` Fib { int fn; };
     734\end{cfa}
     735which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface routines @next@.
     736Like the structure in Figure~\ref{f:ExternalState}, the coroutine type allows multiple instances, where instances of this type are passed to the (overloaded) coroutine main.
     737The coroutine main's stack holds the state for the next generation, @f1@ and @f2@, and the code has the three suspend points, representing the three states in the Fibonacci formula, to context switch back to the caller's resume.
     738The interface routine @next@, takes a Fibonacci instance and context switches to it using @resume@;
     739on restart, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.
     740The first @resume@ is special because it cocalls the coroutine at its coroutine main and allocates the stack;
     741when the coroutine main returns, its stack is deallocated.
     742Hence, @Fib@ is an object at creation, transitions to a coroutine on its first resume, and transitions back to an object when the coroutine main finishes.
     743Figure~\ref{f:Coroutine1State} shows the coroutine version of the C version in Figure~\ref{f:ExternalState}.
     744Coroutine generators are called \newterm{output coroutines} because values are only returned.
     745
     746Figure~\ref{f:CFAFmt} shows an \newterm{input coroutine}, @Format@, for restructuring text into groups of characters of fixed-size blocks.
     747For example, the input of the left is reformatted into the output on the right.
     748\begin{quote}
    654749\tt
    655750\begin{tabular}{@{}l|l@{}}
    656751\multicolumn{1}{c|}{\textbf{\textrm{input}}} & \multicolumn{1}{c}{\textbf{\textrm{output}}} \\
    657 \begin{tabular}[t]{@{}ll@{}}
    658 abcdefghijklmnopqrstuvwxyz \\
    659 abcdefghijklmnopqrstuvwxyz
    660 \end{tabular}
     752abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
    661753&
    662754\begin{tabular}[t]{@{}lllll@{}}
     
    666758\end{tabular}
    667759\end{tabular}
    668 \end{center}
    669 The example takes advantage of resuming a generator in the constructor to prime the loops so the first character sent for formatting appears inside the nested loops.
    670 The destructor provides a newline, if formatted text ends with a full line.
    671 Figure~\ref{f:CFormatSim} shows the C implementation of the \CFA input generator with one additional field and the computed @goto@.
    672 For contrast, Figure~\ref{f:PythonFormatter} shows the equivalent Python format generator with the same properties as the Fibonacci generator.
    673 
    674 Figure~\ref{f:DeviceDriverGen} shows a \emph{killer} asymmetric generator, a device-driver, because device drivers caused 70\%-85\% of failures in Windows/Linux~\cite{Swift05}.
    675 Device drives follow the pattern of simple data state but complex execution state, \ie finite state-machine (FSM) parsing a protocol.
    676 For example, the following protocol:
    677 \begin{center}
    678 \ldots\, STX \ldots\, message \ldots\, ESC ETX \ldots\, message \ldots\, ETX 2-byte crc \ldots
    679 \end{center}
    680 is a network message beginning with the control character STX, ending with an ETX, and followed by a 2-byte cyclic-redundancy check.
    681 Control characters may appear in a message if preceded by an ESC.
    682 When a message byte arrives, it triggers an interrupt, and the operating system services the interrupt by calling the device driver with the byte read from a hardware register.
    683 The device driver returns a status code of its current state, and when a complete message is obtained, the operating system knows the message is in the message buffer.
    684 Hence, the device driver is an input/output generator.
    685 
    686 Note, the cost of creating and resuming the device-driver generator, @Driver@, is virtually identical to call/return, so performance in an operating-system kernel is excellent.
    687 As well, the data state is small, where variables @byte@ and @msg@ are communication variables for passing in message bytes and returning the message, and variables @lnth@, @crc@, and @sum@ are local variable that must be retained between calls and are manually hoisted into the generator type.
    688 % Manually, detecting and hoisting local-state variables is easy when the number is small.
    689 In contrast, the execution state is large, with one @resume@ and seven @suspend@s.
    690 Hence, the key benefits of the generator are correctness, safety, and maintenance because the execution states are transcribed directly into the programming language rather than using a table-driven approach.
    691 Because FSMs can be complex and frequently occur in important domains, direct generator support is important in a system programming language.
     760\end{quote}
     761The example takes advantage of resuming a coroutine in the constructor to prime the loops so the first character sent for formatting appears inside the nested loops.
     762The destruction provides a newline if formatted text ends with a full line.
     763Figure~\ref{f:CFmt} shows the C equivalent formatter, where the loops of the coroutine are flatten (linearized) and rechecked on each call because execution location is not retained between calls.
    692764
    693765\begin{figure}
     
    695767\newbox\myboxA
    696768\begin{lrbox}{\myboxA}
    697 \begin{python}[aboveskip=0pt,belowskip=0pt]
    698 def Fib():
    699         fn1, fn = 0, 1
    700         while True:
    701                 `yield fn1`
    702                 fn1, fn = fn, fn1 + fn
    703 f1 = Fib()
    704 f2 = Fib()
    705 for i in range( 10 ):
    706         print( next( f1 ), next( f2 ) )
    707 
    708 
    709 
    710 
    711 
    712 
    713 \end{python}
    714 \end{lrbox}
    715 
    716 \newbox\myboxB
    717 \begin{lrbox}{\myboxB}
    718 \begin{python}[aboveskip=0pt,belowskip=0pt]
    719 def Fmt():
    720         try:
    721                 while True:
    722                         for g in range( 5 ):
    723                                 for b in range( 4 ):
    724                                         print( `(yield)`, end='' )
    725                                 print( '  ', end='' )
    726                         print()
    727         except GeneratorExit:
    728                 if g != 0 | b != 0:
    729                         print()
    730 fmt = Fmt()
    731 `next( fmt )`                    # prime, next prewritten
    732 for i in range( 41 ):
    733         `fmt.send( 'a' );`      # send to yield
    734 \end{python}
    735 \end{lrbox}
    736 \subfloat[Fibonacci]{\label{f:PythonFibonacci}\usebox\myboxA}
    737 \hspace{3pt}
    738 \vrule
    739 \hspace{3pt}
    740 \subfloat[Formatter]{\label{f:PythonFormatter}\usebox\myboxB}
    741 \caption{Python generator}
    742 \label{f:PythonGenerator}
    743 
    744 \bigskip
    745 
    746 \begin{tabular}{@{}l|l@{}}
    747769\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    748 enum Status { CONT, MSG, ESTX,
    749                                 ELNTH, ECRC };
    750 `generator` Driver {
    751         Status status;
    752         unsigned char byte, * msg; // communication
    753         unsigned int lnth, sum;      // local state
    754         unsigned short int crc;
     770`coroutine` Format {
     771        char ch;   // used for communication
     772        int g, b;  // global because used in destructor
    755773};
    756 void ?{}( Driver & d, char * m ) { d.msg = m; }
    757 Status next( Driver & d, char b ) with( d ) {
    758         byte = b; `resume( d );` return status;
    759 }
    760 void main( Driver & d ) with( d ) {
    761         enum { STX = '\002', ESC = '\033',
    762                         ETX = '\003', MaxMsg = 64 };
    763   msg: for () { // parse message
    764                 status = CONT;
    765                 lnth = 0; sum = 0;
    766                 while ( byte != STX ) `suspend;`
    767           emsg: for () {
    768                         `suspend;` // process byte
    769 \end{cfa}
    770 &
    771 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    772                         choose ( byte ) { // switch with implicit break
    773                           case STX:
    774                                 status = ESTX; `suspend;` continue msg;
    775                           case ETX:
    776                                 break emsg;
    777                           case ESC:
    778                                 `suspend;`
     774void main( Format & fmt ) with( fmt ) {
     775        for ( ;; ) {
     776                for ( g = 0; g < 5; g += 1 ) {      // group
     777                        for ( b = 0; b < 4; b += 1 ) { // block
     778                                `suspend();`
     779                                sout | ch;              // separator
    779780                        }
    780                         if ( lnth >= MaxMsg ) { // buffer full ?
    781                                 status = ELNTH; `suspend;` continue msg; }
    782                         msg[lnth++] = byte;
    783                         sum += byte;
     781                        sout | "  ";               // separator
    784782                }
    785                 msg[lnth] = '\0'; // terminate string
    786                 `suspend;`
    787                 crc = byte << 8;
    788                 `suspend;`
    789                 status = (crc | byte) == sum ? MSG : ECRC;
    790                 `suspend;`
     783                sout | endl;
    791784        }
    792785}
    793 \end{cfa}
    794 \end{tabular}
    795 \caption{Device-driver generator for communication protocol}
    796 \label{f:DeviceDriverGen}
    797 \end{figure}
    798 
    799 Figure~\ref{f:CFAPingPongGen} shows a symmetric generator, where the generator resumes another generator, forming a resume/resume cycle.
    800 (The trivial cycle is a generator resuming itself.)
    801 This control flow is similar to recursion for functions but without stack growth.
    802 The steps for symmetric control-flow are creating, executing, and terminating the cycle.
    803 Constructing the cycle must deal with definition-before-use to close the cycle, \ie, the first generator must know about the last generator, which is not within scope.
    804 (This issue occurs for any cyclic data structure.)
    805 % The example creates all the generators and then assigns the partners that form the cycle.
    806 % Alternatively, the constructor can assign the partners as they are declared, except the first, and the first-generator partner is set after the last generator declaration to close the cycle.
    807 Once the cycle is formed, the program main resumes one of the generators, and the generators can then traverse an arbitrary cycle using @resume@ to activate partner generator(s).
    808 Terminating the cycle is accomplished by @suspend@ or @return@, both of which go back to the stack frame that started the cycle (program main in the example).
    809 The starting stack-frame is below the last active generator because the resume/resume cycle does not grow the stack.
    810 Also, since local variables are not retained in the generator function, it does not contain any objects with destructors that must be called, so the  cost is the same as a function return.
    811 Destructor cost occurs when the generator instance is deallocated, which is easily controlled by the programmer.
    812 
    813 Figure~\ref{f:CPingPongSim} shows the implementation of the symmetric generator, where the complexity is the @resume@, which needs an extension to the calling convention to perform a forward rather than backward jump.
    814 This jump-starts at the top of the next generator main to re-execute the normal calling convention to make space on the stack for its local variables.
    815 However, before the jump, the caller must reset its stack (and any registers) equivalent to a @return@, but subsequently jump forward.
    816 This semantics is basically a tail-call optimization, which compilers already perform.
    817 The example shows the assembly code to undo the generator's entry code before the direct jump.
    818 This assembly code depends on what entry code is generated, specifically if there are local variables and the level of optimization.
    819 To provide this new calling convention requires a mechanism built into the compiler, which is beyond the scope of \CFA at this time.
    820 Nevertheless, it is possible to hand generate any symmetric generators for proof of concept and performance testing.
    821 A compiler could also eliminate other artifacts in the generator simulation to further increase performance, \eg LLVM has various coroutine support~\cite{CoroutineTS}, and \CFA can leverage this support should it fork @clang@.
    822 
    823 \begin{figure}
    824 \centering
    825 \begin{lrbox}{\myboxA}
    826 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    827 `generator PingPong` {
    828         const char * name;
    829         int N;
    830         int i;                          // local state
    831         PingPong & partner; // rebindable reference
    832 };
    833 
    834 void `main( PingPong & pp )` with(pp) {
    835         for ( ; i < N; i += 1 ) {
    836                 sout | name | i;
    837                 `resume( partner );`
    838         }
     786void ?{}( Format & fmt ) { `resume( fmt );` }
     787void ^?{}( Format & fmt ) with( fmt ) {
     788        if ( g != 0 || b != 0 ) sout | endl;
     789}
     790void format( Format & fmt ) {
     791        `resume( fmt );`
    839792}
    840793int main() {
    841         enum { N = 5 };
    842         PingPong ping = {"ping",N,0}, pong = {"pong",N,0};
    843         &ping.partner = &pong;  &pong.partner = &ping;
    844         `resume( ping );`
    845 }
    846 \end{cfa}
    847 \end{lrbox}
    848 
    849 \begin{lrbox}{\myboxB}
    850 \begin{cfa}[escapechar={},aboveskip=0pt,belowskip=0pt]
    851 typedef struct PingPong {
    852         const char * name;
    853         int N, i;
    854         struct PingPong * partner;
    855         void * next;
    856 } PingPong;
    857 #define PPCtor(name, N) {name,N,0,NULL,NULL}
    858 void comain( PingPong * pp ) {
    859         if ( pp->next ) goto *pp->next;
    860         pp->next = &&cycle;
    861         for ( ; pp->i < pp->N; pp->i += 1 ) {
    862                 printf( "%s %d\n", pp->name, pp->i );
    863                 asm( "mov  %0,%%rdi" : "=m" (pp->partner) );
    864                 asm( "mov  %rdi,%rax" );
    865                 asm( "popq %rbx" );
    866                 asm( "jmp  comain" );
    867           cycle: ;
    868         }
    869 }
    870 \end{cfa}
    871 \end{lrbox}
    872 
    873 \subfloat[\CFA symmetric generator]{\label{f:CFAPingPongGen}\usebox\myboxA}
    874 \hspace{3pt}
    875 \vrule
    876 \hspace{3pt}
    877 \subfloat[C generator simulation]{\label{f:CPingPongSim}\usebox\myboxB}
    878 \hspace{3pt}
    879 \caption{Ping-Pong symmetric generator}
    880 \label{f:PingPongSymmetricGenerator}
    881 \end{figure}
    882 
    883 Finally, part of this generator work was inspired by the recent \CCtwenty generator proposal~\cite{C++20Coroutine19} (which they call coroutines).
    884 Our work provides the same high-performance asymmetric generators as \CCtwenty, and extends their work with symmetric generators.
    885 An additional \CCtwenty generator feature allows @suspend@ and @resume@ to be followed by a restricted compound statement that is executed after the current generator has reset its stack but before calling the next generator, specified with \CFA syntax:
    886 \begin{cfa}
    887 ... suspend`{ ... }`;
    888 ... resume( C )`{ ... }` ...
    889 \end{cfa}
    890 Since the current generator's stack is released before calling the compound statement, the compound statement can only reference variables in the generator's type.
    891 This feature is useful when a generator is used in a concurrent context to ensure it is stopped before releasing a lock in the compound statement, which might immediately allow another thread to resume the generator.
    892 Hence, this mechanism provides a general and safe handoff of the generator among competing threads.
    893 
    894 
    895 \subsection{Coroutine}
    896 \label{s:Coroutine}
    897 
    898 Stackful coroutines extend generator semantics, \ie there is an implicit closure and @suspend@ may appear in a helper function called from the coroutine main.
    899 A coroutine is specified by replacing @generator@ with @coroutine@ for the type.
    900 Coroutine generality results in higher cost for creation, due to dynamic stack allocation, execution, due to context switching among stacks, and terminating, due to possible stack unwinding and dynamic stack deallocation.
    901 A series of different kinds of coroutines and their implementations demonstrate how coroutines extend generators.
    902 
    903 First, the previous generator examples are converted to their coroutine counterparts, allowing local-state variables to be moved from the generator type into the coroutine main.
    904 \begin{description}
    905 \item[Fibonacci]
    906 Move the declaration of @fn1@ to the start of coroutine main.
    907 \begin{cfa}[xleftmargin=0pt]
    908 void main( Fib & fib ) with(fib) {
    909         `int fn1;`
    910 \end{cfa}
    911 \item[Formatter]
    912 Move the declaration of @g@ and @b@ to the for loops in the coroutine main.
    913 \begin{cfa}[xleftmargin=0pt]
    914 for ( `g`; 5 ) {
    915         for ( `b`; 4 ) {
    916 \end{cfa}
    917 \item[Device Driver]
    918 Move the declaration of @lnth@ and @sum@ to their points of initialization.
    919 \begin{cfa}[xleftmargin=0pt]
    920         status = CONT;
    921         `unsigned int lnth = 0, sum = 0;`
    922         ...
    923         `unsigned short int crc = byte << 8;`
    924 \end{cfa}
    925 \item[PingPong]
    926 Move the declaration of @i@ to the for loop in the coroutine main.
    927 \begin{cfa}[xleftmargin=0pt]
    928 void main( PingPong & pp ) with(pp) {
    929         for ( `i`; N ) {
    930 \end{cfa}
    931 \end{description}
    932 It is also possible to refactor code containing local-state and @suspend@ statements into a helper function, like the computation of the CRC for the device driver.
    933 \begin{cfa}
    934 unsigned int Crc() {
    935         `suspend;`
    936         unsigned short int crc = byte << 8;
    937         `suspend;`
    938         status = (crc | byte) == sum ? MSG : ECRC;
    939         return crc;
    940 }
    941 \end{cfa}
    942 A call to this function is placed at the end of the driver's coroutine-main.
    943 For complex finite-state machines, refactoring is part of normal program abstraction, especially when code is used in multiple places.
    944 Again, this complexity is usually associated with execution state rather than data state.
    945 
    946 \begin{comment}
    947 Figure~\ref{f:Coroutine3States} creates a @coroutine@ type, @`coroutine` Fib { int fn; }@, which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface functions, \eg @next@.
    948 Like the structure in Figure~\ref{f:ExternalState}, the coroutine type allows multiple instances, where instances of this type are passed to the (overloaded) coroutine main.
    949 The coroutine main's stack holds the state for the next generation, @f1@ and @f2@, and the code represents the three states in the Fibonacci formula via the three suspend points, to context switch back to the caller's @resume@.
    950 The interface function @next@, takes a Fibonacci instance and context switches to it using @resume@;
    951 on restart, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.
    952 The first @resume@ is special because it allocates the coroutine stack and cocalls its coroutine main on that stack;
    953 when the coroutine main returns, its stack is deallocated.
    954 Hence, @Fib@ is an object at creation, transitions to a coroutine on its first resume, and transitions back to an object when the coroutine main finishes.
    955 Figure~\ref{f:Coroutine1State} shows the coroutine version of the C version in Figure~\ref{f:ExternalState}.
    956 Coroutine generators are called \newterm{output coroutines} because values are only returned.
    957 
    958 \begin{figure}
    959 \centering
    960 \newbox\myboxA
    961 % \begin{lrbox}{\myboxA}
    962 % \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    963 % `int fn1, fn2, state = 1;`   // single global variables
    964 % int fib() {
    965 %       int fn;
    966 %       `switch ( state )` {  // explicit execution state
    967 %         case 1: fn = 0;  fn1 = fn;  state = 2;  break;
    968 %         case 2: fn = 1;  fn2 = fn1;  fn1 = fn;  state = 3;  break;
    969 %         case 3: fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn;  break;
    970 %       }
    971 %       return fn;
    972 % }
    973 % int main() {
    974 %
    975 %       for ( int i = 0; i < 10; i += 1 ) {
    976 %               printf( "%d\n", fib() );
    977 %       }
    978 % }
    979 % \end{cfa}
    980 % \end{lrbox}
    981 \begin{lrbox}{\myboxA}
    982 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    983 #define FibCtor { 0, 1 }
    984 typedef struct { int fn1, fn; } Fib;
    985 int fib( Fib * f ) {
    986 
    987         int ret = f->fn1;
    988         f->fn1 = f->fn;
    989         f->fn = ret + f->fn;
    990         return ret;
    991 }
    992 
    993 
    994 
    995 int main() {
    996         Fib f1 = FibCtor, f2 = FibCtor;
    997         for ( int i = 0; i < 10; i += 1 ) {
    998                 printf( "%d %d\n",
    999                                 fib( &f1 ), fib( &f2 ) );
     794        Format fmt;
     795        eof: for ( ;; ) {
     796                sin | fmt.ch;
     797          if ( eof( sin ) ) break eof;
     798                format( fmt );
    1000799        }
    1001800}
     
    1006805\begin{lrbox}{\myboxB}
    1007806\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1008 `coroutine` Fib { int fn1; };
    1009 void main( Fib & fib ) with( fib ) {
    1010         int fn;
    1011         [fn1, fn] = [0, 1];
    1012         for () {
    1013                 `suspend;`
    1014                 [fn1, fn] = [fn, fn1 + fn];
     807struct Format {
     808        char ch;
     809        int g, b;
     810};
     811void format( struct Format * fmt ) {
     812        if ( fmt->ch != -1 ) {      // not EOF ?
     813                printf( "%c", fmt->ch );
     814                fmt->b += 1;
     815                if ( fmt->b == 4 ) {  // block
     816                        printf( "  " );      // separator
     817                        fmt->b = 0;
     818                        fmt->g += 1;
     819                }
     820                if ( fmt->g == 5 ) {  // group
     821                        printf( "\n" );     // separator
     822                        fmt->g = 0;
     823                }
     824        } else {
     825                if ( fmt->g != 0 || fmt->b != 0 ) printf( "\n" );
    1015826        }
    1016827}
    1017 int ?()( Fib & fib ) with( fib ) {
    1018         return `resume( fib )`.fn1;
    1019 }
    1020828int main() {
    1021         Fib f1, f2;
    1022         for ( 10 ) {
    1023                 sout | f1() | f2();
    1024 }
    1025 
    1026 
     829        struct Format fmt = { 0, 0, 0 };
     830        for ( ;; ) {
     831                scanf( "%c", &fmt.ch );
     832          if ( feof( stdin ) ) break;
     833                format( &fmt );
     834        }
     835        fmt.ch = -1;
     836        format( &fmt );
     837}
    1027838\end{cfa}
    1028839\end{lrbox}
    1029 
    1030 \newbox\myboxC
    1031 \begin{lrbox}{\myboxC}
    1032 \begin{python}[aboveskip=0pt,belowskip=0pt]
    1033 
    1034 def Fib():
    1035 
    1036         fn1, fn = 0, 1
    1037         while True:
    1038                 `yield fn1`
    1039                 fn1, fn = fn, fn1 + fn
    1040 
    1041 
    1042 // next prewritten
    1043 
    1044 
    1045 f1 = Fib()
    1046 f2 = Fib()
    1047 for i in range( 10 ):
    1048         print( next( f1 ), next( f2 ) )
    1049 
    1050 
    1051 
    1052 \end{python}
    1053 \end{lrbox}
    1054 
    1055 \subfloat[C]{\label{f:GlobalVariables}\usebox\myboxA}
    1056 \hspace{3pt}
    1057 \vrule
    1058 \hspace{3pt}
    1059 \subfloat[\CFA]{\label{f:ExternalState}\usebox\myboxB}
    1060 \hspace{3pt}
    1061 \vrule
    1062 \hspace{3pt}
    1063 \subfloat[Python]{\label{f:ExternalState}\usebox\myboxC}
    1064 \caption{Fibonacci generator}
    1065 \label{f:C-fibonacci}
     840\subfloat[\CFA Coroutine]{\label{f:CFAFmt}\usebox\myboxA}
     841\qquad
     842\subfloat[C Linearized]{\label{f:CFmt}\usebox\myboxB}
     843\caption{Formatting text into lines of 5 blocks of 4 characters.}
     844\label{f:fmt-line}
    1066845\end{figure}
    1067846
    1068 \bigskip
    1069 
    1070 \newbox\myboxA
    1071 \begin{lrbox}{\myboxA}
    1072 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1073 `coroutine` Fib { int fn; };
    1074 void main( Fib & fib ) with( fib ) {
    1075         fn = 0;  int fn1 = fn; `suspend`;
    1076         fn = 1;  int fn2 = fn1;  fn1 = fn; `suspend`;
    1077         for () {
    1078                 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; `suspend`; }
    1079 }
    1080 int next( Fib & fib ) with( fib ) { `resume( fib );` return fn; }
    1081 int main() {
    1082         Fib f1, f2;
    1083         for ( 10 )
    1084                 sout | next( f1 ) | next( f2 );
    1085 }
    1086 \end{cfa}
    1087 \end{lrbox}
    1088 \newbox\myboxB
    1089 \begin{lrbox}{\myboxB}
    1090 \begin{python}[aboveskip=0pt,belowskip=0pt]
    1091 
    1092 def Fibonacci():
    1093         fn = 0; fn1 = fn; `yield fn`  # suspend
    1094         fn = 1; fn2 = fn1; fn1 = fn; `yield fn`
    1095         while True:
    1096                 fn = fn1 + fn2; fn2 = fn1; fn1 = fn; `yield fn`
    1097 
    1098 
    1099 f1 = Fibonacci()
    1100 f2 = Fibonacci()
    1101 for i in range( 10 ):
    1102         print( `next( f1 )`, `next( f2 )` ) # resume
    1103 
    1104 \end{python}
    1105 \end{lrbox}
    1106 \subfloat[\CFA]{\label{f:Coroutine3States}\usebox\myboxA}
    1107 \qquad
    1108 \subfloat[Python]{\label{f:Coroutine1State}\usebox\myboxB}
    1109 \caption{Fibonacci input coroutine, 3 states, internal variables}
    1110 \label{f:cfa-fibonacci}
    1111 \end{figure}
    1112 \end{comment}
     847The previous examples are \newterm{asymmetric (semi) coroutine}s because one coroutine always calls a resuming routine for another coroutine, and the resumed coroutine always suspends back to its last resumer, similar to call/return for normal routines
     848However, there is no stack growth because @resume@/@suspend@ context switch to existing stack-frames rather than create new ones.
     849\newterm{Symmetric (full) coroutine}s have a coroutine call a resuming routine for another coroutine, which eventually forms a resuming-call cycle.
     850(The trivial cycle is a coroutine resuming itself.)
     851This control flow is similar to recursion for normal routines, but again there is no stack growth from the context switch.
    1113852
    1114853\begin{figure}
     
    1118857\begin{cfa}
    1119858`coroutine` Prod {
    1120         Cons & c;                       // communication
     859        Cons & c;
    1121860        int N, money, receipt;
    1122861};
    1123862void main( Prod & prod ) with( prod ) {
    1124863        // 1st resume starts here
    1125         for ( i; N ) {
     864        for ( int i = 0; i < N; i += 1 ) {
    1126865                int p1 = random( 100 ), p2 = random( 100 );
    1127                 sout | p1 | " " | p2;
     866                sout | p1 | " " | p2 | endl;
    1128867                int status = delivery( c, p1, p2 );
    1129                 sout | " $" | money | nl | status;
     868                sout | " $" | money | endl | status | endl;
    1130869                receipt += 1;
    1131870        }
    1132871        stop( c );
    1133         sout | "prod stops";
     872        sout | "prod stops" | endl;
    1134873}
    1135874int payment( Prod & prod, int money ) {
     
    1152891\begin{cfa}
    1153892`coroutine` Cons {
    1154         Prod & p;                       // communication
     893        Prod & p;
    1155894        int p1, p2, status;
    1156         bool done;
     895        _Bool done;
    1157896};
    1158897void ?{}( Cons & cons, Prod & p ) {
    1159         &cons.p = &p; // reassignable reference
     898        &cons.p = &p;
    1160899        cons.[status, done ] = [0, false];
    1161900}
     901void ^?{}( Cons & cons ) {}
    1162902void main( Cons & cons ) with( cons ) {
    1163903        // 1st resume starts here
    1164904        int money = 1, receipt;
    1165905        for ( ; ! done; ) {
    1166                 sout | p1 | " " | p2 | nl | " $" | money;
     906                sout | p1 | " " | p2 | endl | " $" | money | endl;
    1167907                status += 1;
    1168908                receipt = payment( p, money );
    1169                 sout | " #" | receipt;
     909                sout | " #" | receipt | endl;
    1170910                money += 1;
    1171911        }
    1172         sout | "cons stops";
     912        sout | "cons stops" | endl;
    1173913}
    1174914int delivery( Cons & cons, int p1, int p2 ) {
     
    1181921        `resume( cons );`
    1182922}
    1183 
    1184923\end{cfa}
    1185924\end{tabular}
    1186 \caption{Producer / consumer: resume-resume cycle, bidirectional communication}
     925\caption{Producer / consumer: resume-resume cycle, bi-directional communication}
    1187926\label{f:ProdCons}
    1188927\end{figure}
    1189928
    1190 Figure~\ref{f:ProdCons} shows the ping-pong example in Figure~\ref{f:CFAPingPongGen} extended into a producer/consumer symmetric-coroutine performing bidirectional communication.
    1191 This example is illustrative because both producer/consumer have two interface functions with @resume@s that suspend execution in these interface (helper) functions.
    1192 The program main creates the producer coroutine, passes it to the consumer coroutine in its initialization, and closes the cycle at the call to @start@ along with the number of items to be produced.
    1193 The first @resume@ of @prod@ creates @prod@'s stack with a frame for @prod@'s coroutine main at the top, and context switches to it.
    1194 @prod@'s coroutine main starts, creates local-state variables that are retained between coroutine activations, and executes $N$ iterations, each generating two random values, calling the consumer to deliver the values, and printing the status returned from the consumer.
     929Figure~\ref{f:ProdCons} shows a producer/consumer symmetric-coroutine performing bi-directional communication.
     930Since the solution involves a full-coroutining cycle, the program main creates one coroutine in isolation, passes this coroutine to its partner, and closes the cycle at the call to @start@.
     931The @start@ routine communicates both the number of elements to be produced and the consumer into the producer's coroutine structure.
     932Then the @resume@ to @prod@ creates @prod@'s stack with a frame for @prod@'s coroutine main at the top, and context switches to it.
     933@prod@'s coroutine main starts, creates local variables that are retained between coroutine activations, and executes $N$ iterations, each generating two random values, calling the consumer to deliver the values, and printing the status returned from the consumer.
    1195934
    1196935The producer call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status.
    1197 On the first resume, @cons@'s stack is created and initialized, holding local-state variables retained between subsequent activations of the coroutine.
    1198 The consumer iterates until the @done@ flag is set, prints the values delivered by the producer, increments status, and calls back to the producer via @payment@, and on return from @payment@, prints the receipt from the producer and increments @money@ (inflation).
    1199 The call from the consumer to @payment@ introduces the cycle between producer and consumer.
     936For the first resume, @cons@'s stack is initialized, creating local variables retained between subsequent activations of the coroutine.
     937The consumer iterates until the @done@ flag is set, prints, increments status, and calls back to the producer via @payment@, and on return from @payment@, prints the receipt from the producer and increments @money@ (inflation).
     938The call from the consumer to the @payment@ introduces the cycle between producer and consumer.
    1200939When @payment@ is called, the consumer copies values into the producer's communication variable and a resume is executed.
    1201 The context switch restarts the producer at the point where it last context switched, so it continues in @delivery@ after the resume.
     940The context switch restarts the producer at the point where it was last context switched, so it continues in @delivery@ after the resume.
     941
    1202942@delivery@ returns the status value in @prod@'s coroutine main, where the status is printed.
    1203943The loop then repeats calling @delivery@, where each call resumes the consumer coroutine.
     
    1205945The consumer increments and returns the receipt to the call in @cons@'s coroutine main.
    1206946The loop then repeats calling @payment@, where each call resumes the producer coroutine.
    1207 Figure~\ref{f:ProdConsRuntimeStacks} shows the runtime stacks of the program main, and the coroutine mains for @prod@ and @cons@ during the cycling.
    1208 
    1209 \begin{figure}
    1210 \begin{center}
    1211 \input{FullProdConsStack.pstex_t}
    1212 \end{center}
    1213 \vspace*{-10pt}
    1214 \caption{Producer / consumer runtime stacks}
    1215 \label{f:ProdConsRuntimeStacks}
    1216 
    1217 \medskip
    1218 
    1219 \begin{center}
    1220 \input{FullCoroutinePhases.pstex_t}
    1221 \end{center}
    1222 \vspace*{-10pt}
    1223 \caption{Ping / Pong coroutine steps}
    1224 \label{f:PingPongFullCoroutineSteps}
    1225 \end{figure}
    1226 
    1227 Terminating a coroutine cycle is more complex than a generator cycle, because it requires context switching to the program main's \emph{stack} to shutdown the program, whereas generators started by the program main run on its stack.
    1228 Furthermore, each deallocated coroutine must guarantee all destructors are run for object allocated in the coroutine type \emph{and} allocated on the coroutine's stack at the point of suspension, which can be arbitrarily deep.
    1229 When a coroutine's main ends, its stack is already unwound so any stack allocated objects with destructors have been finalized.
    1230 The na\"{i}ve semantics for coroutine-cycle termination is to context switch to the last resumer, like executing a @suspend@/@return@ in a generator.
    1231 However, for coroutines, the last resumer is \emph{not} implicitly below the current stack frame, as for generators, because each coroutine's stack is independent.
    1232 Unfortunately, it is impossible to determine statically if a coroutine is in a cycle and unrealistic to check dynamically (graph-cycle problem).
    1233 Hence, a compromise solution is necessary that works for asymmetric (acyclic) and symmetric (cyclic) coroutines.
    1234 
    1235 Our solution is to context switch back to the first resumer (starter) once the coroutine ends.
    1236 This semantics works well for the most common asymmetric and symmetric coroutine usage patterns.
    1237 For asymmetric coroutines, it is common for the first resumer (starter) coroutine to be the only resumer.
    1238 All previous generators converted to coroutines have this property.
    1239 For symmetric coroutines, it is common for the cycle creator to persist for the lifetime of the cycle.
    1240 Hence, the starter coroutine is remembered on the first resume and ending the coroutine resumes the starter.
    1241 Figure~\ref{f:ProdConsRuntimeStacks} shows this semantic by the dashed lines from the end of the coroutine mains: @prod@ starts @cons@ so @cons@ resumes @prod@ at the end, and the program main starts @prod@ so @prod@ resumes the program main at the end.
    1242 For other scenarios, it is always possible to devise a solution with additional programming effort, such as forcing the cycle forward (backward) to a safe point before starting termination.
    1243 
    1244 The producer/consumer example does not illustrate the full power of the starter semantics because @cons@ always ends first.
    1245 Assume generator @PingPong@ is converted to a coroutine.
    1246 Figure~\ref{f:PingPongFullCoroutineSteps} shows the creation, starter, and cyclic execution steps of the coroutine version.
    1247 The program main creates (declares) coroutine instances @ping@ and @pong@.
    1248 Next, program main resumes @ping@, making it @ping@'s starter, and @ping@'s main resumes @pong@'s main, making it @pong@'s starter.
    1249 Execution forms a cycle when @pong@ resumes @ping@, and cycles $N$ times.
    1250 By adjusting $N$ for either @ping@/@pong@, it is possible to have either one finish first, instead of @pong@ always ending first.
    1251 If @pong@ ends first, it resumes its starter @ping@ in its coroutine main, then @ping@ ends and resumes its starter the program main in function @start@.
    1252 If @ping@ ends first, it resumes its starter the program main in function @start@.
    1253 Regardless of the cycle complexity, the starter stack always leads back to the program main, but the stack can be entered at an arbitrary point.
    1254 Once back at the program main, coroutines @ping@ and @pong@ are deallocated.
    1255 For generators, deallocation runs the destructors for all objects in the generator type.
    1256 For coroutines, deallocation deals with objects in the coroutine type and must also run the destructors for any objects pending on the coroutine's stack for any unterminated coroutine.
    1257 Hence, if a coroutine's destructor detects the coroutine is not ended, it implicitly raises a cancellation exception (uncatchable exception) at the coroutine and resumes it so the cancellation exception can propagate to the root of the coroutine's stack destroying all local variable on the stack.
    1258 So the \CFA semantics for the generator and coroutine, ensure both can be safely deallocated at any time, regardless of their current state, like any other aggregate object.
    1259 Explicitly raising normal exceptions at another coroutine can replace flag variables, like @stop@, \eg @prod@ raises a @stop@ exception at @cons@ after it finishes generating values and resumes @cons@, which catches the @stop@ exception to terminate its loop.
    1260 
    1261 Finally, there is an interesting effect for @suspend@ with symmetric coroutines.
    1262 A coroutine must retain its last resumer to suspend back because the resumer is on a different stack.
    1263 These reverse pointers allow @suspend@ to cycle \emph{backwards}, which may be useful in certain cases.
    1264 However, there is an anomaly if a coroutine resumes itself, because it overwrites its last resumer with itself, losing the ability to resume the last external resumer.
    1265 To prevent losing this information, a self-resume does not overwrite the last resumer.
    1266 
    1267 
    1268 \subsection{Generator / Coroutine Implementation}
    1269 
    1270 A significant implementation challenge for generators/coroutines (and threads in Section~\ref{s:threads}) is adding extra fields to the custom types and related functions, \eg inserting code after/before the coroutine constructor/destructor and @main@ to create/initialize/de-initialize/destroy any extra fields, \eg stack.
    1271 There are several solutions to these problem, which follow from the object-oriented flavour of adopting custom types.
    1272 
    1273 For object-oriented languages, inheritance is used to provide extra fields and code via explicit inheritance:
    1274 \begin{cfa}[morekeywords={class,inherits}]
    1275 class myCoroutine inherits baseCoroutine { ... }
    1276 \end{cfa}
    1277 % The problem is that the programming language and its tool chain, \eg debugger, @valgrind@, need to understand @baseCoroutine@ because it infers special property, so type @baseCoroutine@ becomes a de facto keyword and all types inheriting from it are implicitly custom types.
    1278 The problem is that some special properties are not handled by existing language semantics, \eg the execution of constructors/destructors is in the wrong order to implicitly start threads because the thread must start \emph{after} all constructors as it relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived.
    1279 Alternatives, such as explicitly starting threads as in Java, are repetitive and forgetting to call start is a common source of errors.
    1280 An alternative is composition:
    1281 \begin{cfa}
    1282 struct myCoroutine {
    1283         ... // declaration/communication variables
     947
     948After iterating $N$ times, the producer calls @stop@.
     949The @done@ flag is set to stop the consumer's execution and a resume is executed.
     950The context switch restarts @cons@ in @payment@ and it returns with the last receipt.
     951The consumer terminates its loops because @done@ is true, its @main@ terminates, so @cons@ transitions from a coroutine back to an object, and @prod@ reactivates after the resume in @stop@.
     952@stop@ returns and @prod@'s coroutine main terminates.
     953The program main restarts after the resume in @start@.
     954@start@ returns and the program main terminates.
     955
     956
     957\subsection{Coroutine Implementation}
     958
     959A significant implementation challenge for coroutines (and threads, see section \ref{threads}) is adding extra fields and executing code after/before the coroutine constructor/destructor and coroutine main to create/initialize/de-initialize/destroy extra fields and the stack.
     960There are several solutions to this problem and the chosen option forced the \CFA coroutine design.
     961
     962Object-oriented inheritance provides extra fields and code in a restricted context, but it requires programmers to explicitly perform the inheritance:
     963\begin{cfa}
     964struct mycoroutine $\textbf{\textsf{inherits}}$ baseCoroutine { ... }
     965\end{cfa}
     966and the programming language (and possibly its tool set, \eg debugger) may need to understand @baseCoroutine@ because of the stack.
     967Furthermore, the execution of constructs/destructors is in the wrong order for certain operations, \eg for threads;
     968\eg, if the thread is implicitly started, it must start \emph{after} all constructors, because the thread relies on a completely initialized object, but the inherited constructor runs \emph{before} the derived.
     969
     970An alternatively is composition:
     971\begin{cfa}
     972struct mycoroutine {
     973        ... // declarations
    1284974        baseCoroutine dummy; // composition, last declaration
    1285975}
    1286976\end{cfa}
    1287 which also requires an explicit declaration that must be last to ensure correct initialization order.
     977which also requires an explicit declaration that must be the last one to ensure correct initialization order.
    1288978However, there is nothing preventing wrong placement or multiple declarations.
    1289979
    1290 \CFA custom types make any special properties explicit to the language and its tool chain, \eg the language code-generator knows where to inject code
    1291 % and when it is unsafe to perform certain optimizations,
    1292 and IDEs using simple parsing can find and manipulate types with special properties.
    1293 The downside of this approach is that it makes custom types a special case in the language.
    1294 Users wanting to extend custom types or build their own can only do so in ways offered by the language.
    1295 Furthermore, implementing custom types without language support may display the power of a programming language.
    1296 \CFA blends the two approaches, providing custom type for idiomatic \CFA code, while extending and building new custom types is still possible, similar to Java concurrency with builtin and library.
    1297 
    1298 Part of the mechanism to generalize custom types is the \CFA trait~\cite[\S~2.3]{Moss18}, \eg the definition for custom-type @coroutine@ is anything satisfying the trait @is_coroutine@, and this trait both enforces and restricts the coroutine-interface functions.
     980For coroutines as for threads, many implementations are based on routine pointers or routine objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
     981For example, Boost implements coroutines in terms of four functor object-types:
     982\begin{cfa}
     983asymmetric_coroutine<>::pull_type
     984asymmetric_coroutine<>::push_type
     985symmetric_coroutine<>::call_type
     986symmetric_coroutine<>::yield_type
     987\end{cfa}
     988Similarly, the canonical threading paradigm is often based on routine pointers, \eg @pthread@~\cite{pthreads}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}.
     989However, the generic thread-handle (identifier) is limited (few operations), unless it is wrapped in a custom type.
     990\begin{cfa}
     991void mycor( coroutine_t cid, void * arg ) {
     992        int * value = (int *)arg;                               $\C{// type unsafe, pointer-size only}$
     993        // Coroutine body
     994}
     995int main() {
     996        int input = 0, output;
     997        coroutine_t cid = coroutine_create( &mycor, (void *)&input ); $\C{// type unsafe, pointer-size only}$
     998        coroutine_resume( cid, (void *)input, (void **)&output ); $\C{// type unsafe, pointer-size only}$
     999}
     1000\end{cfa}
     1001Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda-based coroutines adds very little.
     1002
     1003Note, the type @coroutine_t@ must be an abstract handle to the coroutine, because the coroutine descriptor and its stack are non-copyable.
     1004Copying the coroutine descriptor results in copies being out of date with the current state of the stack.
     1005Correspondingly, copying the stack results is copies being out of date with coroutine descriptor, and pointers in the stack being out of date to data on the stack.
     1006(There is no mechanism in C to find all stack-specific pointers and update them as part of a copy.)
     1007
     1008The selected approach is to use language support by introducing a new kind of aggregate (structure):
     1009\begin{cfa}
     1010coroutine Fibonacci {
     1011        int fn; // communication variables
     1012};
     1013\end{cfa}
     1014The @coroutine@ keyword means the compiler (and tool set) can find and inject code where needed.
     1015The downside of this approach is that it makes coroutine a special case in the language.
     1016Users wanting to extend coroutines or build their own for various reasons can only do so in ways offered by the language.
     1017Furthermore, implementing coroutines without language supports also displays the power of a programming language.
     1018While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed without using the language support.
     1019The reserved keyword eases use for the common cases.
     1020
     1021Part of the mechanism to generalize coroutines is using a \CFA trait, which defines a coroutine as anything satisfying the trait @is_coroutine@, and this trait is used to restrict coroutine-manipulation routines:
    12991022\begin{cfa}
    13001023trait is_coroutine( `dtype` T ) {
     
    13021025        coroutine_desc * get_coroutine( T & );
    13031026};
    1304 forall( `dtype` T | is_coroutine(T) ) void $suspend$( T & ), resume( T & );
    1305 \end{cfa}
    1306 Note, copying generators/coroutines/threads is not meaningful.
    1307 For example, both the resumer and suspender descriptors can have bidirectional pointers;
    1308 copying these coroutines does not update the internal pointers so behaviour of both copies would be difficult to understand.
    1309 Furthermore, two coroutines cannot logically execute on the same stack.
    1310 A deep coroutine copy, which copies the stack, is also meaningless in an unmanaged language (no garbage collection), like C, because the stack may contain pointers to object within it that require updating for the copy.
    1311 The \CFA @dtype@ property provides no \emph{implicit} copying operations and the @is_coroutine@ trait provides no \emph{explicit} copying operations, so all coroutines must be passed by reference (pointer).
    1312 The function definitions ensure there is a statically typed @main@ function that is the starting point (first stack frame) of a coroutine, and a mechanism to get (read) the coroutine descriptor from its handle.
    1313 The @main@ function has no return value or additional parameters because the coroutine type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values versus fixed ones.
    1314 The advantage of this approach is that users can easily create different types of coroutines, \eg changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ function, and possibly redefining \textsf{suspend} and @resume@.
    1315 
    1316 The \CFA custom-type @coroutine@ implicitly implements the getter and forward declarations for the coroutine main.
     1027forall( `dtype` T | is_coroutine(T) ) void suspend( T & );
     1028forall( `dtype` T | is_coroutine(T) ) void resume( T & );
     1029\end{cfa}
     1030The @dtype@ property of the trait ensures the coroutine descriptor is non-copyable, so all coroutines must be passed by reference (pointer).
     1031The routine definitions ensures there is a statically-typed @main@ routine that is the starting point (first stack frame) of a coroutine, and a mechanism to get (read) the currently executing coroutine handle.
     1032The @main@ routine has no return value or additional parameters because the coroutine type allows an arbitrary number of interface routines with corresponding arbitrary typed input/output values versus fixed ones.
     1033The generic routines @suspend@ and @resume@ can be redefined, but any object passed to them is a coroutine since it must satisfy the @is_coroutine@ trait to compile.
     1034The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ routine, and possibly redefining @suspend@ and @resume@.
     1035The \CFA keyword @coroutine@ implicitly implements the getter and forward declarations required for implementing the coroutine main:
    13171036\begin{cquote}
    13181037\begin{tabular}{@{}ccc@{}}
     
    13501069\end{tabular}
    13511070\end{cquote}
    1352 The combination of custom types and fundamental @trait@ description of these types allows a concise specification for programmers and tools, while more advanced programmers can have tighter control over memory layout and initialization.
    1353 
    1354 Figure~\ref{f:CoroutineMemoryLayout} shows different memory-layout options for a coroutine (where a task is similar).
    1355 The coroutine handle is the @coroutine@ instance containing programmer specified type global/communication variables across interface functions.
    1356 The coroutine descriptor contains all implicit declarations needed by the runtime, \eg @suspend@/@resume@, and can be part of the coroutine handle or separate.
    1357 The coroutine stack can appear in a number of locations and be fixed or variable sized.
    1358 Hence, the coroutine's stack could be a VLS\footnote{
    1359 We are examining variable-sized structures (VLS), where fields can be variable-sized structures or arrays.
    1360 Once allocated, a VLS is fixed sized.}
    1361 on the allocating stack, provided the allocating stack is large enough.
    1362 For a VLS stack allocation/deallocation is an inexpensive adjustment of the stack pointer, modulo any stack constructor costs (\eg initial frame setup).
    1363 For heap stack allocation, allocation/deallocation is an expensive heap allocation (where the heap can be a shared resource), modulo any stack constructor costs.
    1364 With heap stack allocation, it is also possible to use a split (segmented) stack calling convention, available with gcc and clang, so the stack is variable sized.
    1365 Currently, \CFA supports stack/heap allocated descriptors but only fixed-sized heap allocated stacks.
    1366 In \CFA debug-mode, the fixed-sized stack is terminated with a write-only page, which catches most stack overflows.
    1367 Experience teaching concurrency with \uC~\cite{CS343} shows fixed-sized stacks are rarely an issue for students.
    1368 Split-stack allocation is under development but requires recompilation of legacy code, which may be impossible.
    1369 
    1370 \begin{figure}
    1371 \centering
    1372 \input{corlayout.pstex_t}
    1373 \caption{Coroutine memory layout}
    1374 \label{f:CoroutineMemoryLayout}
    1375 \end{figure}
    1376 
    1377 
    1378 \section{Concurrency}
    1379 \label{s:Concurrency}
    1380 
    1381 Concurrency is nondeterministic scheduling of independent sequential execution paths (threads), where each thread has its own stack.
    1382 A single thread with multiple call stacks, \newterm{coroutining}~\cite{Conway63,Marlin80}, does \emph{not} imply concurrency~\cite[\S~2]{Buhr05a}.
    1383 In coroutining, coroutines self-schedule the thread across stacks so execution is deterministic.
    1384 (It is \emph{impossible} to generate a concurrency error when coroutining.)
    1385 However, coroutines are a stepping stone towards concurrency.
    1386 
    1387 The transition to concurrency, even for a single thread with multiple stacks, occurs when coroutines context switch to a \newterm{scheduling coroutine}, introducing non-determinism from the coroutine perspective~\cite[\S~3,]{Buhr05a}.
    1388 Therefore, a minimal concurrency system requires coroutines \emph{in conjunction with a nondeterministic scheduler}.
    1389 The resulting execution system now follows a cooperative threading model~\cite{Adya02,libdill}, called \newterm{non-preemptive scheduling}.
    1390 Adding \newterm{preemption} introduces non-cooperative scheduling, where context switching occurs randomly between any two instructions often based on a timer interrupt, called \newterm{preemptive scheduling}.
    1391 While a scheduler introduces uncertain execution among explicit context switches, preemption introduces uncertainty by introducing implicit context switches.
    1392 Uncertainty gives the illusion of parallelism on a single processor and provides a mechanism to access and increase performance on multiple processors.
    1393 The reason is that the scheduler/runtime have complete knowledge about resources and how to best utilized them.
    1394 However, the introduction of unrestricted nondeterminism results in the need for \newterm{mutual exclusion} and \newterm{synchronization}, which restrict nondeterminism for correctness;
    1395 otherwise, it is impossible to write meaningful concurrent programs.
    1396 Optimal concurrent performance is often obtained by having as much nondeterminism as mutual exclusion and synchronization correctness allow.
    1397 
    1398 A scheduler can either be a stackless or stackful.
    1399 For stackless, the scheduler performs scheduling on the stack of the current coroutine and switches directly to the next coroutine, so there is one context switch.
    1400 For stackful, the current coroutine switches to the scheduler, which performs scheduling, and it then switches to the next coroutine, so there are two context switches.
    1401 The \CFA runtime uses a stackful scheduler for uniformity and security.
    1402 
    1403 
    1404 \subsection{Thread}
    1405 \label{s:threads}
    1406 
    1407 Threading needs the ability to start a thread and wait for its completion.
    1408 A common API for this ability is @fork@ and @join@.
     1071The combination of these two approaches allows an easy and concise specification to coroutining (and concurrency) for normal users, while more advanced users have tighter control on memory layout and initialization.
     1072
     1073
     1074\subsection{Thread Interface}
     1075\label{threads}
     1076
     1077Both user and kernel threads are supported, where user threads provide concurrency and kernel threads provide parallelism.
     1078Like coroutines and for the same design reasons, the selected approach for user threads is to use language support by introducing a new kind of aggregate (structure) and a \CFA trait:
    14091079\begin{cquote}
    1410 \begin{tabular}{@{}lll@{}}
    1411 \multicolumn{1}{c}{\textbf{Java}} & \multicolumn{1}{c}{\textbf{\Celeven}} & \multicolumn{1}{c}{\textbf{pthreads}} \\
    1412 \begin{cfa}
    1413 class MyTask extends Thread {...}
    1414 mytask t = new MyTask(...);
    1415 `t.start();` // start
    1416 // concurrency
    1417 `t.join();` // wait
     1080\begin{tabular}{@{}c@{\hspace{3\parindentlnth}}c@{}}
     1081\begin{cfa}
     1082thread myThread {
     1083        // communication variables
     1084};
     1085
     1086
    14181087\end{cfa}
    14191088&
    14201089\begin{cfa}
    1421 class MyTask { ... } // functor
    1422 MyTask mytask;
    1423 `thread t( mytask, ... );` // start
    1424 // concurrency
    1425 `t.join();` // wait
    1426 \end{cfa}
    1427 &
    1428 \begin{cfa}
    1429 void * rtn( void * arg ) {...}
    1430 pthread_t t;  int i = 3;
    1431 `pthread_create( &t, rtn, (void *)i );` // start
    1432 // concurrency
    1433 `pthread_join( t, NULL );` // wait
     1090trait is_thread( `dtype` T ) {
     1091      void main( T & );
     1092      thread_desc * get_thread( T & );
     1093      void ^?{}( T & `mutex` );
     1094};
    14341095\end{cfa}
    14351096\end{tabular}
    14361097\end{cquote}
    1437 \CFA has a simpler approach using a custom @thread@ type and leveraging declaration semantics (allocation/deallocation), where threads implicitly @fork@ after construction and @join@ before destruction.
    1438 \begin{cfa}
    1439 thread MyTask {};
    1440 void main( MyTask & this ) { ... }
     1098(The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitors}.)
     1099Like a coroutine, the statically-typed @main@ routine is the starting point (first stack frame) of a user thread.
     1100The difference is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates an instance of @main@;
     1101whereas, a user thread receives its own thread from the runtime system, which starts in @main@ as some point after the thread constructor is run.\footnote{
     1102The \lstinline@main@ routine is already a special routine in C (where the program begins), so it is a natural extension of the semantics to use overloading to declare mains for different coroutines/threads (the normal main being the main of the initial thread).}
     1103No return value or additional parameters are necessary for this routine because the task type allows an arbitrary number of interface routines with corresponding arbitrary typed input/output values.
     1104
     1105\begin{comment} % put in appendix with coroutine version ???
     1106As such the @main@ routine of a thread can be defined as
     1107\begin{cfa}
     1108thread foo {};
     1109
     1110void main(foo & this) {
     1111        sout | "Hello World!" | endl;
     1112}
     1113\end{cfa}
     1114
     1115In this example, threads of type @foo@ start execution in the @void main(foo &)@ routine, which prints @"Hello World!".@ While this paper encourages this approach to enforce strongly typed programming, users may prefer to use the routine-based thread semantics for the sake of simplicity.
     1116With the static semantics it is trivial to write a thread type that takes a routine pointer as a parameter and executes it on its stack asynchronously.
     1117\begin{cfa}
     1118typedef void (*voidRtn)(int);
     1119
     1120thread RtnRunner {
     1121        voidRtn func;
     1122        int arg;
     1123};
     1124
     1125void ?{}(RtnRunner & this, voidRtn inRtn, int arg) {
     1126        this.func = inRtn;
     1127        this.arg  = arg;
     1128}
     1129
     1130void main(RtnRunner & this) {
     1131        // thread starts here and runs the routine
     1132        this.func( this.arg );
     1133}
     1134
     1135void hello(/*unused*/ int) {
     1136        sout | "Hello World!" | endl;
     1137}
     1138
    14411139int main() {
    1442         MyTask team`[10]`; $\C[2.5in]{// allocate stack-based threads, implicit start after construction}$
    1443         // concurrency
    1444 } $\C{// deallocate stack-based threads, implicit joins before destruction}$
    1445 \end{cfa}
    1446 This semantic ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic (termination) synchronization.
    1447 For block allocation to arbitrary depth, including recursion, threads are created/destroyed in a lattice structure (tree with top and bottom).
    1448 Arbitrary topologies are possible using dynamic allocation, allowing threads to outlive their declaration scope, identical to normal dynamic allocation.
    1449 \begin{cfa}
    1450 MyTask * factory( int N ) { ... return `anew( N )`; } $\C{// allocate heap-based threads, implicit start after construction}$
     1140        RtnRunner f = {hello, 42};
     1141        return 0?
     1142}
     1143\end{cfa}
     1144A consequence of the strongly typed approach to main is that memory layout of parameters and return values to/from a thread are now explicitly specified in the \textbf{api}.
     1145\end{comment}
     1146
     1147For user threads to be useful, it must be possible to start and stop the underlying thread, and wait for it to complete execution.
     1148While using an API such as @fork@ and @join@ is relatively common, such an interface is awkward and unnecessary.
     1149A simple approach is to use allocation/deallocation principles, and have threads implicitly @fork@ after construction and @join@ before destruction.
     1150\begin{cfa}
     1151thread World {};
     1152void main( World & this ) {
     1153        sout | "World!" | endl;
     1154}
    14511155int main() {
    1452         MyTask * team = factory( 10 );
    1453         // concurrency
    1454         `delete( team );` $\C{// deallocate heap-based threads, implicit joins before destruction}\CRT$
    1455 }
    1456 \end{cfa}
    1457 
    1458 Figure~\ref{s:ConcurrentMatrixSummation} shows concurrently adding the rows of a matrix and then totalling the subtotals sequentially, after all the row threads have terminated.
     1156        World w`[10]`;                                                  $\C{// implicit forks after creation}$
     1157        sout | "Hello " | endl;                                 $\C{// "Hello " and 10 "World!" printed concurrently}$
     1158}                                                                                       $\C{// implicit joins before destruction}$
     1159\end{cfa}
     1160This semantics ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic (termination) synchronization.
     1161This tree-structure (lattice) create/delete from C block-structure is generalized by using dynamic allocation, so threads can outlive the scope in which they are created, much like dynamically allocating memory lets objects outlive the scope in which they are created.
     1162\begin{cfa}
     1163int main() {
     1164        MyThread * heapLived;
     1165        {
     1166                MyThread blockLived;                            $\C{// fork block-based thread}$
     1167                heapLived = `new`( MyThread );          $\C{// fork heap-based thread}$
     1168                ...
     1169        }                                                                               $\C{// join block-based thread}$
     1170        ...
     1171        `delete`( heapLived );                                  $\C{// join heap-based thread}$
     1172}
     1173\end{cfa}
     1174The heap-based approach allows arbitrary thread-creation topologies, with respect to fork/join-style concurrency.
     1175
     1176Figure~\ref{s:ConcurrentMatrixSummation} shows concurrently adding the rows of a matrix and then totalling the subtotals sequential, after all the row threads have terminated.
    14591177The program uses heap-based threads because each thread needs different constructor values.
    14601178(Python provides a simple iteration mechanism to initialize array elements to different values allowing stack allocation.)
    1461 The allocation/deallocation pattern appears unusual because allocated objects are immediately deallocated without any intervening code.
     1179The allocation/deallocation pattern appears unusual because allocated objects are immediately deleted without any intervening code.
    14621180However, for threads, the deletion provides implicit synchronization, which is the intervening code.
    1463 % While the subtotals are added in linear order rather than completion order, which slightly inhibits concurrency, the computation is restricted by the critical-path thread (\ie the thread that takes the longest), and so any inhibited concurrency is very small as totalling the subtotals is trivial.
     1181While the subtotals are added in linear order rather than completion order, which slight inhibits concurrency, the computation is restricted by the critical-path thread (\ie the thread that takes the longest), and so any inhibited concurrency is very small as totalling the subtotals is trivial.
    14641182
    14651183\begin{figure}
    14661184\begin{cfa}
    1467 `thread` Adder { int * row, cols, & subtotal; } $\C{// communication variables}$
     1185thread Adder {
     1186    int * row, cols, & subtotal;                        $\C{// communication}$
     1187};
    14681188void ?{}( Adder & adder, int row[], int cols, int & subtotal ) {
    1469         adder.[ row, cols, &subtotal ] = [ row, cols, &subtotal ];
     1189    adder.[ row, cols, &subtotal ] = [ row, cols, &subtotal ];
    14701190}
    14711191void main( Adder & adder ) with( adder ) {
    1472         subtotal = 0;
    1473         for ( c; cols ) { subtotal += row[c]; }
     1192    subtotal = 0;
     1193    for ( int c = 0; c < cols; c += 1 ) {
     1194                subtotal += row[c];
     1195    }
    14741196}
    14751197int main() {
    1476         const int rows = 10, cols = 1000;
    1477         int matrix[rows][cols], subtotals[rows], total = 0;
    1478         // read matrix
    1479         Adder * adders[rows];
    1480         for ( r; rows; ) { $\C{// start threads to sum rows}$
    1481                 adders[r] = `new( matrix[r], cols, &subtotals[r] );`
    1482         }
    1483         for ( r; rows ) { $\C{// wait for threads to finish}$
    1484                 `delete( adders[r] );` $\C{// termination join}$
    1485                 total += subtotals[r]; $\C{// total subtotal}$
    1486         }
    1487         sout | total;
    1488 }
    1489 \end{cfa}
    1490 \caption{Concurrent matrix summation}
     1198    const int rows = 10, cols = 1000;
     1199    int matrix[rows][cols], subtotals[rows], total = 0;
     1200    // read matrix
     1201    Adder * adders[rows];
     1202    for ( int r = 0; r < rows; r += 1 ) {       $\C{// start threads to sum rows}$
     1203                adders[r] = new( matrix[r], cols, &subtotals[r] );
     1204    }
     1205    for ( int r = 0; r < rows; r += 1 ) {       $\C{// wait for threads to finish}$
     1206                delete( adders[r] );                            $\C{// termination join}$
     1207                total += subtotals[r];                          $\C{// total subtotal}$
     1208    }
     1209    sout | total | endl;
     1210}
     1211\end{cfa}
     1212\caption{Concurrent Matrix Summation}
    14911213\label{s:ConcurrentMatrixSummation}
    14921214\end{figure}
    14931215
    14941216
    1495 \subsection{Thread Implementation}
    1496 
    1497 Threads in \CFA are user level run by runtime kernel threads (see Section~\ref{s:CFARuntimeStructure}), where user threads provide concurrency and kernel threads provide parallelism.
    1498 Like coroutines, and for the same design reasons, \CFA provides a custom @thread@ type and a @trait@ to enforce and restrict the task-interface functions.
    1499 \begin{cquote}
    1500 \begin{tabular}{@{}c@{\hspace{3\parindentlnth}}c@{}}
    1501 \begin{cfa}
    1502 thread myThread {
    1503         ... // declaration/communication variables
    1504 };
    1505 
    1506 
    1507 \end{cfa}
    1508 &
    1509 \begin{cfa}
    1510 trait is_thread( `dtype` T ) {
    1511         void main( T & );
    1512         thread_desc * get_thread( T & );
    1513         void ^?{}( T & `mutex` );
    1514 };
    1515 \end{cfa}
    1516 \end{tabular}
    1517 \end{cquote}
    1518 Like coroutines, the @dtype@ property prevents \emph{implicit} copy operations and the @is_thread@ trait provides no \emph{explicit} copy operations, so threads must be passed by reference (pointer).
    1519 Similarly, the function definitions ensure there is a statically typed @main@ function that is the thread starting point (first stack frame), a mechanism to get (read) the thread descriptor from its handle, and a special destructor to prevent deallocation while the thread is executing.
    1520 (The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitor}.)
    1521 The difference between the coroutine and thread is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates the coroutine's stack and starts running the coroutine main on the stack;
    1522 whereas, a thread is scheduling for execution in @main@ immediately after its constructor is run.
    1523 No return value or additional parameters are necessary for this function because the @thread@ type allows an arbitrary number of interface functions with corresponding arbitrary typed input/output values.
    1524 
    1525 
    15261217\section{Mutual Exclusion / Synchronization}
    1527 \label{s:MutualExclusionSynchronization}
    1528 
    1529 Unrestricted nondeterminism is meaningless as there is no way to know when the result is completed without synchronization.
    1530 To produce meaningful execution requires clawing back some determinism using mutual exclusion and synchronization, where mutual exclusion provides access control for threads using shared data, and synchronization is a timing relationship among threads~\cite[\S~4]{Buhr05a}.
    1531 Some concurrent systems eliminate mutable shared-state by switching to stateless communication like message passing~\cite{Thoth,Harmony,V-Kernel,MPI} (Erlang, MPI), channels~\cite{CSP} (CSP,Go), actors~\cite{Akka} (Akka, Scala), or functional techniques (Haskell).
    1532 However, these approaches introduce a new communication mechanism for concurrency different from the standard communication using function call/return.
    1533 Hence, a programmer must learn and manipulate two sets of design/programming patterns.
     1218
     1219Uncontrolled non-deterministic execution is meaningless.
     1220To reestablish meaningful execution requires mechanisms to reintroduce determinism (\ie restrict non-determinism), called mutual exclusion and synchronization, where mutual exclusion is an access-control mechanism on data shared by threads, and synchronization is a timing relationship among threads~\cite[\S~4]{Buhr05a}.
     1221Since many deterministic challenges appear with the use of mutable shared state, some languages/libraries disallow it, \eg Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka~\cite{Akka} (Scala).
     1222In these paradigms, interaction among concurrent objects is performed by stateless message-passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms closely relate to networking concepts (\eg channels~\cite{CSP,Go}).
     1223However, in call/return-based languages, these approaches force a clear distinction (\ie introduce a new programming paradigm) between regular and concurrent computation (\ie routine call versus message passing).
     1224Hence, a programmer must learn and manipulate two sets of design patterns.
    15341225While this distinction can be hidden away in library code, effective use of the library still has to take both paradigms into account.
    1535 In contrast, approaches based on stateful models more closely resemble the standard call/return programming model, resulting in a single programming paradigm.
    1536 
    1537 At the lowest level, concurrent control is implemented by atomic operations, upon which different kinds of locking mechanisms are constructed, \eg semaphores~\cite{Dijkstra68b}, barriers, and path expressions~\cite{Campbell74}.
     1226In contrast, approaches based on statefull models more closely resemble the standard call/return programming-model, resulting in a single programming paradigm.
     1227
     1228At the lowest level, concurrent control is implemented by atomic operations, upon which different kinds of locks mechanism are constructed, \eg semaphores~\cite{Dijkstra68b}, barriers, and path expressions~\cite{Campbell74}.
    15381229However, for productivity it is always desirable to use the highest-level construct that provides the necessary efficiency~\cite{Hochstein05}.
    15391230A newer approach for restricting non-determinism is transactional memory~\cite{Herlihy93}.
    1540 While this approach is pursued in hardware~\cite{Nakaike15} and system languages, like \CC~\cite{Cpp-Transactions}, the performance and feature set is still too restrictive to be the main concurrency paradigm for system languages, which is why it is rejected as the core paradigm for concurrency in \CFA.
     1231While this approach is pursued in hardware~\cite{Nakaike15} and system languages, like \CC~\cite{Cpp-Transactions}, the performance and feature set is still too restrictive to be the main concurrency paradigm for system languages, which is why it was rejected as the core paradigm for concurrency in \CFA.
    15411232
    15421233One of the most natural, elegant, and efficient mechanisms for mutual exclusion and synchronization for shared-memory systems is the \emph{monitor}.
    1543 First proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}, many concurrent programming languages provide monitors as an explicit language construct: \eg Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}.
     1234First proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}, many concurrent programming-languages provide monitors as an explicit language construct: \eg Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}.
    15441235In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as mutex locks or semaphores to simulate monitors.
    1545 For these reasons, \CFA selected monitors as the core high-level concurrency construct, upon which higher-level approaches can be easily constructed.
     1236For these reasons, \CFA selected monitors as the core high-level concurrency-construct, upon which higher-level approaches can be easily constructed.
    15461237
    15471238
    15481239\subsection{Mutual Exclusion}
    15491240
    1550 A group of instructions manipulating a specific instance of shared data that must be performed atomically is called a \newterm{critical section}~\cite{Dijkstra65}, which is enforced by \newterm{simple mutual-exclusion}.
    1551 The generalization is called a \newterm{group critical-section}~\cite{Joung00}, where multiple tasks with the same session use the resource simultaneously and different sessions are segregated, which is enforced by \newterm{complex mutual-exclusion} providing the correct kind and number of threads using a group critical-section.
    1552 The readers/writer problem~\cite{Courtois71} is an instance of a group critical-section, where readers share a session but writers have a unique session.
     1241A group of instructions manipulating a specific instance of shared data that must be performed atomically is called an (individual) \newterm{critical-section}~\cite{Dijkstra65}.
     1242The generalization is called a \newterm{group critical-section}~\cite{Joung00}, where multiple tasks with the same session may use the resource simultaneously, but different sessions may not use the resource simultaneously.
     1243The readers/writer problem~\cite{Courtois71} is an instance of a group critical-section, where readers have the same session and all writers have a unique session.
     1244\newterm{Mutual exclusion} enforces that the correct kind and number of threads are using a critical section.
    15531245
    15541246However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use.
    15551247Methods range from low-level locks, which are fast and flexible but require significant attention for correctness, to higher-level concurrency techniques, which sacrifice some performance to improve ease of use.
    1556 Ease of use comes by either guaranteeing some problems cannot occur, \eg deadlock free, or by offering a more explicit coupling between shared data and critical section.
    1557 For example, the \CC @std::atomic<T>@ offers an easy way to express mutual-exclusion on a restricted set of operations, \eg reading/writing, for numerical types.
     1248Ease of use comes by either guaranteeing some problems cannot occur (\eg deadlock free), or by offering a more explicit coupling between shared data and critical section.
     1249For example, the \CC @std::atomic<T>@ offers an easy way to express mutual-exclusion on a restricted set of operations (\eg reading/writing) for numerical types.
    15581250However, a significant challenge with locks is composability because it takes careful organization for multiple locks to be used while preventing deadlock.
    15591251Easing composability is another feature higher-level mutual-exclusion mechanisms can offer.
     
    15641256Synchronization enforces relative ordering of execution, and synchronization tools provide numerous mechanisms to establish these timing relationships.
    15651257Low-level synchronization primitives offer good performance and flexibility at the cost of ease of use;
    1566 higher-level mechanisms often simplify usage by adding better coupling between synchronization and data, \eg receive-specific versus receive-any thread in message passing or offering specialized solutions, \eg barrier lock.
    1567 Often synchronization is used to order access to a critical section, \eg ensuring a waiting writer thread enters the critical section before a calling reader thread.
    1568 If the calling reader is scheduled before the waiting writer, the reader has barged.
     1258higher-level mechanisms often simplify usage by adding better coupling between synchronization and data (\eg message passing), or offering a simpler solution to otherwise involved challenges, \eg barrier lock.
     1259Often synchronization is used to order access to a critical section, \eg ensuring a reader thread is the next kind of thread to enter a critical section.
     1260If a writer thread is scheduled for next access, but another reader thread acquires the critical section first, that reader has \newterm{barged}.
    15691261Barging can result in staleness/freshness problems, where a reader barges ahead of a writer and reads temporally stale data, or a writer barges ahead of another writer overwriting data with a fresh value preventing the previous value from ever being read (lost computation).
    1570 Preventing or detecting barging is an involved challenge with low-level locks, which is made easier through higher-level constructs.
    1571 This challenge is often split into two different approaches: barging avoidance and prevention.
    1572 Algorithms that unconditionally releasing a lock for competing threads to acquire use barging avoidance during synchronization to force a barging thread to wait;
    1573 algorithms that conditionally hold locks during synchronization, \eg baton-passing~\cite{Andrews89}, prevent barging completely.
    1574 
    1575 
    1576 \section{Monitor}
    1577 \label{s:Monitor}
    1578 
    1579 A \textbf{monitor} is a set of functions that ensure mutual exclusion when accessing shared state.
    1580 More precisely, a monitor is a programming technique that implicitly binds mutual exclusion to static function scope, as opposed to locks, where mutual-exclusion is defined by acquire/release calls, independent of lexical context (analogous to block and heap storage allocation).
    1581 Restricting acquire/release points eases programming, comprehension, and maintenance, at a slight cost in flexibility and efficiency.
    1582 \CFA uses a custom @monitor@ type and leverages declaration semantics (deallocation) to protect active or waiting threads in a monitor.
    1583 
    1584 The following is a \CFA monitor implementation of an atomic counter.
    1585 \begin{cfa}[morekeywords=nomutex]
    1586 `monitor` Aint { int cnt; }; $\C[4.25in]{// atomic integer counter}$
    1587 int ++?( Aint & `mutex`$\(_{opt}\)$ this ) with( this ) { return ++cnt; } $\C{// increment}$
    1588 int ?=?( Aint & `mutex`$\(_{opt}\)$ lhs, int rhs ) with( lhs ) { cnt = rhs; } $\C{// conversions with int}\CRT$
    1589 int ?=?( int & lhs, Aint & `mutex`$\(_{opt}\)$ rhs ) with( rhs ) { lhs = cnt; }
    1590 \end{cfa}
    1591 % The @Aint@ constructor, @?{}@, uses the \lstinline[morekeywords=nomutex]@nomutex@ qualifier indicating mutual exclusion is unnecessary during construction because an object is inaccessible (private) until after it is initialized.
    1592 % (While a constructor may publish its address into a global variable, doing so generates a race-condition.)
    1593 The prefix increment operation, @++?@, is normally @mutex@, indicating mutual exclusion is necessary during function execution, to protect the incrementing from race conditions, unless there is an atomic increment instruction for the implementation type.
    1594 The assignment operators provide bidirectional conversion between an atomic and normal integer without accessing field @cnt@;
    1595 these operations only need @mutex@, if reading/writing the implementation type is not atomic.
    1596 The atomic counter is used without any explicit mutual-exclusion and provides thread-safe semantics, which is similar to the \CC template @std::atomic@.
    1597 \begin{cfa}
    1598 int i = 0, j = 0, k = 5;
    1599 Aint x = { 0 }, y = { 0 }, z = { 5 }; $\C{// no mutex required}$
    1600 ++x; ++y; ++z; $\C{// safe increment by multiple threads}$
    1601 x = 2; y = i; z = k; $\C{// conversions}$
    1602 i = x; j = y; k = z;
    1603 \end{cfa}
    1604 
    1605 \CFA monitors have \newterm{multi-acquire} semantics so the thread in the monitor may acquire it multiple times without deadlock, allowing recursion and calling other interface functions.
    1606 \begin{cfa}
    1607 monitor M { ... } m;
    1608 void foo( M & mutex m ) { ... } $\C{// acquire mutual exclusion}$
    1609 void bar( M & mutex m ) { $\C{// acquire mutual exclusion}$
    1610         ... `bar( m );` ... `foo( m );` ... $\C{// reacquire mutual exclusion}$
    1611 }
    1612 \end{cfa}
    1613 \CFA monitors also ensure the monitor lock is released regardless of how an acquiring function ends (normal or exceptional), and returning a shared variable is safe via copying before the lock is released.
    1614 Similar safety is offered by \emph{explicit} mechanisms like \CC RAII;
    1615 monitor \emph{implicit} safety ensures no programmer usage errors.
    1616 Furthermore, RAII mechanisms cannot handle complex synchronization within a monitor, where the monitor lock may not be released on function exit because it is passed to an unblocking thread;
    1617 RAII is purely a mutual-exclusion mechanism (see Section~\ref{s:Scheduling}).
    1618 
    1619 
    1620 \subsection{Monitor Implementation}
    1621 
    1622 For the same design reasons, \CFA provides a custom @monitor@ type and a @trait@ to enforce and restrict the monitor-interface functions.
    1623 \begin{cquote}
    1624 \begin{tabular}{@{}c@{\hspace{3\parindentlnth}}c@{}}
    1625 \begin{cfa}
    1626 monitor M {
    1627         ... // shared data
    1628 };
    1629 
    1630 \end{cfa}
    1631 &
     1262Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs.
     1263This challenge is often split into two different approaches: barging avoidance and barging prevention.
     1264Algorithms that allow a barger, but divert it until later using current synchronization state (flags), are avoiding the barger;
     1265algorithms that preclude a barger from entering during synchronization in the critical section prevent barging completely.
     1266Techniques like baton-pass locks~\cite{Andrews89} between threads instead of unconditionally releasing locks is an example of barging prevention.
     1267
     1268
     1269\section{Monitors}
     1270\label{s:Monitors}
     1271
     1272A \textbf{monitor} is a set of routines that ensure mutual exclusion when accessing shared state.
     1273More precisely, a monitor is a programming technique that binds mutual exclusion to routine scope, as opposed to locks, where mutual-exclusion is defined by acquire/release calls, independent of lexical context (analogous to block and heap storage allocation).
     1274The strong association with the call/return paradigm eases programmability, readability and maintainability, at a slight cost in flexibility and efficiency.
     1275
     1276Note, like coroutines/threads, both locks and monitors require an abstract handle to reference them, because at their core, both mechanisms are manipulating non-copyable shared state.
     1277Copying a lock is insecure because it is possible to copy an open lock and then use the open copy when the original lock is closed to simultaneously access the shared data.
     1278Copying a monitor is secure because both the lock and shared data are copies, but copying the shared data is meaningless because it no longer represents a unique entity.
     1279As for coroutines/tasks, a non-copyable (@dtype@) trait is used to capture this requirement, so all locks/monitors must be passed by reference (pointer).
    16321280\begin{cfa}
    16331281trait is_monitor( `dtype` T ) {
     
    16361284};
    16371285\end{cfa}
    1638 \end{tabular}
    1639 \end{cquote}
    1640 The @dtype@ property prevents \emph{implicit} copy operations and the @is_monitor@ trait provides no \emph{explicit} copy operations, so monitors must be passed by reference (pointer).
    1641 % Copying a lock is insecure because it is possible to copy an open lock and then use the open copy when the original lock is closed to simultaneously access the shared data.
    1642 % Copying a monitor is secure because both the lock and shared data are copies, but copying the shared data is meaningless because it no longer represents a unique entity.
    1643 Similarly, the function definitions ensures there is a mechanism to get (read) the monitor descriptor from its handle, and a special destructor to prevent deallocation if a thread using the shared data.
    1644 The custom monitor type also inserts any locks needed to implement the mutual exclusion semantics.
    16451286
    16461287
     
    16481289\label{s:MutexAcquisition}
    16491290
    1650 While the monitor lock provides mutual exclusion for shared data, there are implementation options for when and where the locking/unlocking occurs.
     1291While correctness implicitly implies a monitor's mutual exclusion is acquired and released, there are implementation options about when and where the locking/unlocking occurs.
    16511292(Much of this discussion also applies to basic locks.)
    1652 For example, a monitor may be passed through multiple helper functions before it is necessary to acquire the monitor's mutual exclusion.
    1653 
    1654 The benefit of mandatory monitor qualifiers is self-documentation, but requiring both @mutex@ and \lstinline[morekeywords=nomutex]@nomutex@ for all monitor parameters is redundant.
    1655 Instead, the semantics has one qualifier as the default and the other required.
    1656 For example, make the safe @mutex@ qualifier the default because assuming \lstinline[morekeywords=nomutex]@nomutex@ may cause subtle errors.
    1657 Alternatively, make the unsafe \lstinline[morekeywords=nomutex]@nomutex@ qualifier the default because it is the \emph{normal} parameter semantics while @mutex@ parameters are rare.
     1293For example, a monitor may need to be passed through multiple helper routines before it becomes necessary to acquire the monitor mutual-exclusion.
     1294\begin{cfa}[morekeywords=nomutex]
     1295monitor Aint { int cnt; };                                      $\C{// atomic integer counter}$
     1296void ?{}( Aint & `nomutex` this ) with( this ) { cnt = 0; } $\C{// constructor}$
     1297int ?=?( Aint & `mutex`$\(_{opt}\)$ lhs, int rhs ) with( lhs ) { cnt = rhs; } $\C{// conversions}$
     1298void ?{}( int & this, Aint & `mutex`$\(_{opt}\)$ v ) { this = v.cnt; }
     1299int ?=?( int & lhs, Aint & `mutex`$\(_{opt}\)$ rhs ) with( rhs ) { lhs = cnt; }
     1300int ++?( Aint & `mutex`$\(_{opt}\)$ this ) with( this ) { return ++cnt; } $\C{// increment}$
     1301\end{cfa}
     1302The @Aint@ constructor, @?{}@, uses the \lstinline[morekeywords=nomutex]@nomutex@ qualifier indicating mutual exclusion is unnecessary during construction because an object is inaccessible (private) until after it is initialized.
     1303(While a constructor may publish its address into a global variable, doing so generates a race-condition.)
     1304The conversion operators for initializing and assigning with a normal integer only need @mutex@, if reading/writing the implementation type is not atomic.
     1305Finally, the prefix increment operato, @++?@, is normally @mutex@ to protect the incrementing from race conditions, unless there is an atomic increment instruction for the implementation type.
     1306
     1307The atomic counter is used without any explicit mutual-exclusion and provides thread-safe semantics, which is similar to the \CC template @std::atomic@.
     1308\begin{cfa}
     1309Aint x, y, z;
     1310++x; ++y; ++z;                                                          $\C{// safe increment by multiple threads}$
     1311x = 2; y = 2; z = 2;                                            $\C{// conversions}$
     1312int i = x, j = y, k = z;
     1313i = x; j = y; k = z;
     1314\end{cfa}
     1315
     1316For maximum usability, monitors have \newterm{multi-acquire} semantics allowing a thread to acquire it multiple times without deadlock.
     1317For example, atomically printing the contents of a binary tree:
     1318\begin{cfa}
     1319monitor Tree {
     1320        Tree * left, right;
     1321        // value
     1322};
     1323void print( Tree & mutex tree ) {                       $\C{// prefix traversal}$
     1324        // write value
     1325        print( tree->left );                                    $\C{// multiply acquire monitor lock on each recursion}$
     1326        print( tree->right );
     1327}
     1328\end{cfa}
     1329
     1330Mandatory monitor qualifiers have the benefit of being self-documented, but requiring both @mutex@ and \lstinline[morekeywords=nomutex]@nomutex@ for all monitor parameter is redundant.
     1331Instead, one of qualifier semantics can be the default, and the other required.
     1332For example, assume the safe @mutex@ option for a monitor parameter because assuming \lstinline[morekeywords=nomutex]@nomutex@ may cause subtle errors.
     1333On the other hand, assuming \lstinline[morekeywords=nomutex]@nomutex@ is the \emph{normal} parameter behaviour, stating explicitly ``this parameter is not special''.
    16581334Providing a default qualifier implies knowing whether a parameter is a monitor.
    1659 Since \CFA relies heavily on traits as an abstraction mechanism, types can coincidentally match the monitor trait but not be a monitor, similar to inheritance where a shape and playing card can both be drawable.
     1335Since \CFA relies heavily on traits as an abstraction mechanism, the distinction between a type that is a monitor and a type that looks like a monitor can become blurred.
    16601336For this reason, \CFA requires programmers to identify the kind of parameter with the @mutex@ keyword and uses no keyword to mean \lstinline[morekeywords=nomutex]@nomutex@.
    16611337
    16621338The next semantic decision is establishing which parameter \emph{types} may be qualified with @mutex@.
    1663 The following has monitor parameter types that are composed of multiple objects.
     1339Given:
    16641340\begin{cfa}
    16651341monitor M { ... }
    1666 int f1( M & mutex m ); $\C{// single parameter object}$
    1667 int f2( M * mutex m ); $\C{// single or multiple parameter object}$
    1668 int f3( M * mutex m[$\,$] ); $\C{// multiple parameter object}$
    1669 int f4( stack( M * ) & mutex m ); $\C{// multiple parameters object}$
    1670 \end{cfa}
    1671 Function @f1@ has a single parameter object, while @f2@'s indirection could be a single or multi-element array, where static array size is often unknown in C.
    1672 Function @f3@ has a multiple object matrix, and @f4@ a multiple object data structure.
    1673 While shown shortly, multiple object acquisition is possible, but the number of objects must be statically known.
    1674 Therefore, \CFA only acquires one monitor per parameter with at most one level of indirection, excluding pointers as it is impossible to statically determine the size.
    1675 
    1676 For object-oriented monitors, \eg Java, calling a mutex member \emph{implicitly} acquires mutual exclusion of the receiver object, @`rec`.foo(...)@.
    1677 \CFA has no receiver, and hence, the explicit @mutex@ qualifier is used to specify which objects acquire mutual exclusion.
    1678 A positive consequence of this design decision is the ability to support multi-monitor functions,\footnote{
    1679 While object-oriented monitors can be extended with a mutex qualifier for multiple-monitor members, no prior example of this feature could be found.}
    1680 called \newterm{bulk acquire}.
    1681 \CFA guarantees acquisition order is consistent across calls to @mutex@ functions using the same monitors as arguments, so acquiring multiple monitors is safe from deadlock.
    1682 Figure~\ref{f:BankTransfer} shows a trivial solution to the bank transfer problem~\cite{BankTransfer}, where two resources must be locked simultaneously, using \CFA monitors with implicit locking and \CC with explicit locking.
    1683 A \CFA programmer only has to manage when to acquire mutual exclusion;
    1684 a \CC programmer must select the correct lock and acquisition mechanism from a panoply of locking options.
    1685 Making good choices for common cases in \CFA simplifies the programming experience and enhances safety.
    1686 
    1687 \begin{figure}
    1688 \centering
    1689 \begin{lrbox}{\myboxA}
    1690 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1691 monitor BankAccount {
    1692 
    1693         int balance;
    1694 } b1 = { 0 }, b2 = { 0 };
    1695 void deposit( BankAccount & `mutex` b,
    1696                         int deposit ) with(b) {
    1697         balance += deposit;
    1698 }
    1699 void transfer( BankAccount & `mutex` my,
    1700         BankAccount & `mutex` your, int me2you ) {
    1701 
    1702         deposit( my, -me2you ); // debit
    1703         deposit( your, me2you ); // credit
    1704 }
    1705 `thread` Person { BankAccount & b1, & b2; };
    1706 void main( Person & person ) with(person) {
    1707         for ( 10_000_000 ) {
    1708                 if ( random() % 3 ) deposit( b1, 3 );
    1709                 if ( random() % 3 ) transfer( b1, b2, 7 );
    1710         }
    1711 }
    1712 int main() {
    1713         `Person p1 = { b1, b2 }, p2 = { b2, b1 };`
    1714 
    1715 } // wait for threads to complete
    1716 \end{cfa}
    1717 \end{lrbox}
    1718 
    1719 \begin{lrbox}{\myboxB}
    1720 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1721 struct BankAccount {
    1722         `recursive_mutex m;`
    1723         int balance = 0;
    1724 } b1, b2;
    1725 void deposit( BankAccount & b, int deposit ) {
    1726         `scoped_lock lock( b.m );`
    1727         b.balance += deposit;
    1728 }
    1729 void transfer( BankAccount & my,
    1730                         BankAccount & your, int me2you ) {
    1731         `scoped_lock lock( my.m, your.m );`
    1732         deposit( my, -me2you ); // debit
    1733         deposit( your, me2you ); // credit
    1734 }
    1735 
    1736 void person( BankAccount & b1, BankAccount & b2 ) {
    1737         for ( int i = 0; i < 10$'$000$'$000; i += 1 ) {
    1738                 if ( random() % 3 ) deposit( b1, 3 );
    1739                 if ( random() % 3 ) transfer( b1, b2, 7 );
    1740         }
    1741 }
    1742 int main() {
    1743         `thread p1(person, ref(b1), ref(b2)), p2(person, ref(b2), ref(b1));`
    1744         `p1.join(); p2.join();`
    1745 }
    1746 \end{cfa}
    1747 \end{lrbox}
    1748 
    1749 \subfloat[\CFA]{\label{f:CFABank}\usebox\myboxA}
    1750 \hspace{3pt}
    1751 \vrule
    1752 \hspace{3pt}
    1753 \subfloat[\CC]{\label{f:C++Bank}\usebox\myboxB}
    1754 \hspace{3pt}
    1755 \caption{Bank transfer problem}
    1756 \label{f:BankTransfer}
    1757 \end{figure}
    1758 
    1759 Users can still force the acquiring order by using @mutex@/\lstinline[morekeywords=nomutex]@nomutex@.
    1760 \begin{cfa}
    1761 void foo( M & mutex m1, M & mutex m2 ); $\C{// acquire m1 and m2}$
     1342int f1( M & mutex m );
     1343int f2( M * mutex m );
     1344int f3( M * mutex m[] );
     1345int f4( stack( M * ) & mutex m );
     1346\end{cfa}
     1347the issue is that some of these parameter types are composed of multiple objects.
     1348For @f1@, there is only a single parameter object.
     1349Adding indirection in @f2@ still identifies a single object.
     1350However, the matrix in @f3@ introduces multiple objects.
     1351While shown shortly, multiple acquisition is possible;
     1352however array lengths are often unknown in C.
     1353This issue is exacerbated in @f4@, where the data structure must be safely traversed to acquire all of its elements.
     1354
     1355To make the issue tractable, \CFA only acquires one monitor per parameter with at most one level of indirection.
     1356However, the C type-system has an ambiguity with respects to arrays.
     1357Is the argument for @f2@ a single object or an array of objects?
     1358If it is an array, only the first element of the array is acquired, which seems unsafe;
     1359hence, @mutex@ is disallowed for array parameters.
     1360\begin{cfa}
     1361int f1( M & mutex m );                                          $\C{// allowed: recommended case}$
     1362int f2( M * mutex m );                                          $\C{// disallowed: could be an array}$
     1363int f3( M mutex m[$\,$] );                                      $\C{// disallowed: array length unknown}$
     1364int f4( M ** mutex m );                                         $\C{// disallowed: could be an array}$
     1365int f5( M * mutex m[$\,$] );                            $\C{// disallowed: array length unknown}$
     1366\end{cfa}
     1367% Note, not all array routines have distinct types: @f2@ and @f3@ have the same type, as do @f4@ and @f5@.
     1368% However, even if the code generation could tell the difference, the extra information is still not sufficient to extend meaningfully the monitor call semantic.
     1369
     1370For object-oriented monitors, calling a mutex member \emph{implicitly} acquires mutual exclusion of the receiver object, @`rec`.foo(...)@.
     1371\CFA has no receiver, and hence, must use an explicit mechanism to specify which object has mutual exclusion acquired.
     1372A positive consequence of this design decision is the ability to support multi-monitor routines.
     1373\begin{cfa}
     1374int f( M & mutex x, M & mutex y );              $\C{// multiple monitor parameter of any type}$
     1375M m1, m2;
     1376f( m1, m2 );
     1377\end{cfa}
     1378(While object-oriented monitors can be extended with a mutex qualifier for multiple-monitor members, no prior example of this feature could be found.)
     1379In practice, writing multi-locking routines that do not deadlocks is tricky.
     1380Having language support for such a feature is therefore a significant asset for \CFA.
     1381
     1382The capability to acquire multiple locks before entering a critical section is called \newterm{bulk acquire}.
     1383In previous example, \CFA guarantees the order of acquisition is consistent across calls to different routines using the same monitors as arguments.
     1384This consistent ordering means acquiring multiple monitors is safe from deadlock.
     1385However, users can force the acquiring order.
     1386For example, notice the use of @mutex@/\lstinline[morekeywords=nomutex]@nomutex@ and how this affects the acquiring order:
     1387\begin{cfa}
     1388void foo( M & mutex m1, M & mutex m2 );         $\C{// acquire m1 and m2}$
    17621389void bar( M & mutex m1, M & /* nomutex */ m2 ) { $\C{// acquire m1}$
    1763         ... foo( m1, m2 ); ... $\C{// acquire m2}$
     1390        ... foo( m1, m2 ); ...                                  $\C{// acquire m2}$
    17641391}
    17651392void baz( M & /* nomutex */ m1, M & mutex m2 ) { $\C{// acquire m2}$
    1766         ... foo( m1, m2 ); ... $\C{// acquire m1}$
    1767 }
    1768 \end{cfa}
    1769 The bulk-acquire semantics allow @bar@ or @baz@ to acquire a monitor lock and reacquire it in @foo@.
    1770 The calls to @bar@ and @baz@ acquired the monitors in opposite order, possibly resulting in deadlock.
    1771 However, this case is the simplest instance of the \emph{nested-monitor problem}~\cite{Lister77}, where monitors are acquired in sequence versus bulk.
    1772 Detecting the nested-monitor problem requires dynamic tracking of monitor calls, and dealing with it requires rollback semantics~\cite{Dice10}.
    1773 \CFA does not deal with this fundamental problem.
    1774 
    1775 Finally, like Java, \CFA offers an alternative @mutex@ statement to reduce refactoring and naming.
     1393        ... foo( m1, m2 ); ...                                  $\C{// acquire m1}$
     1394}
     1395\end{cfa}
     1396The multi-acquire semantics allows @bar@ or @baz@ to acquire a monitor lock and reacquire it in @foo@.
     1397In the calls to @bar@ and @baz@, the monitors are acquired in opposite order.
     1398
     1399However, such use leads to lock acquiring order problems resulting in deadlock~\cite{Lister77}, where detecting it requires dynamically tracking of monitor calls, and dealing with it requires implement rollback semantics~\cite{Dice10}.
     1400In \CFA, safety is guaranteed by using bulk acquire of all monitors to shared objects, whereas other monitor systems provide no aid.
     1401While \CFA provides only a partial solution, the \CFA partial solution handles many useful cases.
     1402\begin{cfa}
     1403monitor Bank { ... };
     1404void deposit( Bank & `mutex` b, int deposit );
     1405void transfer( Bank & `mutex` mybank, Bank & `mutex` yourbank, int me2you) {
     1406        deposit( mybank, `-`me2you );                   $\C{// debit}$
     1407        deposit( yourbank, me2you );                    $\C{// credit}$
     1408}
     1409\end{cfa}
     1410This example shows a trivial solution to the bank-account transfer problem~\cite{BankTransfer}.
     1411Without multi- and bulk acquire, the solution to this problem requires careful engineering.
     1412
     1413
     1414\subsection{\protect\lstinline|mutex| statement} \label{mutex-stmt}
     1415
     1416The monitor call-semantics associate all locking semantics to routines.
     1417Like Java, \CFA offers an alternative @mutex@ statement to reduce refactoring and naming.
    17761418\begin{cquote}
    1777 \renewcommand{\arraystretch}{0.0}
    1778 \begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
    1779 \multicolumn{1}{c}{\textbf{\lstinline@mutex@ call}} & \multicolumn{1}{c}{\lstinline@mutex@ \textbf{statement}} \\
    1780 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1781 monitor M { ... };
     1419\begin{tabular}{@{}c|@{\hspace{\parindentlnth}}c@{}}
     1420routine call & @mutex@ statement \\
     1421\begin{cfa}
     1422monitor M {};
    17821423void foo( M & mutex m1, M & mutex m2 ) {
    17831424        // critical section
     
    17881429\end{cfa}
    17891430&
    1790 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1431\begin{cfa}
    17911432
    17921433void bar( M & m1, M & m2 ) {
     
    18011442
    18021443
    1803 \subsection{Scheduling}
    1804 \label{s:Scheduling}
    1805 
    1806 % There are many aspects of scheduling in a concurrency system, all related to resource utilization by waiting threads, \ie which thread gets the resource next.
    1807 % Different forms of scheduling include access to processors by threads (see Section~\ref{s:RuntimeStructureCluster}), another is access to a shared resource by a lock or monitor.
    1808 This section discusses monitor scheduling for waiting threads eligible for entry, \ie which thread gets the shared resource next. (See Section~\ref{s:RuntimeStructureCluster} for scheduling threads on virtual processors.)
    1809 While monitor mutual-exclusion provides safe access to shared data, the monitor data may indicate that a thread accessing it cannot proceed, \eg a bounded buffer may be full/empty so produce/consumer threads must block.
     1444\section{Internal Scheduling}
     1445\label{s:InternalScheduling}
     1446
     1447While monitor mutual-exclusion provides safe access to shared data, the monitor data may indicate that a thread accessing it cannot proceed, \eg a bounded buffer, Figure~\ref{f:GenericBoundedBuffer}, may be full/empty so produce/consumer threads must block.
    18101448Leaving the monitor and trying again (busy waiting) is impractical for high-level programming.
    1811 Monitors eliminate busy waiting by providing synchronization to schedule threads needing access to the shared data, where threads block versus spinning.
    1812 Synchronization is generally achieved with internal~\cite{Hoare74} or external~\cite[\S~2.9.2]{uC++} scheduling.
     1449Monitors eliminate busy waiting by providing internal synchronization to schedule threads needing access to the shared data, where the synchronization is blocking (threads are parked) versus spinning.
     1450The synchronization is generally achieved with internal~\cite{Hoare74} or external~\cite[\S~2.9.2]{uC++} scheduling, where \newterm{scheduling} is defined as indicating which thread acquires the critical section next.
    18131451\newterm{Internal scheduling} is characterized by each thread entering the monitor and making an individual decision about proceeding or blocking, while \newterm{external scheduling} is characterized by an entering thread making a decision about proceeding for itself and on behalf of other threads attempting entry.
    1814 Finally, \CFA monitors do not allow calling threads to barge ahead of signalled threads, which simplifies synchronization among threads in the monitor and increases correctness.
    1815 If barging is allowed, synchronization between a signaller and signallee is difficult, often requiring additional flags and multiple unblock/block cycles.
    1816 In fact, signals-as-hints is completely opposite from that proposed by Hoare in the seminal paper on monitors~\cite[p.~550]{Hoare74}.
    1817 % \begin{cquote}
    1818 % However, we decree that a signal operation be followed immediately by resumption of a waiting program, without possibility of an intervening procedure call from yet a third program.
    1819 % It is only in this way that a waiting program has an absolute guarantee that it can acquire the resource just released by the signalling program without any danger that a third program will interpose a monitor entry and seize the resource instead.~\cite[p.~550]{Hoare74}
    1820 % \end{cquote}
    1821 Furthermore, \CFA concurrency has no spurious wakeup~\cite[\S~9]{Buhr05a}, which eliminates an implicit form of self barging.
    1822 Hence, a \CFA @wait@ statement is not enclosed in a @while@ loop retesting a blocking predicate, which can cause thread starvation due to barging.
    1823 
    1824 Figure~\ref{f:MonitorScheduling} shows general internal/external scheduling (for the bounded-buffer example in Figure~\ref{f:InternalExternalScheduling}).
    1825 External calling threads block on the calling queue, if the monitor is occupied, otherwise they enter in FIFO order.
    1826 Internal threads block on condition queues via @wait@ and reenter from the condition in FIFO order.
    1827 Alternatively, internal threads block on urgent from the @signal_block@ or @waitfor@, and reenter implicitly when the monitor becomes empty, \ie, the thread in the monitor exits or waits.
    1828 
    1829 There are three signalling mechanisms to unblock waiting threads to enter the monitor.
    1830 Note, signalling cannot have the signaller and signalled thread in the monitor simultaneously because of the mutual exclusion, so either the signaller or signallee can proceed.
    1831 For internal scheduling, threads are unblocked from condition queues using @signal@, where the signallee is moved to urgent and the signaller continues (solid line).
    1832 Multiple signals move multiple signallees to urgent until the condition is empty.
    1833 When the signaller exits or waits, a thread blocked on urgent is processed before calling threads to prevent barging.
    1834 (Java conceptually moves the signalled thread to the calling queue, and hence, allows barging.)
    1835 The alternative unblock is in the opposite order using @signal_block@, where the signaller is moved to urgent and the signallee continues (dashed line), and is implicitly unblocked from urgent when the signallee exits or waits.
    1836 
    1837 For external scheduling, the condition queues are not used;
    1838 instead threads are unblocked directly from the calling queue using @waitfor@ based on function names requesting mutual exclusion.
    1839 (The linear search through the calling queue to locate a particular call can be reduced to $O(1)$.)
    1840 The @waitfor@ has the same semantics as @signal_block@, where the signalled thread executes before the signallee, which waits on urgent.
    1841 Executing multiple @waitfor@s from different signalled functions causes the calling threads to move to urgent.
    1842 External scheduling requires urgent to be a stack, because the signaller expects to execute immediately after the specified monitor call has exited or waited.
    1843 Internal scheduling behaves the same for an urgent stack or queue, except for multiple signalling, where the threads unblock from urgent in reverse order from signalling.
    1844 If the restart order is important, multiple signalling by a signal thread can be transformed into daisy-chain signalling among threads, where each thread signals the next thread.
    1845 We tried both a stack for @waitfor@ and queue for signalling, but that resulted in complex semantics about which thread enters next.
    1846 Hence, \CFA uses a single urgent stack to correctly handle @waitfor@ and adequately support both forms of signalling.
    1847 
    1848 \begin{figure}
    1849 \centering
    1850 % \subfloat[Scheduling Statements] {
    1851 % \label{fig:SchedulingStatements}
    1852 % {\resizebox{0.45\textwidth}{!}{\input{CondSigWait.pstex_t}}}
    1853 \input{CondSigWait.pstex_t}
    1854 % }% subfloat
    1855 % \quad
    1856 % \subfloat[Bulk acquire monitor] {
    1857 % \label{fig:BulkMonitor}
    1858 % {\resizebox{0.45\textwidth}{!}{\input{ext_monitor.pstex_t}}}
    1859 % }% subfloat
    1860 \caption{Monitor Scheduling}
    1861 \label{f:MonitorScheduling}
    1862 \end{figure}
    1863 
    1864 Figure~\ref{f:BBInt} shows a \CFA generic bounded-buffer with internal scheduling, where producers/consumers enter the monitor, detect the buffer is full/empty, and block on an appropriate condition variable, @full@/@empty@.
    1865 The @wait@ function atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the function's parameter list.
    1866 The appropriate condition variable is signalled to unblock an opposite kind of thread after an element is inserted/removed from the buffer.
    1867 Signalling is unconditional, because signalling an empty condition variable does nothing.
    1868 It is common to declare condition variables as monitor fields to prevent shared access, hence no locking is required for access as the conditions are protected by the monitor lock.
    1869 In \CFA, a condition variable can be created/stored independently.
    1870 % To still prevent expensive locking on access, a condition variable is tied to a \emph{group} of monitors on first use, called \newterm{branding}, resulting in a low-cost boolean test to detect sharing from other monitors.
    1871 
    1872 % Signalling semantics cannot have the signaller and signalled thread in the monitor simultaneously, which means:
    1873 % \begin{enumerate}
    1874 % \item
    1875 % The signalling thread returns immediately and the signalled thread continues.
    1876 % \item
    1877 % The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait).
    1878 % \item
    1879 % The signalling thread blocks but is marked for urgent unblocking at the next scheduling point and the signalled thread continues.
    1880 % \end{enumerate}
    1881 % The first approach is too restrictive, as it precludes solving a reasonable class of problems, \eg dating service (see Figure~\ref{f:DatingService}).
    1882 % \CFA supports the next two semantics as both are useful.
     1452
     1453Figure~\ref{f:BBInt} shows a \CFA bounded-buffer with internal scheduling, where producers/consumers enter the monitor, see the buffer is full/empty, and block on an appropriate condition lock, @full@/@empty@.
     1454The @wait@ routine atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the routine's parameter list.
     1455The appropriate condition lock is signalled to unblock an opposite kind of thread after an element is inserted/removed from the buffer.
     1456Signalling is unconditional, because signalling an empty condition lock does nothing.
     1457Signalling semantics cannot have the signaller and signalled thread in the monitor simultaneously, which means:
     1458\begin{enumerate}
     1459\item
     1460The signalling thread returns immediately, and the signalled thread continues.
     1461\item
     1462The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait).
     1463\item
     1464The signalling thread blocks but is marked for urgrent unblocking at the next scheduling point and the signalled thread continues.
     1465\end{enumerate}
     1466The first approach is too restrictive, as it precludes solving a reasonable class of problems (\eg dating service).
     1467\CFA supports the next two semantics as both are useful.
     1468Finally, while it is common to store a @condition@ as a field of the monitor, in \CFA, a @condition@ variable can be created/stored independently.
     1469Furthermore, a condition variable is tied to a \emph{group} of monitors on first use (called \newterm{branding}), which means that using internal scheduling with distinct sets of monitors requires one condition variable per set of monitors.
    18831470
    18841471\begin{figure}
     
    18941481        };
    18951482        void ?{}( Buffer(T) & buffer ) with(buffer) {
    1896                 front = back = count = 0;
     1483                [front, back, count] = 0;
    18971484        }
     1485
    18981486        void insert( Buffer(T) & mutex buffer, T elem )
    18991487                                with(buffer) {
     
    19121500\end{lrbox}
    19131501
    1914 % \newbox\myboxB
    1915 % \begin{lrbox}{\myboxB}
    1916 % \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1917 % forall( otype T ) { // distribute forall
    1918 %       monitor Buffer {
    1919 %
    1920 %               int front, back, count;
    1921 %               T elements[10];
    1922 %       };
    1923 %       void ?{}( Buffer(T) & buffer ) with(buffer) {
    1924 %               [front, back, count] = 0;
    1925 %       }
    1926 %       T remove( Buffer(T) & mutex buffer ); // forward
    1927 %       void insert( Buffer(T) & mutex buffer, T elem )
    1928 %                               with(buffer) {
    1929 %               if ( count == 10 ) `waitfor( remove, buffer )`;
    1930 %               // insert elem into buffer
    1931 %
    1932 %       }
    1933 %       T remove( Buffer(T) & mutex buffer ) with(buffer) {
    1934 %               if ( count == 0 ) `waitfor( insert, buffer )`;
    1935 %               // remove elem from buffer
    1936 %
    1937 %               return elem;
    1938 %       }
    1939 % }
    1940 % \end{cfa}
    1941 % \end{lrbox}
    1942 
    19431502\newbox\myboxB
    19441503\begin{lrbox}{\myboxB}
    19451504\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1946 monitor ReadersWriter {
    1947         int rcnt, wcnt; // readers/writer using resource
    1948 };
    1949 void ?{}( ReadersWriter & rw ) with(rw) {
    1950         rcnt = wcnt = 0;
    1951 }
    1952 void EndRead( ReadersWriter & mutex rw ) with(rw) {
    1953         rcnt -= 1;
    1954 }
    1955 void EndWrite( ReadersWriter & mutex rw ) with(rw) {
    1956         wcnt = 0;
    1957 }
    1958 void StartRead( ReadersWriter & mutex rw ) with(rw) {
    1959         if ( wcnt > 0 ) `waitfor( EndWrite, rw );`
    1960         rcnt += 1;
    1961 }
    1962 void StartWrite( ReadersWriter & mutex rw ) with(rw) {
    1963         if ( wcnt > 0 ) `waitfor( EndWrite, rw );`
    1964         else while ( rcnt > 0 ) `waitfor( EndRead, rw );`
    1965         wcnt = 1;
    1966 }
    1967 
     1505forall( otype T ) { // distribute forall
     1506        monitor Buffer {
     1507
     1508                int front, back, count;
     1509                T elements[10];
     1510        };
     1511        void ?{}( Buffer(T) & buffer ) with(buffer) {
     1512                [front, back, count] = 0;
     1513        }
     1514        T remove( Buffer(T) & mutex buffer ); // forward
     1515        void insert( Buffer(T) & mutex buffer, T elem )
     1516                                with(buffer) {
     1517                if ( count == 10 ) `waitfor( remove, buffer )`;
     1518                // insert elem into buffer
     1519
     1520        }
     1521        T remove( Buffer(T) & mutex buffer ) with(buffer) {
     1522                if ( count == 0 ) `waitfor( insert, buffer )`;
     1523                // remove elem from buffer
     1524
     1525                return elem;
     1526        }
     1527}
    19681528\end{cfa}
    19691529\end{lrbox}
    19701530
    1971 \subfloat[Generic bounded buffer, internal scheduling]{\label{f:BBInt}\usebox\myboxA}
    1972 \hspace{3pt}
    1973 \vrule
    1974 \hspace{3pt}
    1975 \subfloat[Readers / writer lock, external scheduling]{\label{f:RWExt}\usebox\myboxB}
    1976 
    1977 \caption{Internal / external scheduling}
    1978 \label{f:InternalExternalScheduling}
     1531\subfloat[Internal Scheduling]{\label{f:BBInt}\usebox\myboxA}
     1532%\qquad
     1533\subfloat[External Scheduling]{\label{f:BBExt}\usebox\myboxB}
     1534\caption{Generic Bounded-Buffer}
     1535\label{f:GenericBoundedBuffer}
    19791536\end{figure}
    19801537
    1981 Figure~\ref{f:BBInt} can be transformed into external scheduling by removing the condition variables and signals/waits, and adding the following lines at the locations of the current @wait@s in @insert@/@remove@, respectively.
    1982 \begin{cfa}[aboveskip=2pt,belowskip=1pt]
    1983 if ( count == 10 ) `waitfor( remove, buffer )`;       |      if ( count == 0 ) `waitfor( insert, buffer )`;
    1984 \end{cfa}
    1985 Here, the producers/consumers detects a full/\-empty buffer and prevents more producers/consumers from entering the monitor until there is a free/empty slot in the buffer.
    1986 External scheduling is controlled by the @waitfor@ statement, which atomically blocks the calling thread, releases the monitor lock, and restricts the function calls that can next acquire mutual exclusion.
     1538Figure~\ref{f:BBExt} shows a \CFA bounded-buffer with external scheduling, where producers/consumers detecting a full/empty buffer block and prevent more producers/consumers from entering the monitor until the buffer has a free/empty slot.
     1539External scheduling is controlled by the @waitfor@ statement, which atomically blocks the calling thread, releases the monitor lock, and restricts the routine calls that can next acquire mutual exclusion.
    19871540If the buffer is full, only calls to @remove@ can acquire the buffer, and if the buffer is empty, only calls to @insert@ can acquire the buffer.
    1988 Threads calling excluded functions block outside of (external to) the monitor on the calling queue, versus blocking on condition queues inside of (internal to) the monitor.
    1989 Figure~\ref{f:RWExt} shows a readers/writer lock written using external scheduling, where a waiting reader detects a writer using the resource and restricts further calls until the writer exits by calling @EndWrite@.
    1990 The writer does a similar action for each reader or writer using the resource.
    1991 Note, no new calls to @StarRead@/@StartWrite@ may occur when waiting for the call to @EndRead@/@EndWrite@.
    1992 External scheduling allows waiting for events from other threads while restricting unrelated events, that would otherwise have to wait on conditions in the monitor.
    1993 The mechnaism can be done in terms of control flow, \eg Ada @accept@ or \uC @_Accept@, or in terms of data, \eg Go @select@ on channels.
    1994 While both mechanisms have strengths and weaknesses, this project uses the control-flow mechanism to be consistent with other language features.
    1995 % Two challenges specific to \CFA for external scheduling are loose object-definitions (see Section~\ref{s:LooseObjectDefinitions}) and multiple-monitor functions (see Section~\ref{s:Multi-MonitorScheduling}).
    1996 
    1997 Figure~\ref{f:DatingService} shows a dating service demonstrating non-blocking and blocking signalling.
    1998 The dating service matches girl and boy threads with matching compatibility codes so they can exchange phone numbers.
    1999 A thread blocks until an appropriate partner arrives.
    2000 The complexity is exchanging phone numbers in the monitor because of the mutual-exclusion property.
    2001 For signal scheduling, the @exchange@ condition is necessary to block the thread finding the match, while the matcher unblocks to take the opposite number, post its phone number, and unblock the partner.
    2002 For signal-block scheduling, the implicit urgent-queue replaces the explict @exchange@-condition and @signal_block@ puts the finding thread on the urgent condition and unblocks the matcher.
    2003 The dating service is an example of a monitor that cannot be written using external scheduling because it requires knowledge of calling parameters to make scheduling decisions, and parameters of waiting threads are unavailable;
    2004 as well, an arriving thread may not find a partner and must wait, which requires a condition variable, and condition variables imply internal scheduling.
    2005 Furthermore, barging corrupts the dating service during an exchange because a barger may also match and change the phone numbers, invalidating the previous exchange phone number.
    2006 Putting loops around the @wait@s does not correct the problem;
    2007 the simple solution must be restructured to account for barging.
     1541Threads making calls to routines that are currently excluded block outside (externally) of the monitor on a calling queue, versus blocking on condition queues inside the monitor.
     1542
     1543Both internal and external scheduling extend to multiple monitors in a natural way.
     1544\begin{cfa}
     1545monitor M { `condition e`; ... };
     1546void foo( M & mutex m1, M & mutex m2 ) {
     1547        ... wait( `e` ); ...                                    $\C{// wait( e, m1, m2 )}$
     1548        ... wait( `e, m1` ); ...
     1549        ... wait( `e, m2` ); ...
     1550}
     1551
     1552void rtn$\(_1\)$( M & mutex m1, M & mutex m2 );
     1553void rtn$\(_2\)$( M & mutex m1 );
     1554void bar( M & mutex m1, M & mutex m2 ) {
     1555        ... waitfor( `rtn` ); ...                               $\C{// waitfor( rtn\(_1\), m1, m2 )}$
     1556        ... waitfor( `rtn, m1` ); ...                   $\C{// waitfor( rtn\(_2\), m1 )}$
     1557}
     1558\end{cfa}
     1559For @wait( e )@, the default semantics is to atomically block the signaller and release all acquired mutex types in the parameter list, \ie @wait( e, m1, m2 )@.
     1560To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@.
     1561Wait statically verifies the released monitors are the acquired mutex-parameters so unconditional release is safe.
     1562Similarly, for @waitfor( rtn, ... )@, the default semantics is to atomically block the acceptor and release all acquired mutex types in the parameter list, \ie @waitfor( rtn, m1, m2 )@.
     1563To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@.
     1564Waitfor statically verifies the released monitors are the same as the acquired mutex-parameters of the given routine or routine pointer.
     1565To statically verify the released monitors match with the accepted routine's mutex parameters, the routine (pointer) prototype must be accessible.
     1566
     1567Given the ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock.
     1568\begin{cfa}
     1569void foo( M & mutex m1, M & mutex m2 ) {
     1570        ... wait( `e, m1` ); ...                                $\C{// release m1, keeping m2 acquired )}$
     1571void baz( M & mutex m1, M & mutex m2 ) {        $\C{// must acquire m1 and m2 )}$
     1572        ... signal( `e` ); ...
     1573\end{cfa}
     1574The @wait@ only releases @m1@ so the signalling thread cannot acquire both @m1@ and @m2@ to  enter @baz@ to get to the @signal@.
     1575While deadlock issues can occur with multiple/nesting acquisition, this issue results from the fact that locks, and by extension monitors, are not perfectly composable.
     1576
     1577Finally, an important aspect of monitor implementation is barging, \ie can calling threads barge ahead of signalled threads?
     1578If barging is allowed, synchronization between a singller and signallee is difficult, often requiring multiple unblock/block cycles (looping around a wait rechecking if a condition is met).
     1579\begin{quote}
     1580However, we decree that a signal operation be followed immediately by resumption of a waiting program, without possibility of an intervening procedure call from yet a third program.
     1581It is only in this way that a waiting program has an absolute guarantee that it can acquire the resource just released by the signalling program without any danger that a third program will interpose a monitor entry and seize the resource instead.~\cite[p.~550]{Hoare74}
     1582\end{quote}
     1583\CFA scheduling \emph{precludes} barging, which simplifies synchronization among threads in the monitor and increases correctness.
     1584For example, there are no loops in either bounded buffer solution in Figure~\ref{f:GenericBoundedBuffer}.
     1585Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design and implementation of \CFA concurrency.
     1586
     1587
     1588\subsection{Barging Prevention}
     1589
     1590Figure~\ref{f:BargingPrevention} shows \CFA code where bulk acquire adds complexity to the internal-signalling semantics.
     1591The complexity begins at the end of the inner @mutex@ statement, where the semantics of internal scheduling need to be extended for multiple monitors.
     1592The problem is that bulk acquire is used in the inner @mutex@ statement where one of the monitors is already acquired.
     1593When the signalling thread reaches the end of the inner @mutex@ statement, it should transfer ownership of @m1@ and @m2@ to the waiting thread to prevent barging into the outer @mutex@ statement by another thread.
     1594However, both the signalling and signalled threads still need monitor @m1@.
     1595
     1596\begin{figure}
     1597\newbox\myboxA
     1598\begin{lrbox}{\myboxA}
     1599\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1600monitor M m1, m2;
     1601condition c;
     1602mutex( m1 ) {
     1603        ...
     1604        mutex( m1, m2 ) {
     1605                ... `wait( c )`; // block and release m1, m2
     1606                // m1, m2 acquired
     1607        } // $\LstCommentStyle{\color{red}release m2}$
     1608        // m1 acquired
     1609} // release m1
     1610\end{cfa}
     1611\end{lrbox}
     1612
     1613\newbox\myboxB
     1614\begin{lrbox}{\myboxB}
     1615\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1616
     1617
     1618mutex( m1 ) {
     1619        ...
     1620        mutex( m1, m2 ) {
     1621                ... `signal( c )`; ...
     1622                // m1, m2 acquired
     1623        } // $\LstCommentStyle{\color{red}release m2}$
     1624        // m1 acquired
     1625} // release m1
     1626\end{cfa}
     1627\end{lrbox}
     1628
     1629\newbox\myboxC
     1630\begin{lrbox}{\myboxC}
     1631\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1632
     1633
     1634mutex( m1 ) {
     1635        ... `wait( c )`; ...
     1636        // m1 acquired
     1637} // $\LstCommentStyle{\color{red}release m1}$
     1638
     1639
     1640
     1641
     1642\end{cfa}
     1643\end{lrbox}
     1644
     1645\begin{cquote}
     1646\subfloat[Waiting Thread]{\label{f:WaitingThread}\usebox\myboxA}
     1647\hspace{2\parindentlnth}
     1648\subfloat[Signalling Thread]{\label{f:SignallingThread}\usebox\myboxB}
     1649\hspace{2\parindentlnth}
     1650\subfloat[Other Waiting Thread]{\label{f:SignallingThread}\usebox\myboxC}
     1651\end{cquote}
     1652\caption{Barging Prevention}
     1653\label{f:BargingPrevention}
     1654\end{figure}
     1655
     1656The obvious solution to the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred.
     1657It can be argued that that moment is when the last lock is no longer needed, because this semantics fits most closely to the behaviour of single-monitor scheduling.
     1658This solution has the main benefit of transferring ownership of groups of monitors, which simplifies the semantics from multiple objects to a single group of objects, effectively making the existing single-monitor semantic viable by simply changing monitors to monitor groups.
     1659This solution releases the monitors once every monitor in a group can be released.
     1660However, since some monitors are never released (\eg the monitor of a thread), this interpretation means a group might never be released.
     1661A more interesting interpretation is to transfer the group until all its monitors are released, which means the group is not passed further and a thread can retain its locks.
     1662
     1663However, listing \ref{f:int-secret} shows this solution can become much more complicated depending on what is executed while secretly holding B at line \ref{line:secret}, while avoiding the need to transfer ownership of a subset of the condition monitors.
     1664Figure~\ref{f:dependency} shows a slightly different example where a third thread is waiting on monitor @A@, using a different condition variable.
     1665Because the third thread is signalled when secretly holding @B@, the goal  becomes unreachable.
     1666Depending on the order of signals (listing \ref{f:dependency} line \ref{line:signal-ab} and \ref{line:signal-a}) two cases can happen:
     1667
     1668\begin{comment}
     1669\paragraph{Case 1: thread $\alpha$ goes first.} In this case, the problem is that monitor @A@ needs to be passed to thread $\beta$ when thread $\alpha$ is done with it.
     1670\paragraph{Case 2: thread $\beta$ goes first.} In this case, the problem is that monitor @B@ needs to be retained and passed to thread $\alpha$ along with monitor @A@, which can be done directly or possibly using thread $\beta$ as an intermediate.
     1671\\
     1672
     1673Note that ordering is not determined by a race condition but by whether signalled threads are enqueued in FIFO or FILO order.
     1674However, regardless of the answer, users can move line \ref{line:signal-a} before line \ref{line:signal-ab} and get the reverse effect for listing \ref{f:dependency}.
     1675
     1676In both cases, the threads need to be able to distinguish, on a per monitor basis, which ones need to be released and which ones need to be transferred, which means knowing when to release a group becomes complex and inefficient (see next section) and therefore effectively precludes this approach.
     1677
     1678
     1679\subsubsection{Dependency graphs}
     1680
     1681\begin{figure}
     1682\begin{multicols}{3}
     1683Thread $\alpha$
     1684\begin{cfa}[numbers=left, firstnumber=1]
     1685acquire A
     1686        acquire A & B
     1687                wait A & B
     1688        release A & B
     1689release A
     1690\end{cfa}
     1691\columnbreak
     1692Thread $\gamma$
     1693\begin{cfa}[numbers=left, firstnumber=6, escapechar=|]
     1694acquire A
     1695        acquire A & B
     1696                |\label{line:signal-ab}|signal A & B
     1697        |\label{line:release-ab}|release A & B
     1698        |\label{line:signal-a}|signal A
     1699|\label{line:release-a}|release A
     1700\end{cfa}
     1701\columnbreak
     1702Thread $\beta$
     1703\begin{cfa}[numbers=left, firstnumber=12, escapechar=|]
     1704acquire A
     1705        wait A
     1706|\label{line:release-aa}|release A
     1707\end{cfa}
     1708\end{multicols}
     1709\begin{cfa}[caption={Pseudo-code for the three thread example.},label={f:dependency}]
     1710\end{cfa}
     1711\begin{center}
     1712\input{dependency}
     1713\end{center}
     1714\caption{Dependency graph of the statements in listing \ref{f:dependency}}
     1715\label{fig:dependency}
     1716\end{figure}
     1717
     1718In listing \ref{f:int-bulk-cfa}, there is a solution that satisfies both barging prevention and mutual exclusion.
     1719If ownership of both monitors is transferred to the waiter when the signaller releases @A & B@ and then the waiter transfers back ownership of @A@ back to the signaller when it releases it, then the problem is solved (@B@ is no longer in use at this point).
     1720Dynamically finding the correct order is therefore the second possible solution.
     1721The problem is effectively resolving a dependency graph of ownership requirements.
     1722Here even the simplest of code snippets requires two transfers and has a super-linear complexity.
     1723This complexity can be seen in listing \ref{f:explosion}, which is just a direct extension to three monitors, requires at least three ownership transfer and has multiple solutions.
     1724Furthermore, the presence of multiple solutions for ownership transfer can cause deadlock problems if a specific solution is not consistently picked; In the same way that multiple lock acquiring order can cause deadlocks.
     1725\begin{figure}
     1726\begin{multicols}{2}
     1727\begin{cfa}
     1728acquire A
     1729        acquire B
     1730                acquire C
     1731                        wait A & B & C
     1732                release C
     1733        release B
     1734release A
     1735\end{cfa}
     1736
     1737\columnbreak
     1738
     1739\begin{cfa}
     1740acquire A
     1741        acquire B
     1742                acquire C
     1743                        signal A & B & C
     1744                release C
     1745        release B
     1746release A
     1747\end{cfa}
     1748\end{multicols}
     1749\begin{cfa}[caption={Extension to three monitors of listing \ref{f:int-bulk-cfa}},label={f:explosion}]
     1750\end{cfa}
     1751\end{figure}
     1752
     1753Given the three threads example in listing \ref{f:dependency}, figure \ref{fig:dependency} shows the corresponding dependency graph that results, where every node is a statement of one of the three threads, and the arrows the dependency of that statement (\eg $\alpha1$ must happen before $\alpha2$).
     1754The extra challenge is that this dependency graph is effectively post-mortem, but the runtime system needs to be able to build and solve these graphs as the dependencies unfold.
     1755Resolving dependency graphs being a complex and expensive endeavour, this solution is not the preferred one.
     1756
     1757\subsubsection{Partial Signalling} \label{partial-sig}
     1758\end{comment}
     1759
     1760Finally, the solution that is chosen for \CFA is to use partial signalling.
     1761Again using listing \ref{f:int-bulk-cfa}, the partial signalling solution transfers ownership of monitor @B@ at lines \ref{line:signal1} to the waiter but does not wake the waiting thread since it is still using monitor @A@.
     1762Only when it reaches line \ref{line:lastRelease} does it actually wake up the waiting thread.
     1763This solution has the benefit that complexity is encapsulated into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met.
     1764This solution has a much simpler implementation than a dependency graph solving algorithms, which is why it was chosen.
     1765Furthermore, after being fully implemented, this solution does not appear to have any significant downsides.
     1766
     1767Using partial signalling, listing \ref{f:dependency} can be solved easily:
     1768\begin{itemize}
     1769        \item When thread $\gamma$ reaches line \ref{line:release-ab} it transfers monitor @B@ to thread $\alpha$ and continues to hold monitor @A@.
     1770        \item When thread $\gamma$ reaches line \ref{line:release-a}  it transfers monitor @A@ to thread $\beta$  and wakes it up.
     1771        \item When thread $\beta$  reaches line \ref{line:release-aa} it transfers monitor @A@ to thread $\alpha$ and wakes it up.
     1772\end{itemize}
     1773
     1774
     1775\subsection{Signalling: Now or Later}
    20081776
    20091777\begin{figure}
     
    20161784        int GirlPhNo, BoyPhNo;
    20171785        condition Girls[CCodes], Boys[CCodes];
    2018         `condition exchange;`
     1786        condition exchange;
    20191787};
    20201788int girl( DS & mutex ds, int phNo, int ccode ) {
     
    20221790                wait( Girls[ccode] );
    20231791                GirlPhNo = phNo;
    2024                 `signal( exchange );`
     1792                exchange.signal();
    20251793        } else {
    20261794                GirlPhNo = phNo;
    2027                 `signal( Boys[ccode] );`
    2028                 `wait( exchange );`
    2029         }
     1795                signal( Boys[ccode] );
     1796                exchange.wait();
     1797        } // if
    20301798        return BoyPhNo;
    20311799}
     
    20521820        } else {
    20531821                GirlPhNo = phNo; // make phone number available
    2054                 `signal_block( Boys[ccode] );` // restart boy
     1822                signal_block( Boys[ccode] ); // restart boy
    20551823
    20561824        } // if
     
    20661834\qquad
    20671835\subfloat[\lstinline@signal_block@]{\label{f:DatingSignalBlock}\usebox\myboxB}
    2068 \caption{Dating service}
    2069 \label{f:DatingService}
     1836\caption{Dating service. }
     1837\label{f:Dating service}
    20701838\end{figure}
    20711839
    2072 In summation, for internal scheduling, non-blocking signalling (as in the producer/consumer example) is used when the signaller is providing the cooperation for a waiting thread;
    2073 the signaller enters the monitor and changes state, detects a waiting threads that can use the state, performs a non-blocking signal on the condition queue for the waiting thread, and exits the monitor to run concurrently.
    2074 The waiter unblocks next from the urgent queue, uses/takes the state, and exits the monitor.
    2075 Blocking signal is the reverse, where the waiter is providing the cooperation for the signalling thread;
    2076 the signaller enters the monitor, detects a waiting thread providing the necessary state, performs a blocking signal to place it on the urgent queue and unblock the waiter.
    2077 The waiter changes state and exits the monitor, and the signaller unblocks next from the urgent queue to use/take the state.
    2078 
    2079 Both internal and external scheduling extend to multiple monitors in a natural way.
    2080 \begin{cquote}
    2081 \begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
    2082 \begin{cfa}
    2083 monitor M { `condition e`; ... };
    2084 void foo( M & mutex m1, M & mutex m2 ) {
    2085         ... wait( `e` ); ...   // wait( e, m1, m2 )
    2086         ... wait( `e, m1` ); ...
    2087         ... wait( `e, m2` ); ...
    2088 }
    2089 \end{cfa}
    2090 &
    2091 \begin{cfa}
    2092 void rtn$\(_1\)$( M & mutex m1, M & mutex m2 );
    2093 void rtn$\(_2\)$( M & mutex m1 );
    2094 void bar( M & mutex m1, M & mutex m2 ) {
    2095         ... waitfor( `rtn` ); ...       // $\LstCommentStyle{waitfor( rtn\(_1\), m1, m2 )}$
    2096         ... waitfor( `rtn, m1` ); ... // $\LstCommentStyle{waitfor( rtn\(_2\), m1 )}$
    2097 }
    2098 \end{cfa}
     1840An important note is that, until now, signalling a monitor was a delayed operation.
     1841The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the @signal@ statement.
     1842However, in some cases, it may be more convenient for users to immediately transfer ownership to the thread that is waiting for cooperation, which is achieved using the @signal_block@ routine.
     1843
     1844The example in table \ref{tbl:datingservice} highlights the difference in behaviour.
     1845As mentioned, @signal@ only transfers ownership once the current critical section exits; this behaviour requires additional synchronization when a two-way handshake is needed.
     1846To avoid this explicit synchronization, the @condition@ type offers the @signal_block@ routine, which handles the two-way handshake as shown in the example.
     1847This feature removes the need for a second condition variables and simplifies programming.
     1848Like every other monitor semantic, @signal_block@ uses barging prevention, which means mutual-exclusion is baton-passed both on the front end and the back end of the call to @signal_block@, meaning no other thread can acquire the monitor either before or after the call.
     1849
     1850% ======================================================================
     1851% ======================================================================
     1852\section{External scheduling} \label{extsched}
     1853% ======================================================================
     1854% ======================================================================
     1855An alternative to internal scheduling is external scheduling (see Table~\ref{tbl:sched}).
     1856
     1857\begin{comment}
     1858\begin{table}
     1859\begin{tabular}{|c|c|c|}
     1860Internal Scheduling & External Scheduling & Go\\
     1861\hline
     1862\begin{uC++}[tabsize=3]
     1863_Monitor Semaphore {
     1864        condition c;
     1865        bool inUse;
     1866public:
     1867        void P() {
     1868                if(inUse)
     1869                        wait(c);
     1870                inUse = true;
     1871        }
     1872        void V() {
     1873                inUse = false;
     1874                signal(c);
     1875        }
     1876}
     1877\end{uC++}&\begin{uC++}[tabsize=3]
     1878_Monitor Semaphore {
     1879
     1880        bool inUse;
     1881public:
     1882        void P() {
     1883                if(inUse)
     1884                        _Accept(V);
     1885                inUse = true;
     1886        }
     1887        void V() {
     1888                inUse = false;
     1889
     1890        }
     1891}
     1892\end{uC++}&\begin{Go}[tabsize=3]
     1893type MySem struct {
     1894        inUse bool
     1895        c     chan bool
     1896}
     1897
     1898// acquire
     1899func (s MySem) P() {
     1900        if s.inUse {
     1901                select {
     1902                case <-s.c:
     1903                }
     1904        }
     1905        s.inUse = true
     1906}
     1907
     1908// release
     1909func (s MySem) V() {
     1910        s.inUse = false
     1911
     1912        // This actually deadlocks
     1913        // when single thread
     1914        s.c <- false
     1915}
     1916\end{Go}
    20991917\end{tabular}
    2100 \end{cquote}
    2101 For @wait( e )@, the default semantics is to atomically block the signaller and release all acquired mutex parameters, \ie @wait( e, m1, m2 )@.
    2102 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@.
    2103 Wait cannot statically verifies the released monitors are the acquired mutex-parameters without disallowing separately compiled helper functions calling @wait@.
    2104 While \CC supports bulk locking, @wait@ only accepts a single lock for a condition variable, so bulk locking with condition variables is asymmetric.
    2105 Finally, a signaller,
    2106 \begin{cfa}
    2107 void baz( M & mutex m1, M & mutex m2 ) {
    2108         ... signal( e ); ...
    2109 }
    2110 \end{cfa}
    2111 must have acquired at least the same locks as the waiting thread signalled from a condition queue to allow the locks to be passed, and hence, prevent barging.
    2112 
    2113 Similarly, for @waitfor( rtn )@, the default semantics is to atomically block the acceptor and release all acquired mutex parameters, \ie @waitfor( rtn, m1, m2 )@.
    2114 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@.
    2115 @waitfor@ does statically verify the monitor types passed are the same as the acquired mutex-parameters of the given function or function pointer, hence the function (pointer) prototype must be accessible.
    2116 % When an overloaded function appears in an @waitfor@ statement, calls to any function with that name are accepted.
    2117 % The rationale is that members with the same name should perform a similar function, and therefore, all should be eligible to accept a call.
    2118 Overloaded functions can be disambiguated using a cast
    2119 \begin{cfa}
    2120 void rtn( M & mutex m );
    2121 `int` rtn( M & mutex m );
    2122 waitfor( (`int` (*)( M & mutex ))rtn, m );
    2123 \end{cfa}
    2124 
    2125 The ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock.
    2126 \begin{cfa}
    2127 void foo( M & mutex m1, M & mutex m2 ) {
    2128         ... wait( `e, m1` ); ...                                $\C{// release m1, keeping m2 acquired )}$
    2129 void bar( M & mutex m1, M & mutex m2 ) {        $\C{// must acquire m1 and m2 )}$
    2130         ... signal( `e` ); ...
    2131 \end{cfa}
    2132 The @wait@ only releases @m1@ so the signalling thread cannot acquire @m1@ and @m2@ to enter @bar@ and @signal@ the condition.
    2133 While deadlock can occur with multiple/nesting acquisition, this is a consequence of locks, and by extension monitors, not being perfectly composable.
    2134 
    2135 
    2136 
    2137 \subsection{\texorpdfstring{Extended \protect\lstinline@waitfor@}{Extended waitfor}}
    2138 
    2139 Figure~\ref{f:ExtendedWaitfor} shows the extended form of the @waitfor@ statement to conditionally accept one of a group of mutex functions, with an optional statement to be performed \emph{after} the mutex function finishes.
    2140 For a @waitfor@ clause to be executed, its @when@ must be true and an outstanding call to its corresponding member(s) must exist.
    2141 The \emph{conditional-expression} of a @when@ may call a function, but the function must not block or context switch.
    2142 If there are multiple acceptable mutex calls, selection occurs top-to-bottom (prioritized) among the @waitfor@ clauses, whereas some programming languages with similar mechanisms accept nondeterministically for this case, \eg Go \lstinline[morekeywords=select]@select@.
    2143 If some accept guards are true and there are no outstanding calls to these members, the acceptor is blocked until a call to one of these members is made.
    2144 If there is a @timeout@ clause, it provides an upper bound on waiting.
    2145 If all the accept guards are false, the statement does nothing, unless there is a terminating @else@ clause with a true guard, which is executed instead.
    2146 Hence, the terminating @else@ clause allows a conditional attempt to accept a call without blocking.
    2147 If both @timeout@ and @else@ clause are present, the @else@ must be conditional, or the @timeout@ is never triggered.
    2148 There is also a traditional future wait queue (not shown) (\eg Microsoft (@WaitForMultipleObjects@)), to wait for a specified number of future elements in the queue.
     1918\caption{Different forms of scheduling.}
     1919\label{tbl:sched}
     1920\end{table}
     1921\end{comment}
     1922
     1923This method is more constrained and explicit, which helps users reduce the non-deterministic nature of concurrency.
     1924Indeed, as the following examples demonstrate, external scheduling allows users to wait for events from other threads without the concern of unrelated events occurring.
     1925External scheduling can generally be done either in terms of control flow (\eg Ada with @accept@, \uC with @_Accept@) or in terms of data (\eg Go with channels).
     1926Of course, both of these paradigms have their own strengths and weaknesses, but for this project, control-flow semantics was chosen to stay consistent with the rest of the languages semantics.
     1927Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multiple-monitor routines.
     1928The previous example shows a simple use @_Accept@ versus @wait@/@signal@ and its advantages.
     1929Note that while other languages often use @accept@/@select@ as the core external scheduling keyword, \CFA uses @waitfor@ to prevent name collisions with existing socket \textbf{api}s.
     1930
     1931For the @P@ member above using internal scheduling, the call to @wait@ only guarantees that @V@ is the last routine to access the monitor, allowing a third routine, say @isInUse()@, acquire mutual exclusion several times while routine @P@ is waiting.
     1932On the other hand, external scheduling guarantees that while routine @P@ is waiting, no other routine than @V@ can acquire the monitor.
     1933
     1934% ======================================================================
     1935% ======================================================================
     1936\subsection{Loose Object Definitions}
     1937% ======================================================================
     1938% ======================================================================
     1939In \uC, a monitor class declaration includes an exhaustive list of monitor operations.
     1940Since \CFA is not object oriented, monitors become both more difficult to implement and less clear for a user:
     1941
     1942\begin{cfa}
     1943monitor A {};
     1944
     1945void f(A & mutex a);
     1946void g(A & mutex a) {
     1947        waitfor(f); // Obvious which f() to wait for
     1948}
     1949
     1950void f(A & mutex a, int); // New different F added in scope
     1951void h(A & mutex a) {
     1952        waitfor(f); // Less obvious which f() to wait for
     1953}
     1954\end{cfa}
     1955
     1956Furthermore, external scheduling is an example where implementation constraints become visible from the interface.
     1957Here is the cfa-code for the entering phase of a monitor:
     1958\begin{center}
     1959\begin{tabular}{l}
     1960\begin{cfa}
     1961        if monitor is free
     1962                enter
     1963        elif already own the monitor
     1964                continue
     1965        elif monitor accepts me
     1966                enter
     1967        else
     1968                block
     1969\end{cfa}
     1970\end{tabular}
     1971\end{center}
     1972For the first two conditions, it is easy to implement a check that can evaluate the condition in a few instructions.
     1973However, a fast check for @monitor accepts me@ is much harder to implement depending on the constraints put on the monitors.
     1974Indeed, monitors are often expressed as an entry queue and some acceptor queue as in Figure~\ref{fig:ClassicalMonitor}.
    21491975
    21501976\begin{figure}
    21511977\centering
    2152 \begin{cfa}
    2153 `when` ( $\emph{conditional-expression}$ )      $\C{// optional guard}$
    2154         waitfor( $\emph{mutex-member-name}$ ) $\emph{statement}$ $\C{// action after call}$
    2155 `or` `when` ( $\emph{conditional-expression}$ ) $\C{// any number of functions}$
    2156         waitfor( $\emph{mutex-member-name}$ ) $\emph{statement}$
    2157 `or`    ...
    2158 `when` ( $\emph{conditional-expression}$ ) $\C{// optional guard}$
    2159         `timeout` $\emph{statement}$ $\C{// optional terminating timeout clause}$
    2160 `when` ( $\emph{conditional-expression}$ ) $\C{// optional guard}$
    2161         `else`  $\emph{statement}$ $\C{// optional terminating clause}$
    2162 \end{cfa}
    2163 \caption{Extended \protect\lstinline@waitfor@}
    2164 \label{f:ExtendedWaitfor}
     1978\subfloat[Classical Monitor] {
     1979\label{fig:ClassicalMonitor}
     1980{\resizebox{0.45\textwidth}{!}{\input{monitor}}}
     1981}% subfloat
     1982\qquad
     1983\subfloat[bulk acquire Monitor] {
     1984\label{fig:BulkMonitor}
     1985{\resizebox{0.45\textwidth}{!}{\input{ext_monitor}}}
     1986}% subfloat
     1987\caption{External Scheduling Monitor}
    21651988\end{figure}
    21661989
    2167 Note, a group of conditional @waitfor@ clauses is \emph{not} the same as a group of @if@ statements, \eg:
    2168 \begin{cfa}
    2169 if ( C1 ) waitfor( mem1 );                       when ( C1 ) waitfor( mem1 );
    2170 else if ( C2 ) waitfor( mem2 );         or when ( C2 ) waitfor( mem2 );
    2171 \end{cfa}
    2172 The left example only accepts @mem1@ if @C1@ is true or only @mem2@ if @C2@ is true.
    2173 The right example accepts either @mem1@ or @mem2@ if @C1@ and @C2@ are true.
    2174 
    2175 An interesting use of @waitfor@ is accepting the @mutex@ destructor to know when an object is deallocated, \eg assume the bounded buffer is restructred from a monitor to a thread with the following @main@.
    2176 \begin{cfa}
    2177 void main( Buffer(T) & buffer ) with(buffer) {
    2178         for () {
    2179                 `waitfor( ^?{}, buffer )` break;
    2180                 or when ( count != 20 ) waitfor( insert, buffer ) { ... }
    2181                 or when ( count != 0 ) waitfor( remove, buffer ) { ... }
     1990There are other alternatives to these pictures, but in the case of the left picture, implementing a fast accept check is relatively easy.
     1991Restricted to a fixed number of mutex members, N, the accept check reduces to updating a bitmask when the acceptor queue changes, a check that executes in a single instruction even with a fairly large number (\eg 128) of mutex members.
     1992This approach requires a unique dense ordering of routines with an upper-bound and that ordering must be consistent across translation units.
     1993For OO languages these constraints are common, since objects only offer adding member routines consistently across translation units via inheritance.
     1994However, in \CFA users can extend objects with mutex routines that are only visible in certain translation unit.
     1995This means that establishing a program-wide dense-ordering among mutex routines can only be done in the program linking phase, and still could have issues when using dynamically shared objects.
     1996
     1997The alternative is to alter the implementation as in Figure~\ref{fig:BulkMonitor}.
     1998Here, the mutex routine called is associated with a thread on the entry queue while a list of acceptable routines is kept separate.
     1999Generating a mask dynamically means that the storage for the mask information can vary between calls to @waitfor@, allowing for more flexibility and extensions.
     2000Storing an array of accepted routine pointers replaces the single instruction bitmask comparison with dereferencing a pointer followed by a linear search.
     2001Furthermore, supporting nested external scheduling (\eg listing \ref{f:nest-ext}) may now require additional searches for the @waitfor@ statement to check if a routine is already queued.
     2002
     2003\begin{figure}
     2004\begin{cfa}[caption={Example of nested external scheduling},label={f:nest-ext}]
     2005monitor M {};
     2006void foo( M & mutex a ) {}
     2007void bar( M & mutex b ) {
     2008        // Nested in the waitfor(bar, c) call
     2009        waitfor(foo, b);
     2010}
     2011void baz( M & mutex c ) {
     2012        waitfor(bar, c);
     2013}
     2014
     2015\end{cfa}
     2016\end{figure}
     2017
     2018Note that in the right picture, tasks need to always keep track of the monitors associated with mutex routines, and the routine mask needs to have both a routine pointer and a set of monitors, as is discussed in the next section.
     2019These details are omitted from the picture for the sake of simplicity.
     2020
     2021At this point, a decision must be made between flexibility and performance.
     2022Many design decisions in \CFA achieve both flexibility and performance, for example polymorphic routines add significant flexibility but inlining them means the optimizer can easily remove any runtime cost.
     2023Here, however, the cost of flexibility cannot be trivially removed.
     2024In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be  hard to write.
     2025This decision is based on the assumption that writing fast but inflexible locks is closer to a solved problem than writing locks that are as flexible as external scheduling in \CFA.
     2026
     2027% ======================================================================
     2028% ======================================================================
     2029\subsection{Multi-Monitor Scheduling}
     2030% ======================================================================
     2031% ======================================================================
     2032
     2033External scheduling, like internal scheduling, becomes significantly more complex when introducing multi-monitor syntax.
     2034Even in the simplest possible case, some new semantics needs to be established:
     2035\begin{cfa}
     2036monitor M {};
     2037
     2038void f(M & mutex a);
     2039
     2040void g(M & mutex b, M & mutex c) {
     2041        waitfor(f); // two monitors M => unknown which to pass to f(M & mutex)
     2042}
     2043\end{cfa}
     2044The obvious solution is to specify the correct monitor as follows:
     2045
     2046\begin{cfa}
     2047monitor M {};
     2048
     2049void f(M & mutex a);
     2050
     2051void g(M & mutex a, M & mutex b) {
     2052        // wait for call to f with argument b
     2053        waitfor(f, b);
     2054}
     2055\end{cfa}
     2056This syntax is unambiguous.
     2057Both locks are acquired and kept by @g@.
     2058When routine @f@ is called, the lock for monitor @b@ is temporarily transferred from @g@ to @f@ (while @g@ still holds lock @a@).
     2059This behaviour can be extended to the multi-monitor @waitfor@ statement as follows.
     2060
     2061\begin{cfa}
     2062monitor M {};
     2063
     2064void f(M & mutex a, M & mutex b);
     2065
     2066void g(M & mutex a, M & mutex b) {
     2067        // wait for call to f with arguments a and b
     2068        waitfor(f, a, b);
     2069}
     2070\end{cfa}
     2071
     2072Note that the set of monitors passed to the @waitfor@ statement must be entirely contained in the set of monitors already acquired in the routine. @waitfor@ used in any other context is undefined behaviour.
     2073
     2074An important behaviour to note is when a set of monitors only match partially:
     2075
     2076\begin{cfa}
     2077mutex struct A {};
     2078
     2079mutex struct B {};
     2080
     2081void g(A & mutex a, B & mutex b) {
     2082        waitfor(f, a, b);
     2083}
     2084
     2085A a1, a2;
     2086B b;
     2087
     2088void foo() {
     2089        g(a1, b); // block on accept
     2090}
     2091
     2092void bar() {
     2093        f(a2, b); // fulfill cooperation
     2094}
     2095\end{cfa}
     2096While the equivalent can happen when using internal scheduling, the fact that conditions are specific to a set of monitors means that users have to use two different condition variables.
     2097In both cases, partially matching monitor sets does not wakeup the waiting thread.
     2098It is also important to note that in the case of external scheduling the order of parameters is irrelevant; @waitfor(f,a,b)@ and @waitfor(f,b,a)@ are indistinguishable waiting condition.
     2099
     2100% ======================================================================
     2101% ======================================================================
     2102\subsection{\protect\lstinline|waitfor| Semantics}
     2103% ======================================================================
     2104% ======================================================================
     2105
     2106Syntactically, the @waitfor@ statement takes a routine identifier and a set of monitors.
     2107While the set of monitors can be any list of expressions, the routine name is more restricted because the compiler validates at compile time the validity of the routine type and the parameters used with the @waitfor@ statement.
     2108It checks that the set of monitors passed in matches the requirements for a routine call.
     2109Figure~\ref{f:waitfor} shows various usages of the waitfor statement and which are acceptable.
     2110The choice of the routine type is made ignoring any non-@mutex@ parameter.
     2111One limitation of the current implementation is that it does not handle overloading, but overloading is possible.
     2112\begin{figure}
     2113\begin{cfa}[caption={Various correct and incorrect uses of the waitfor statement},label={f:waitfor}]
     2114monitor A{};
     2115monitor B{};
     2116
     2117void f1( A & mutex );
     2118void f2( A & mutex, B & mutex );
     2119void f3( A & mutex, int );
     2120void f4( A & mutex, int );
     2121void f4( A & mutex, double );
     2122
     2123void foo( A & mutex a1, A & mutex a2, B & mutex b1, B & b2 ) {
     2124        A * ap = & a1;
     2125        void (*fp)( A & mutex ) = f1;
     2126
     2127        waitfor(f1, a1);     // Correct : 1 monitor case
     2128        waitfor(f2, a1, b1); // Correct : 2 monitor case
     2129        waitfor(f3, a1);     // Correct : non-mutex arguments are ignored
     2130        waitfor(f1, *ap);    // Correct : expression as argument
     2131
     2132        waitfor(f1, a1, b1); // Incorrect : Too many mutex arguments
     2133        waitfor(f2, a1);     // Incorrect : Too few mutex arguments
     2134        waitfor(f2, a1, a2); // Incorrect : Mutex arguments don't match
     2135        waitfor(f1, 1);      // Incorrect : 1 not a mutex argument
     2136        waitfor(f9, a1);     // Incorrect : f9 routine does not exist
     2137        waitfor(*fp, a1 );   // Incorrect : fp not an identifier
     2138        waitfor(f4, a1);     // Incorrect : f4 ambiguous
     2139
     2140        waitfor(f2, a1, b2); // Undefined behaviour : b2 not mutex
     2141}
     2142\end{cfa}
     2143\end{figure}
     2144
     2145Finally, for added flexibility, \CFA supports constructing a complex @waitfor@ statement using the @or@, @timeout@ and @else@.
     2146Indeed, multiple @waitfor@ clauses can be chained together using @or@; this chain forms a single statement that uses baton pass to any routine that fits one of the routine+monitor set passed in.
     2147To enable users to tell which accepted routine executed, @waitfor@s are followed by a statement (including the null statement @;@) or a compound statement, which is executed after the clause is triggered.
     2148A @waitfor@ chain can also be followed by a @timeout@, to signify an upper bound on the wait, or an @else@, to signify that the call should be non-blocking, which checks for a matching routine call already arrived and otherwise continues.
     2149Any and all of these clauses can be preceded by a @when@ condition to dynamically toggle the accept clauses on or off based on some current state.
     2150Figure~\ref{f:waitfor2} demonstrates several complex masks and some incorrect ones.
     2151
     2152\begin{figure}
     2153\lstset{language=CFA,deletedelim=**[is][]{`}{`}}
     2154\begin{cfa}
     2155monitor A{};
     2156
     2157void f1( A & mutex );
     2158void f2( A & mutex );
     2159
     2160void foo( A & mutex a, bool b, int t ) {
     2161        waitfor(f1, a);                                                 $\C{// Correct : blocking case}$
     2162
     2163        waitfor(f1, a) {                                                $\C{// Correct : block with statement}$
     2164                sout | "f1" | endl;
    21822165        }
    2183         // clean up
    2184 }
    2185 \end{cfa}
    2186 When the program main deallocates the buffer, it first calls the buffer's destructor, which is accepted, the destructor runs, and the buffer is deallocated.
    2187 However, the buffer thread cannot continue after the destructor call because the object is gone;
    2188 hence, clean up in @main@ cannot occur, which means destructors for local objects are not run.
    2189 To make this useful capability work, the semantics for accepting the destructor is the same as @signal@, \ie the destructor call is placed on urgent and the acceptor continues execution, which ends the loop, cleans up, and the thread terminates.
    2190 Then, the destructor caller unblocks from urgent to deallocate the object.
    2191 Accepting the destructor is the idiomatic way in \CFA to terminate a thread performing direct communication.
    2192 
    2193 
    2194 \subsection{Bulk Barging Prevention}
    2195 
    2196 Figure~\ref{f:BulkBargingPrevention} shows \CFA code where bulk acquire adds complexity to the internal-signalling semantics.
    2197 The complexity begins at the end of the inner @mutex@ statement, where the semantics of internal scheduling need to be extended for multiple monitors.
    2198 The problem is that bulk acquire is used in the inner @mutex@ statement where one of the monitors is already acquired.
    2199 When the signalling thread reaches the end of the inner @mutex@ statement, it should transfer ownership of @m1@ and @m2@ to the waiting threads to prevent barging into the outer @mutex@ statement by another thread.
    2200 However, both the signalling and waiting threads W1 and W2 need some subset of monitors @m1@ and @m2@.
    2201 \begin{cquote}
    2202 condition c: (order 1) W2(@m2@), W1(@m1@,@m2@)\ \ \ or\ \ \ (order 2) W1(@m1@,@m2@), W2(@m2@) \\
    2203 S: acq. @m1@ $\rightarrow$ acq. @m1,m2@ $\rightarrow$ @signal(c)@ $\rightarrow$ rel. @m2@ $\rightarrow$ pass @m2@ unblock W2 (order 2) $\rightarrow$ rel. @m1@ $\rightarrow$ pass @m1,m2@ unblock W1 \\
    2204 \hspace*{2.75in}$\rightarrow$ rel. @m1@ $\rightarrow$ pass @m1,m2@ unblock W1 (order 1)
    2205 \end{cquote}
    2206 
     2166        waitfor(f1, a) {                                                $\C{// Correct : block waiting for f1 or f2}$
     2167                sout | "f1" | endl;
     2168        } or waitfor(f2, a) {
     2169                sout | "f2" | endl;
     2170        }
     2171        waitfor(f1, a); or else;                                $\C{// Correct : non-blocking case}$
     2172
     2173        waitfor(f1, a) {                                                $\C{// Correct : non-blocking case}$
     2174                sout | "blocked" | endl;
     2175        } or else {
     2176                sout | "didn't block" | endl;
     2177        }
     2178        waitfor(f1, a) {                                                $\C{// Correct : block at most 10 seconds}$
     2179                sout | "blocked" | endl;
     2180        } or timeout( 10`s) {
     2181                sout | "didn't block" | endl;
     2182        }
     2183        // Correct : block only if b == true if b == false, don't even make the call
     2184        when(b) waitfor(f1, a);
     2185
     2186        // Correct : block only if b == true if b == false, make non-blocking call
     2187        waitfor(f1, a); or when(!b) else;
     2188
     2189        // Correct : block only of t > 1
     2190        waitfor(f1, a); or when(t > 1) timeout(t); or else;
     2191
     2192        // Incorrect : timeout clause is dead code
     2193        waitfor(f1, a); or timeout(t); or else;
     2194
     2195        // Incorrect : order must be waitfor [or waitfor... [or timeout] [or else]]
     2196        timeout(t); or waitfor(f1, a); or else;
     2197}
     2198\end{cfa}
     2199\caption{Correct and incorrect uses of the or, else, and timeout clause around a waitfor statement}
     2200\label{f:waitfor2}
     2201\end{figure}
     2202
     2203% ======================================================================
     2204% ======================================================================
     2205\subsection{Waiting For The Destructor}
     2206% ======================================================================
     2207% ======================================================================
     2208An interesting use for the @waitfor@ statement is destructor semantics.
     2209Indeed, the @waitfor@ statement can accept any @mutex@ routine, which includes the destructor (see section \ref{data}).
     2210However, with the semantics discussed until now, waiting for the destructor does not make any sense, since using an object after its destructor is called is undefined behaviour.
     2211The simplest approach is to disallow @waitfor@ on a destructor.
     2212However, a more expressive approach is to flip ordering of execution when waiting for the destructor, meaning that waiting for the destructor allows the destructor to run after the current @mutex@ routine, similarly to how a condition is signalled.
    22072213\begin{figure}
    2208 \newbox\myboxA
    2209 \begin{lrbox}{\myboxA}
    2210 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2211 monitor M m1, m2;
    2212 condition c;
    2213 mutex( m1 ) { // $\LstCommentStyle{\color{red}outer}$
    2214         ...
    2215         mutex( m1, m2 ) { // $\LstCommentStyle{\color{red}inner}$
    2216                 ... `signal( c )`; ...
    2217                 // m1, m2 still acquired
    2218         } // $\LstCommentStyle{\color{red}release m2}$
    2219         // m1 acquired
    2220 } // release m1
    2221 \end{cfa}
    2222 \end{lrbox}
    2223 
    2224 \newbox\myboxB
    2225 \begin{lrbox}{\myboxB}
    2226 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2227 
    2228 
    2229 mutex( m1 ) {
    2230         ...
    2231         mutex( m1, m2 ) {
    2232                 ... `wait( c )`; // release m1, m2
    2233                 // m1, m2 reacquired
    2234         } // $\LstCommentStyle{\color{red}release m2}$
    2235         // m1 acquired
    2236 } // release m1
    2237 \end{cfa}
    2238 \end{lrbox}
    2239 
    2240 \newbox\myboxC
    2241 \begin{lrbox}{\myboxC}
    2242 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2243 
    2244 
    2245 mutex( m2 ) {
    2246         ... `wait( c )`; // release m2
    2247         // m2 reacquired
    2248 } // $\LstCommentStyle{\color{red}release m2}$
    2249 
    2250 
    2251 
    2252 
    2253 \end{cfa}
    2254 \end{lrbox}
    2255 
    2256 \begin{cquote}
    2257 \subfloat[Signalling Thread (S)]{\label{f:SignallingThread}\usebox\myboxA}
    2258 \hspace{3\parindentlnth}
    2259 \subfloat[Waiting Thread (W1)]{\label{f:WaitingThread}\usebox\myboxB}
    2260 \hspace{2\parindentlnth}
    2261 \subfloat[Waiting Thread (W2)]{\label{f:OtherWaitingThread}\usebox\myboxC}
    2262 \end{cquote}
    2263 \caption{Bulk Barging Prevention}
    2264 \label{f:BulkBargingPrevention}
     2214\begin{cfa}[caption={Example of an executor which executes action in series until the destructor is called.},label={f:dtor-order}]
     2215monitor Executer {};
     2216struct  Action;
     2217
     2218void ^?{}   (Executer & mutex this);
     2219void execute(Executer & mutex this, const Action & );
     2220void run    (Executer & mutex this) {
     2221        while(true) {
     2222                   waitfor(execute, this);
     2223                or waitfor(^?{}   , this) {
     2224                        break;
     2225                }
     2226        }
     2227}
     2228\end{cfa}
    22652229\end{figure}
    2266 
    2267 One scheduling solution is for the signaller S to keep ownership of all locks until the last lock is ready to be transferred, because this semantics fits most closely to the behaviour of single-monitor scheduling.
    2268 However, this solution is inefficient if W2 waited first and can be immediate passed @m2@ when released, while S retains @m1@ until completion of the outer mutex statement.
    2269 If W1 waited first, the signaller must retain @m1@ amd @m2@ until completion of the outer mutex statement and then pass both to W1.
    2270 % Furthermore, there is an execution sequence where the signaller always finds waiter W2, and hence, waiter W1 starves.
    2271 To support this efficient semantics (and prevent barging), the implementation maintains a list of monitors acquired for each blocked thread.
    2272 When a signaller exits or waits in a monitor function/statement, the front waiter on urgent is unblocked if all its monitors are released.
    2273 Implementing a fast subset check for the necessary released monitors is important.
    2274 % The benefit is encapsulating complexity into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met.
    2275 
    2276 
    2277 \subsection{Loose Object Definitions}
    2278 \label{s:LooseObjectDefinitions}
    2279 
    2280 In an object-oriented programming language, a class includes an exhaustive list of operations.
    2281 A new class can add members via static inheritance but the subclass still has an exhaustive list of operations.
    2282 (Dynamic member adding, \eg JavaScript~\cite{JavaScript}, is not considered.)
    2283 In the object-oriented scenario, the type and all its operators are always present at compilation (even separate compilation), so it is possible to number the operations in a bit mask and use an $O(1)$ compare with a similar bit mask created for the operations specified in a @waitfor@.
    2284 
    2285 However, in \CFA, monitor functions can be statically added/removed in translation units, making a fast subset check difficult.
    2286 \begin{cfa}
    2287         monitor M { ... }; // common type, included in .h file
    2288 translation unit 1
    2289         void `f`( M & mutex m );
    2290         void g( M & mutex m ) { waitfor( `f`, m ); }
    2291 translation unit 2
    2292         void `f`( M & mutex m ); $\C{// replacing f and g for type M in this translation unit}$
    2293         void `g`( M & mutex m );
    2294         void h( M & mutex m ) { waitfor( `f`, m ) or waitfor( `g`, m ); } $\C{// extending type M in this translation unit}$
    2295 \end{cfa}
    2296 The @waitfor@ statements in each translation unit cannot form a unique bit-mask because the monitor type does not carry that information.
    2297 Hence, function pointers are used to identify the functions listed in the @waitfor@ statement, stored in a variable-sized array.
    2298 Then, the same implementation approach used for the urgent stack is used for the calling queue.
    2299 Each caller has a list of monitors acquired, and the @waitfor@ statement performs a (usually short) linear search matching functions in the @waitfor@ list with called functions, and then verifying the associated mutex locks can be transfers.
    2300 (A possible way to construct a dense mapping is at link or load-time.)
    2301 
    2302 
    2303 \subsection{Multi-Monitor Scheduling}
    2304 \label{s:Multi-MonitorScheduling}
    2305 
    2306 External scheduling, like internal scheduling, becomes significantly more complex for multi-monitor semantics.
    2307 Even in the simplest case, new semantics need to be established.
    2308 \begin{cfa}
    2309 monitor M { ... };
    2310 void f( M & mutex m1 );
    2311 void g( M & mutex m1, M & mutex m2 ) { `waitfor( f );` } $\C{// pass m1 or m2 to f?}$
    2312 \end{cfa}
    2313 The solution is for the programmer to disambiguate:
    2314 \begin{cfa}
    2315 waitfor( f, `m2` ); $\C{// wait for call to f with argument m2}$
    2316 \end{cfa}
    2317 Both locks are acquired by function @g@, so when function @f@ is called, the lock for monitor @m2@ is passed from @g@ to @f@, while @g@ still holds lock @m1@.
    2318 This behaviour can be extended to the multi-monitor @waitfor@ statement.
    2319 \begin{cfa}
    2320 monitor M { ... };
    2321 void f( M & mutex m1, M & mutex m2 );
    2322 void g( M & mutex m1, M & mutex m2 ) { waitfor( f, `m1, m2` ); $\C{// wait for call to f with arguments m1 and m2}$
    2323 \end{cfa}
    2324 Again, the set of monitors passed to the @waitfor@ statement must be entirely contained in the set of monitors already acquired by the accepting function.
    2325 Also, the order of the monitors in a @waitfor@ statement is unimportant.
    2326 
    2327 Figure~\ref{f:UnmatchedMutexSets} shows an example where, for internal and external scheduling with multiple monitors, a signalling or accepting thread must match exactly, \ie partial matching results in waiting.
    2328 For both examples, the set of monitors is disjoint so unblocking is impossible.
    2329 
     2230For example, listing \ref{f:dtor-order} shows an example of an executor with an infinite loop, which waits for the destructor to break out of this loop.
     2231Switching the semantic meaning introduces an idiomatic way to terminate a task and/or wait for its termination via destruction.
     2232
     2233
     2234% ######     #    ######     #    #       #       ####### #       ###  #####  #     #
     2235% #     #   # #   #     #   # #   #       #       #       #        #  #     # ##   ##
     2236% #     #  #   #  #     #  #   #  #       #       #       #        #  #       # # # #
     2237% ######  #     # ######  #     # #       #       #####   #        #   #####  #  #  #
     2238% #       ####### #   #   ####### #       #       #       #        #        # #     #
     2239% #       #     # #    #  #     # #       #       #       #        #  #     # #     #
     2240% #       #     # #     # #     # ####### ####### ####### ####### ###  #####  #     #
     2241\section{Parallelism}
     2242Historically, computer performance was about processor speeds and instruction counts.
     2243However, with heat dissipation being a direct consequence of speed increase, parallelism has become the new source for increased performance~\cite{Sutter05, Sutter05b}.
     2244In this decade, it is no longer reasonable to create a high-performance application without caring about parallelism.
     2245Indeed, parallelism is an important aspect of performance and more specifically throughput and hardware utilization.
     2246The lowest-level approach of parallelism is to use \textbf{kthread} in combination with semantics like @fork@, @join@, \etc.
     2247However, since these have significant costs and limitations, \textbf{kthread} are now mostly used as an implementation tool rather than a user oriented one.
     2248There are several alternatives to solve these issues that all have strengths and weaknesses.
     2249While there are many variations of the presented paradigms, most of these variations do not actually change the guarantees or the semantics, they simply move costs in order to achieve better performance for certain workloads.
     2250
     2251\section{Paradigms}
     2252\subsection{User-Level Threads}
     2253A direct improvement on the \textbf{kthread} approach is to use \textbf{uthread}.
     2254These threads offer most of the same features that the operating system already provides but can be used on a much larger scale.
     2255This approach is the most powerful solution as it allows all the features of multithreading, while removing several of the more expensive costs of kernel threads.
     2256The downside is that almost none of the low-level threading problems are hidden; users still have to think about data races, deadlocks and synchronization issues.
     2257These issues can be somewhat alleviated by a concurrency toolkit with strong guarantees, but the parallelism toolkit offers very little to reduce complexity in itself.
     2258
     2259Examples of languages that support \textbf{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
     2260
     2261\subsection{Fibers : User-Level Threads Without Preemption} \label{fibers}
     2262A popular variant of \textbf{uthread} is what is often referred to as \textbf{fiber}.
     2263However, \textbf{fiber} do not present meaningful semantic differences with \textbf{uthread}.
     2264The significant difference between \textbf{uthread} and \textbf{fiber} is the lack of \textbf{preemption} in the latter.
     2265Advocates of \textbf{fiber} list their high performance and ease of implementation as major strengths, but the performance difference between \textbf{uthread} and \textbf{fiber} is controversial, and the ease of implementation, while true, is a weak argument in the context of language design.
     2266Therefore this proposal largely ignores fibers.
     2267
     2268An example of a language that uses fibers is Go~\cite{Go}
     2269
     2270\subsection{Jobs and Thread Pools}
     2271An approach on the opposite end of the spectrum is to base parallelism on \textbf{pool}.
     2272Indeed, \textbf{pool} offer limited flexibility but at the benefit of a simpler user interface.
     2273In \textbf{pool} based systems, users express parallelism as units of work, called jobs, and a dependency graph (either explicit or implicit) that ties them together.
     2274This approach means users need not worry about concurrency but significantly limit the interaction that can occur among jobs.
     2275Indeed, any \textbf{job} that blocks also block the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably.
     2276It can be argued that a solution to this problem is to use more workers than available cores.
     2277However, unless the number of jobs and the number of workers are comparable, having a significant number of blocked jobs always results in idles cores.
     2278
     2279The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
     2280
     2281\subsection{Paradigm Performance}
     2282While the choice between the three paradigms listed above may have significant performance implications, it is difficult to pin down the performance implications of choosing a model at the language level.
     2283Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload.
     2284Having a large amount of mostly independent units of work to execute almost guarantees equivalent performance across paradigms and that the \textbf{pool}-based system has the best efficiency thanks to the lower memory overhead (\ie no thread stack per job).
     2285However, interactions among jobs can easily exacerbate contention.
     2286User-level threads allow fine-grain context switching, which results in better resource utilization, but a context switch is more expensive and the extra control means users need to tweak more variables to get the desired performance.
     2287Finally, if the units of uninterrupted work are large, enough the paradigm choice is largely amortized by the actual work done.
     2288
     2289\section{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
     2290A \textbf{cfacluster} is a group of \textbf{kthread} executed in isolation. \textbf{uthread} are scheduled on the \textbf{kthread} of a given \textbf{cfacluster}, allowing organization between \textbf{uthread} and \textbf{kthread}.
     2291It is important that \textbf{kthread} belonging to a same \textbf{cfacluster} have homogeneous settings, otherwise migrating a \textbf{uthread} from one \textbf{kthread} to the other can cause issues.
     2292A \textbf{cfacluster} also offers a pluggable scheduler that can optimize the workload generated by the \textbf{uthread}.
     2293
     2294\textbf{cfacluster} have not been fully implemented in the context of this paper.
     2295Currently \CFA only supports one \textbf{cfacluster}, the initial one.
     2296
     2297\subsection{Future Work: Machine Setup}\label{machine}
     2298While this was not done in the context of this paper, another important aspect of clusters is affinity.
     2299While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heterogeneous setups.
     2300For example, a system using \textbf{numa} configurations may benefit from users being able to tie clusters and/or kernel threads to certain CPU cores.
     2301OS support for CPU affinity is now common~\cite{affinityLinux, affinityWindows, affinityFreebsd, affinityNetbsd, affinityMacosx}, which means it is both possible and desirable for \CFA to offer an abstraction mechanism for portable CPU affinity.
     2302
     2303\subsection{Paradigms}\label{cfaparadigms}
     2304Given these building blocks, it is possible to reproduce all three of the popular paradigms.
     2305Indeed, \textbf{uthread} is the default paradigm in \CFA.
     2306However, disabling \textbf{preemption} on a cluster means threads effectively become fibers.
     2307Since several \textbf{cfacluster} with different scheduling policy can coexist in the same application, this allows \textbf{fiber} and \textbf{uthread} to coexist in the runtime of an application.
     2308Finally, it is possible to build executors for thread pools from \textbf{uthread} or \textbf{fiber}, which includes specialized jobs like actors~\cite{Actors}.
     2309
     2310
     2311
     2312\section{Behind the Scenes}
     2313There are several challenges specific to \CFA when implementing concurrency.
     2314These challenges are a direct result of bulk acquire and loose object definitions.
     2315These two constraints are the root cause of most design decisions in the implementation.
     2316Furthermore, to avoid contention from dynamically allocating memory in a concurrent environment, the internal-scheduling design is (almost) entirely free of mallocs.
     2317This approach avoids the chicken and egg problem~\cite{Chicken} of having a memory allocator that relies on the threading system and a threading system that relies on the runtime.
     2318This extra goal means that memory management is a constant concern in the design of the system.
     2319
     2320The main memory concern for concurrency is queues.
     2321All blocking operations are made by parking threads onto queues and all queues are designed with intrusive nodes, where each node has pre-allocated link fields for chaining, to avoid the need for memory allocation.
     2322Since several concurrency operations can use an unbound amount of memory (depending on bulk acquire), statically defining information in the intrusive fields of threads is insufficient.The only way to use a variable amount of memory without requiring memory allocation is to pre-allocate large buffers of memory eagerly and store the information in these buffers.
     2323Conveniently, the call stack fits that description and is easy to use, which is why it is used heavily in the implementation of internal scheduling, particularly variable-length arrays.
     2324Since stack allocation is based on scopes, the first step of the implementation is to identify the scopes that are available to store the information, and which of these can have a variable-length array.
     2325The threads and the condition both have a fixed amount of memory, while @mutex@ routines and blocking calls allow for an unbound amount, within the stack size.
     2326
     2327Note that since the major contributions of this paper are extending monitor semantics to bulk acquire and loose object definitions, any challenges that are not resulting of these characteristics of \CFA are considered as solved problems and therefore not discussed.
     2328
     2329% ======================================================================
     2330% ======================================================================
     2331\section{Mutex Routines}
     2332% ======================================================================
     2333% ======================================================================
     2334
     2335The first step towards the monitor implementation is simple @mutex@ routines.
     2336In the single monitor case, mutual-exclusion is done using the entry/exit procedure in listing \ref{f:entry1}.
     2337The entry/exit procedures do not have to be extended to support multiple monitors.
     2338Indeed it is sufficient to enter/leave monitors one-by-one as long as the order is correct to prevent deadlock~\cite{Havender68}.
     2339In \CFA, ordering of monitor acquisition relies on memory ordering.
     2340This approach is sufficient because all objects are guaranteed to have distinct non-overlapping memory layouts and mutual-exclusion for a monitor is only defined for its lifetime, meaning that destroying a monitor while it is acquired is undefined behaviour.
     2341When a mutex call is made, the concerned monitors are aggregated into a variable-length pointer array and sorted based on pointer values.
     2342This array persists for the entire duration of the mutual-exclusion and its ordering reused extensively.
    23302343\begin{figure}
    2331 \centering
    2332 \begin{lrbox}{\myboxA}
    2333 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2334 monitor M1 {} m11, m12;
    2335 monitor M2 {} m2;
    2336 condition c;
    2337 void f( M1 & mutex m1, M2 & mutex m2 ) {
    2338         signal( c );
    2339 }
    2340 void g( M1 & mutex m1, M2 & mutex m2 ) {
    2341         wait( c );
    2342 }
    2343 g( `m11`, m2 ); // block on wait
    2344 f( `m12`, m2 ); // cannot fulfil
    2345 \end{cfa}
    2346 \end{lrbox}
    2347 
    2348 \begin{lrbox}{\myboxB}
    2349 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2350 monitor M1 {} m11, m12;
    2351 monitor M2 {} m2;
    2352 
    2353 void f( M1 & mutex m1, M2 & mutex m2 ) {
    2354 
    2355 }
    2356 void g( M1 & mutex m1, M2 & mutex m2 ) {
    2357         waitfor( f, m1, m2 );
    2358 }
    2359 g( `m11`, m2 ); // block on accept
    2360 f( `m12`, m2 ); // cannot fulfil
    2361 \end{cfa}
    2362 \end{lrbox}
    2363 \subfloat[Internal scheduling]{\label{f:InternalScheduling}\usebox\myboxA}
    2364 \hspace{3pt}
    2365 \vrule
    2366 \hspace{3pt}
    2367 \subfloat[External scheduling]{\label{f:ExternalScheduling}\usebox\myboxB}
    2368 \caption{Unmatched \protect\lstinline@mutex@ sets}
    2369 \label{f:UnmatchedMutexSets}
     2344\begin{multicols}{2}
     2345Entry
     2346\begin{cfa}
     2347if monitor is free
     2348        enter
     2349elif already own the monitor
     2350        continue
     2351else
     2352        block
     2353increment recursions
     2354\end{cfa}
     2355\columnbreak
     2356Exit
     2357\begin{cfa}
     2358decrement recursion
     2359if recursion == 0
     2360        if entry queue not empty
     2361                wake-up thread
     2362\end{cfa}
     2363\end{multicols}
     2364\begin{cfa}[caption={Initial entry and exit routine for monitors},label={f:entry1}]
     2365\end{cfa}
    23702366\end{figure}
    23712367
    2372 
    2373 \subsection{\texorpdfstring{\protect\lstinline@mutex@ Threads}{mutex Threads}}
    2374 
    2375 Threads in \CFA can also be monitors to allow \emph{direct communication} among threads, \ie threads can have mutex functions that are called by other threads.
    2376 Hence, all monitor features are available when using threads.
    2377 Figure~\ref{f:DirectCommunication} shows a comparison of direct call communication in \CFA with direct channel communication in Go.
    2378 (Ada provides a similar mechanism to the \CFA direct communication.)
    2379 The program main in both programs communicates directly with the other thread versus indirect communication where two threads interact through a passive monitor.
    2380 Both direct and indirection thread communication are valuable tools in structuring concurrent programs.
     2368\subsection{Details: Interaction with polymorphism}
     2369Depending on the choice of semantics for when monitor locks are acquired, interaction between monitors and \CFA's concept of polymorphism can be more complex to support.
     2370However, it is shown that entry-point locking solves most of the issues.
     2371
     2372First of all, interaction between @otype@ polymorphism (see Section~\ref{s:ParametricPolymorphism}) and monitors is impossible since monitors do not support copying.
     2373Therefore, the main question is how to support @dtype@ polymorphism.
     2374It is important to present the difference between the two acquiring options: \textbf{callsite-locking} and entry-point locking, \ie acquiring the monitors before making a mutex routine-call or as the first operation of the mutex routine-call.
     2375For example:
     2376\begin{table}
     2377\begin{center}
     2378\begin{tabular}{|c|c|c|}
     2379Mutex & \textbf{callsite-locking} & \textbf{entry-point-locking} \\
     2380call & cfa-code & cfa-code \\
     2381\hline
     2382\begin{cfa}[tabsize=3]
     2383void foo(monitor& mutex a){
     2384
     2385        // Do Work
     2386        //...
     2387
     2388}
     2389
     2390void main() {
     2391        monitor a;
     2392
     2393        foo(a);
     2394
     2395}
     2396\end{cfa} & \begin{cfa}[tabsize=3]
     2397foo(& a) {
     2398
     2399        // Do Work
     2400        //...
     2401
     2402}
     2403
     2404main() {
     2405        monitor a;
     2406        acquire(a);
     2407        foo(a);
     2408        release(a);
     2409}
     2410\end{cfa} & \begin{cfa}[tabsize=3]
     2411foo(& a) {
     2412        acquire(a);
     2413        // Do Work
     2414        //...
     2415        release(a);
     2416}
     2417
     2418main() {
     2419        monitor a;
     2420
     2421        foo(a);
     2422
     2423}
     2424\end{cfa}
     2425\end{tabular}
     2426\end{center}
     2427\caption{Call-site vs entry-point locking for mutex calls}
     2428\label{tbl:locking-site}
     2429\end{table}
     2430
     2431Note the @mutex@ keyword relies on the type system, which means that in cases where a generic monitor-routine is desired, writing the mutex routine is possible with the proper trait, \eg:
     2432\begin{cfa}
     2433// Incorrect: T may not be monitor
     2434forall(dtype T)
     2435void foo(T * mutex t);
     2436
     2437// Correct: this routine only works on monitors (any monitor)
     2438forall(dtype T | is_monitor(T))
     2439void bar(T * mutex t));
     2440\end{cfa}
     2441
     2442Both entry point and \textbf{callsite-locking} are feasible implementations.
     2443The current \CFA implementation uses entry-point locking because it requires less work when using \textbf{raii}, effectively transferring the burden of implementation to object construction/destruction.
     2444It is harder to use \textbf{raii} for call-site locking, as it does not necessarily have an existing scope that matches exactly the scope of the mutual exclusion, \ie the routine body.
     2445For example, the monitor call can appear in the middle of an expression.
     2446Furthermore, entry-point locking requires less code generation since any useful routine is called multiple times but there is only one entry point for many call sites.
     2447
     2448% ======================================================================
     2449% ======================================================================
     2450\section{Threading} \label{impl:thread}
     2451% ======================================================================
     2452% ======================================================================
     2453
     2454Figure \ref{fig:system1} shows a high-level picture if the \CFA runtime system in regards to concurrency.
     2455Each component of the picture is explained in detail in the flowing sections.
    23812456
    23822457\begin{figure}
    2383 \centering
    2384 \begin{lrbox}{\myboxA}
    2385 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2386 
    2387 struct Msg { int i, j; };
    2388 thread GoRtn { int i;  float f;  Msg m; };
    2389 void mem1( GoRtn & mutex gortn, int i ) { gortn.i = i; }
    2390 void mem2( GoRtn & mutex gortn, float f ) { gortn.f = f; }
    2391 void mem3( GoRtn & mutex gortn, Msg m ) { gortn.m = m; }
    2392 void ^?{}( GoRtn & mutex ) {}
    2393 
    2394 void main( GoRtn & gortn ) with( gortn ) {  // thread starts
    2395 
    2396         for () {
    2397 
    2398                 `waitfor( mem1, gortn )` sout | i;  // wait for calls
    2399                 or `waitfor( mem2, gortn )` sout | f;
    2400                 or `waitfor( mem3, gortn )` sout | m.i | m.j;
    2401                 or `waitfor( ^?{}, gortn )` break;
    2402 
     2458\begin{center}
     2459{\resizebox{\textwidth}{!}{\input{system.pstex_t}}}
     2460\end{center}
     2461\caption{Overview of the entire system}
     2462\label{fig:system1}
     2463\end{figure}
     2464
     2465\subsection{Processors}
     2466Parallelism in \CFA is built around using processors to specify how much parallelism is desired. \CFA processors are object wrappers around kernel threads, specifically @pthread@s in the current implementation of \CFA.
     2467Indeed, any parallelism must go through operating-system libraries.
     2468However, \textbf{uthread} are still the main source of concurrency, processors are simply the underlying source of parallelism.
     2469Indeed, processor \textbf{kthread} simply fetch a \textbf{uthread} from the scheduler and run it; they are effectively executers for user-threads.
     2470The main benefit of this approach is that it offers a well-defined boundary between kernel code and user code, for example, kernel thread quiescing, scheduling and interrupt handling.
     2471Processors internally use coroutines to take advantage of the existing context-switching semantics.
     2472
     2473\subsection{Stack Management}
     2474One of the challenges of this system is to reduce the footprint as much as possible.
     2475Specifically, all @pthread@s created also have a stack created with them, which should be used as much as possible.
     2476Normally, coroutines also create their own stack to run on, however, in the case of the coroutines used for processors, these coroutines run directly on the \textbf{kthread} stack, effectively stealing the processor stack.
     2477The exception to this rule is the Main Processor, \ie the initial \textbf{kthread} that is given to any program.
     2478In order to respect C user expectations, the stack of the initial kernel thread, the main stack of the program, is used by the main user thread rather than the main processor, which can grow very large.
     2479
     2480\subsection{Context Switching}
     2481As mentioned in section \ref{coroutine}, coroutines are a stepping stone for implementing threading, because they share the same mechanism for context-switching between different stacks.
     2482To improve performance and simplicity, context-switching is implemented using the following assumption: all context-switches happen inside a specific routine call.
     2483This assumption means that the context-switch only has to copy the callee-saved registers onto the stack and then switch the stack registers with the ones of the target coroutine/thread.
     2484Note that the instruction pointer can be left untouched since the context-switch is always inside the same routine
     2485Threads, however, do not context-switch between each other directly.
     2486They context-switch to the scheduler.
     2487This method is called a 2-step context-switch and has the advantage of having a clear distinction between user code and the kernel where scheduling and other system operations happen.
     2488Obviously, this doubles the context-switch cost because threads must context-switch to an intermediate stack.
     2489The alternative 1-step context-switch uses the stack of the ``from'' thread to schedule and then context-switches directly to the ``to'' thread.
     2490However, the performance of the 2-step context-switch is still superior to a @pthread_yield@ (see section \ref{results}).
     2491Additionally, for users in need for optimal performance, it is important to note that having a 2-step context-switch as the default does not prevent \CFA from offering a 1-step context-switch (akin to the Microsoft @SwitchToFiber@~\cite{switchToWindows} routine).
     2492This option is not currently present in \CFA, but the changes required to add it are strictly additive.
     2493
     2494\subsection{Preemption} \label{preemption}
     2495Finally, an important aspect for any complete threading system is preemption.
     2496As mentioned in section \ref{basics}, preemption introduces an extra degree of uncertainty, which enables users to have multiple threads interleave transparently, rather than having to cooperate among threads for proper scheduling and CPU distribution.
     2497Indeed, preemption is desirable because it adds a degree of isolation among threads.
     2498In a fully cooperative system, any thread that runs a long loop can starve other threads, while in a preemptive system, starvation can still occur but it does not rely on every thread having to yield or block on a regular basis, which reduces significantly a programmer burden.
     2499Obviously, preemption is not optimal for every workload.
     2500However any preemptive system can become a cooperative system by making the time slices extremely large.
     2501Therefore, \CFA uses a preemptive threading system.
     2502
     2503Preemption in \CFA\footnote{Note that the implementation of preemption is strongly tied with the underlying threading system.
     2504For this reason, only the Linux implementation is cover, \CFA does not run on Windows at the time of writting} is based on kernel timers, which are used to run a discrete-event simulation.
     2505Every processor keeps track of the current time and registers an expiration time with the preemption system.
     2506When the preemption system receives a change in preemption, it inserts the time in a sorted order and sets a kernel timer for the closest one, effectively stepping through preemption events on each signal sent by the timer.
     2507These timers use the Linux signal {\tt SIGALRM}, which is delivered to the process rather than the kernel-thread.
     2508This results in an implementation problem, because when delivering signals to a process, the kernel can deliver the signal to any kernel thread for which the signal is not blocked, \ie:
     2509\begin{quote}
     2510A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked.
     2511If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.
     2512SIGNAL(7) - Linux Programmer's Manual
     2513\end{quote}
     2514For the sake of simplicity, and in order to prevent the case of having two threads receiving alarms simultaneously, \CFA programs block the {\tt SIGALRM} signal on every kernel thread except one.
     2515
     2516Now because of how involuntary context-switches are handled, the kernel thread handling {\tt SIGALRM} cannot also be a processor thread.
     2517Hence, involuntary context-switching is done by sending signal {\tt SIGUSR1} to the corresponding proces\-sor and having the thread yield from inside the signal handler.
     2518This approach effectively context-switches away from the signal handler back to the kernel and the signal handler frame is eventually unwound when the thread is scheduled again.
     2519As a result, a signal handler can start on one kernel thread and terminate on a second kernel thread (but the same user thread).
     2520It is important to note that signal handlers save and restore signal masks because user-thread migration can cause a signal mask to migrate from one kernel thread to another.
     2521This behaviour is only a problem if all kernel threads, among which a user thread can migrate, differ in terms of signal masks\footnote{Sadly, official POSIX documentation is silent on what distinguishes ``async-signal-safe'' routines from other routines}.
     2522However, since the kernel thread handling preemption requires a different signal mask, executing user threads on the kernel-alarm thread can cause deadlocks.
     2523For this reason, the alarm thread is in a tight loop around a system call to @sigwaitinfo@, requiring very little CPU time for preemption.
     2524One final detail about the alarm thread is how to wake it when additional communication is required (\eg on thread termination).
     2525This unblocking is also done using {\tt SIGALRM}, but sent through the @pthread_sigqueue@.
     2526Indeed, @sigwait@ can differentiate signals sent from @pthread_sigqueue@ from signals sent from alarms or the kernel.
     2527
     2528\subsection{Scheduler}
     2529Finally, an aspect that was not mentioned yet is the scheduling algorithm.
     2530Currently, the \CFA scheduler uses a single ready queue for all processors, which is the simplest approach to scheduling.
     2531Further discussion on scheduling is present in section \ref{futur:sched}.
     2532
     2533% ======================================================================
     2534% ======================================================================
     2535\section{Internal Scheduling} \label{impl:intsched}
     2536% ======================================================================
     2537% ======================================================================
     2538The following figure is the traditional illustration of a monitor (repeated from page~\pageref{fig:ClassicalMonitor} for convenience):
     2539
     2540\begin{figure}
     2541\begin{center}
     2542{\resizebox{0.4\textwidth}{!}{\input{monitor}}}
     2543\end{center}
     2544\caption{Traditional illustration of a monitor}
     2545\end{figure}
     2546
     2547This picture has several components, the two most important being the entry queue and the AS-stack.
     2548The entry queue is an (almost) FIFO list where threads waiting to enter are parked, while the acceptor/signaller (AS) stack is a FILO list used for threads that have been signalled or otherwise marked as running next.
     2549
     2550For \CFA, this picture does not have support for blocking multiple monitors on a single condition.
     2551To support bulk acquire two changes to this picture are required.
     2552First, it is no longer helpful to attach the condition to \emph{a single} monitor.
     2553Secondly, the thread waiting on the condition has to be separated across multiple monitors, seen in figure \ref{fig:monitor_cfa}.
     2554
     2555\begin{figure}
     2556\begin{center}
     2557{\resizebox{0.8\textwidth}{!}{\input{int_monitor}}}
     2558\end{center}
     2559\caption{Illustration of \CFA Monitor}
     2560\label{fig:monitor_cfa}
     2561\end{figure}
     2562
     2563This picture and the proper entry and leave algorithms (see listing \ref{f:entry2}) is the fundamental implementation of internal scheduling.
     2564Note that when a thread is moved from the condition to the AS-stack, it is conceptually split into N pieces, where N is the number of monitors specified in the parameter list.
     2565The thread is woken up when all the pieces have popped from the AS-stacks and made active.
     2566In this picture, the threads are split into halves but this is only because there are two monitors.
     2567For a specific signalling operation every monitor needs a piece of thread on its AS-stack.
     2568
     2569\begin{figure}
     2570\begin{multicols}{2}
     2571Entry
     2572\begin{cfa}
     2573if monitor is free
     2574        enter
     2575elif already own the monitor
     2576        continue
     2577else
     2578        block
     2579increment recursion
     2580
     2581\end{cfa}
     2582\columnbreak
     2583Exit
     2584\begin{cfa}
     2585decrement recursion
     2586if recursion == 0
     2587        if signal_stack not empty
     2588                set_owner to thread
     2589                if all monitors ready
     2590                        wake-up thread
     2591
     2592        if entry queue not empty
     2593                wake-up thread
     2594\end{cfa}
     2595\end{multicols}
     2596\begin{cfa}[caption={Entry and exit routine for monitors with internal scheduling},label={f:entry2}]
     2597\end{cfa}
     2598\end{figure}
     2599
     2600The solution discussed in \ref{s:InternalScheduling} can be seen in the exit routine of listing \ref{f:entry2}.
     2601Basically, the solution boils down to having a separate data structure for the condition queue and the AS-stack, and unconditionally transferring ownership of the monitors but only unblocking the thread when the last monitor has transferred ownership.
     2602This solution is deadlock safe as well as preventing any potential barging.
     2603The data structures used for the AS-stack are reused extensively for external scheduling, but in the case of internal scheduling, the data is allocated using variable-length arrays on the call stack of the @wait@ and @signal_block@ routines.
     2604
     2605\begin{figure}
     2606\begin{center}
     2607{\resizebox{0.8\textwidth}{!}{\input{monitor_structs.pstex_t}}}
     2608\end{center}
     2609\caption{Data structures involved in internal/external scheduling}
     2610\label{fig:structs}
     2611\end{figure}
     2612
     2613Figure \ref{fig:structs} shows a high-level representation of these data structures.
     2614The main idea behind them is that, a thread cannot contain an arbitrary number of intrusive ``next'' pointers for linking onto monitors.
     2615The @condition node@ is the data structure that is queued onto a condition variable and, when signalled, the condition queue is popped and each @condition criterion@ is moved to the AS-stack.
     2616Once all the criteria have been popped from their respective AS-stacks, the thread is woken up, which is what is shown in listing \ref{f:entry2}.
     2617
     2618% ======================================================================
     2619% ======================================================================
     2620\section{External Scheduling}
     2621% ======================================================================
     2622% ======================================================================
     2623Similarly to internal scheduling, external scheduling for multiple monitors relies on the idea that waiting-thread queues are no longer specific to a single monitor, as mentioned in section \ref{extsched}.
     2624For internal scheduling, these queues are part of condition variables, which are still unique for a given scheduling operation (\ie no signal statement uses multiple conditions).
     2625However, in the case of external scheduling, there is no equivalent object which is associated with @waitfor@ statements.
     2626This absence means the queues holding the waiting threads must be stored inside at least one of the monitors that is acquired.
     2627These monitors being the only objects that have sufficient lifetime and are available on both sides of the @waitfor@ statement.
     2628This requires an algorithm to choose which monitor holds the relevant queue.
     2629It is also important that said algorithm be independent of the order in which users list parameters.
     2630The proposed algorithm is to fall back on monitor lock ordering (sorting by address) and specify that the monitor that is acquired first is the one with the relevant waiting queue.
     2631This assumes that the lock acquiring order is static for the lifetime of all concerned objects but that is a reasonable constraint.
     2632
     2633This algorithm choice has two consequences:
     2634\begin{itemize}
     2635        \item The queue of the monitor with the lowest address is no longer a true FIFO queue because threads can be moved to the front of the queue.
     2636These queues need to contain a set of monitors for each of the waiting threads.
     2637Therefore, another thread whose set contains the same lowest address monitor but different lower priority monitors may arrive first but enter the critical section after a thread with the correct pairing.
     2638        \item The queue of the lowest priority monitor is both required and potentially unused.
     2639Indeed, since it is not known at compile time which monitor is the monitor which has the lowest address, every monitor needs to have the correct queues even though it is possible that some queues go unused for the entire duration of the program, for example if a monitor is only used in a specific pair.
     2640\end{itemize}
     2641Therefore, the following modifications need to be made to support external scheduling:
     2642\begin{itemize}
     2643        \item The threads waiting on the entry queue need to keep track of which routine they are trying to enter, and using which set of monitors.
     2644The @mutex@ routine already has all the required information on its stack, so the thread only needs to keep a pointer to that information.
     2645        \item The monitors need to keep a mask of acceptable routines.
     2646This mask contains for each acceptable routine, a routine pointer and an array of monitors to go with it.
     2647It also needs storage to keep track of which routine was accepted.
     2648Since this information is not specific to any monitor, the monitors actually contain a pointer to an integer on the stack of the waiting thread.
     2649Note that if a thread has acquired two monitors but executes a @waitfor@ with only one monitor as a parameter, setting the mask of acceptable routines to both monitors will not cause any problems since the extra monitor will not change ownership regardless.
     2650This becomes relevant when @when@ clauses affect the number of monitors passed to a @waitfor@ statement.
     2651        \item The entry/exit routines need to be updated as shown in listing \ref{f:entry3}.
     2652\end{itemize}
     2653
     2654\subsection{External Scheduling - Destructors}
     2655Finally, to support the ordering inversion of destructors, the code generation needs to be modified to use a special entry routine.
     2656This routine is needed because of the storage requirements of the call order inversion.
     2657Indeed, when waiting for the destructors, storage is needed for the waiting context and the lifetime of said storage needs to outlive the waiting operation it is needed for.
     2658For regular @waitfor@ statements, the call stack of the routine itself matches this requirement but it is no longer the case when waiting for the destructor since it is pushed on to the AS-stack for later.
     2659The @waitfor@ semantics can then be adjusted correspondingly, as seen in listing \ref{f:entry-dtor}
     2660
     2661\begin{figure}
     2662\begin{multicols}{2}
     2663Entry
     2664\begin{cfa}
     2665if monitor is free
     2666        enter
     2667elif already own the monitor
     2668        continue
     2669elif matches waitfor mask
     2670        push criteria to AS-stack
     2671        continue
     2672else
     2673        block
     2674increment recursion
     2675\end{cfa}
     2676\columnbreak
     2677Exit
     2678\begin{cfa}
     2679decrement recursion
     2680if recursion == 0
     2681        if signal_stack not empty
     2682                set_owner to thread
     2683                if all monitors ready
     2684                        wake-up thread
     2685                endif
     2686        endif
     2687
     2688        if entry queue not empty
     2689                wake-up thread
     2690        endif
     2691\end{cfa}
     2692\end{multicols}
     2693\begin{cfa}[caption={Entry and exit routine for monitors with internal scheduling and external scheduling},label={f:entry3}]
     2694\end{cfa}
     2695\end{figure}
     2696
     2697\begin{figure}
     2698\begin{multicols}{2}
     2699Destructor Entry
     2700\begin{cfa}
     2701if monitor is free
     2702        enter
     2703elif already own the monitor
     2704        increment recursion
     2705        return
     2706create wait context
     2707if matches waitfor mask
     2708        reset mask
     2709        push self to AS-stack
     2710        baton pass
     2711else
     2712        wait
     2713increment recursion
     2714\end{cfa}
     2715\columnbreak
     2716Waitfor
     2717\begin{cfa}
     2718if matching thread is already there
     2719        if found destructor
     2720                push destructor to AS-stack
     2721                unlock all monitors
     2722        else
     2723                push self to AS-stack
     2724                baton pass
     2725        endif
     2726        return
     2727endif
     2728if non-blocking
     2729        Unlock all monitors
     2730        Return
     2731endif
     2732
     2733push self to AS-stack
     2734set waitfor mask
     2735block
     2736return
     2737\end{cfa}
     2738\end{multicols}
     2739\begin{cfa}[caption={Pseudo code for the \protect\lstinline|waitfor| routine and the \protect\lstinline|mutex| entry routine for destructors},label={f:entry-dtor}]
     2740\end{cfa}
     2741\end{figure}
     2742
     2743
     2744% ======================================================================
     2745% ======================================================================
     2746\section{Putting It All Together}
     2747% ======================================================================
     2748% ======================================================================
     2749
     2750
     2751\section{Threads As Monitors}
     2752As it was subtly alluded in section \ref{threads}, @thread@s in \CFA are in fact monitors, which means that all monitor features are available when using threads.
     2753For example, here is a very simple two thread pipeline that could be used for a simulator of a game engine:
     2754\begin{figure}
     2755\begin{cfa}[caption={Toy simulator using \protect\lstinline|thread|s and \protect\lstinline|monitor|s.},label={f:engine-v1}]
     2756// Visualization declaration
     2757thread Renderer {} renderer;
     2758Frame * simulate( Simulator & this );
     2759
     2760// Simulation declaration
     2761thread Simulator{} simulator;
     2762void render( Renderer & this );
     2763
     2764// Blocking call used as communication
     2765void draw( Renderer & mutex this, Frame * frame );
     2766
     2767// Simulation loop
     2768void main( Simulator & this ) {
     2769        while( true ) {
     2770                Frame * frame = simulate( this );
     2771                draw( renderer, frame );
    24032772        }
    2404 
    2405 }
    2406 int main() {
    2407         GoRtn gortn; $\C[2.0in]{// start thread}$
    2408         `mem1( gortn, 0 );` $\C{// different calls}\CRT$
    2409         `mem2( gortn, 2.5 );`
    2410         `mem3( gortn, (Msg){1, 2} );`
    2411 
    2412 
    2413 } // wait for completion
    2414 \end{cfa}
    2415 \end{lrbox}
    2416 
    2417 \begin{lrbox}{\myboxB}
    2418 \begin{Go}[aboveskip=0pt,belowskip=0pt]
    2419 func main() {
    2420         type Msg struct{ i, j int }
    2421 
    2422         ch1 := make( chan int )
    2423         ch2 := make( chan float32 )
    2424         ch3 := make( chan Msg )
    2425         hand := make( chan string )
    2426         shake := make( chan string )
    2427         gortn := func() { $\C[1.5in]{// thread starts}$
    2428                 var i int;  var f float32;  var m Msg
    2429                 L: for {
    2430                         select { $\C{// wait for messages}$
    2431                           case `i = <- ch1`: fmt.Println( i )
    2432                           case `f = <- ch2`: fmt.Println( f )
    2433                           case `m = <- ch3`: fmt.Println( m )
    2434                           case `<- hand`: break L $\C{// sentinel}$
    2435                         }
     2773}
     2774
     2775// Rendering loop
     2776void main( Renderer & this ) {
     2777        while( true ) {
     2778                waitfor( draw, this );
     2779                render( this );
     2780        }
     2781}
     2782\end{cfa}
     2783\end{figure}
     2784One of the obvious complaints of the previous code snippet (other than its toy-like simplicity) is that it does not handle exit conditions and just goes on forever.
     2785Luckily, the monitor semantics can also be used to clearly enforce a shutdown order in a concise manner:
     2786\begin{figure}
     2787\begin{cfa}[caption={Same toy simulator with proper termination condition.},label={f:engine-v2}]
     2788// Visualization declaration
     2789thread Renderer {} renderer;
     2790Frame * simulate( Simulator & this );
     2791
     2792// Simulation declaration
     2793thread Simulator{} simulator;
     2794void render( Renderer & this );
     2795
     2796// Blocking call used as communication
     2797void draw( Renderer & mutex this, Frame * frame );
     2798
     2799// Simulation loop
     2800void main( Simulator & this ) {
     2801        while( true ) {
     2802                Frame * frame = simulate( this );
     2803                draw( renderer, frame );
     2804
     2805                // Exit main loop after the last frame
     2806                if( frame->is_last ) break;
     2807        }
     2808}
     2809
     2810// Rendering loop
     2811void main( Renderer & this ) {
     2812        while( true ) {
     2813                   waitfor( draw, this );
     2814                or waitfor( ^?{}, this ) {
     2815                        // Add an exit condition
     2816                        break;
    24362817                }
    2437                 `shake <- "SHAKE"` $\C{// completion}$
     2818
     2819                render( this );
    24382820        }
    2439 
    2440         go gortn() $\C{// start thread}$
    2441         `ch1 <- 0` $\C{// different messages}$
    2442         `ch2 <- 2.5`
    2443         `ch3 <- Msg{1, 2}`
    2444         `hand <- "HAND"` $\C{// sentinel value}$
    2445         `<- shake` $\C{// wait for completion}\CRT$
    2446 }
    2447 \end{Go}
    2448 \end{lrbox}
    2449 
    2450 \subfloat[\CFA]{\label{f:CFAwaitfor}\usebox\myboxA}
    2451 \hspace{3pt}
    2452 \vrule
    2453 \hspace{3pt}
    2454 \subfloat[Go]{\label{f:Gochannel}\usebox\myboxB}
    2455 \caption{Direct communication}
    2456 \label{f:DirectCommunication}
     2821}
     2822
     2823// Call destructor for simulator once simulator finishes
     2824// Call destructor for renderer to signify shutdown
     2825\end{cfa}
    24572826\end{figure}
    24582827
    2459 \begin{comment}
    2460 The following shows an example of two threads directly calling each other and accepting calls from each other in a cycle.
    2461 \begin{cfa}
    2462 \end{cfa}
    2463 \vspace{-0.8\baselineskip}
    2464 \begin{cquote}
    2465 \begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
    2466 \begin{cfa}
    2467 thread Ping {} pi;
    2468 void ping( Ping & mutex ) {}
    2469 void main( Ping & pi ) {
    2470         for ( 10 ) {
    2471                 `waitfor( ping, pi );`
    2472                 `pong( po );`
    2473         }
    2474 }
    2475 int main() {}
    2476 \end{cfa}
    2477 &
    2478 \begin{cfa}
    2479 thread Pong {} po;
    2480 void pong( Pong & mutex ) {}
    2481 void main( Pong & po ) {
    2482         for ( 10 ) {
    2483                 `ping( pi );`
    2484                 `waitfor( pong, po );`
    2485         }
    2486 }
    2487 
    2488 \end{cfa}
    2489 \end{tabular}
    2490 \end{cquote}
    2491 % \lstMakeShortInline@%
    2492 % \caption{Threads ping/pong using external scheduling}
    2493 % \label{f:pingpong}
    2494 % \end{figure}
    2495 Note, the ping/pong threads are globally declared, @pi@/@po@, and hence, start (and possibly complete) before the program main starts.
    2496 \end{comment}
    2497 
    2498 
    2499 \subsection{Execution Properties}
    2500 
    2501 Table~\ref{t:ObjectPropertyComposition} shows how the \CFA high-level constructs cover 3 fundamental execution properties: thread, stateful function, and mutual exclusion.
    2502 Case 1 is a basic object, with none of the new execution properties.
    2503 Case 2 allows @mutex@ calls to Case 1 to protect shared data.
    2504 Case 3 allows stateful functions to suspend/resume but restricts operations because the state is stackless.
    2505 Case 4 allows @mutex@ calls to Case 3 to protect shared data.
    2506 Cases 5 and 6 are the same as 3 and 4 without restriction because the state is stackful.
    2507 Cases 7 and 8 are rejected because a thread cannot execute without a stackful state in a preemptive environment when context switching from the signal handler.
    2508 Cases 9 and 10 have a stackful thread without and with @mutex@ calls.
    2509 For situations where threads do not require direct communication, case 9 provides faster creation/destruction by eliminating @mutex@ setup.
    2510 
     2828\section{Fibers \& Threads}
     2829As mentioned in section \ref{preemption}, \CFA uses preemptive threads by default but can use fibers on demand.
     2830Currently, using fibers is done by adding the following line of code to the program~:
     2831\begin{cfa}
     2832unsigned int default_preemption() {
     2833        return 0;
     2834}
     2835\end{cfa}
     2836This routine is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, \ie no preemption.
     2837However, once clusters are fully implemented, it will be possible to create fibers and \textbf{uthread} in the same system, as in listing \ref{f:fiber-uthread}
     2838\begin{figure}
     2839\lstset{language=CFA,deletedelim=**[is][]{`}{`}}
     2840\begin{cfa}[caption={Using fibers and \textbf{uthread} side-by-side in \CFA},label={f:fiber-uthread}]
     2841// Cluster forward declaration
     2842struct cluster;
     2843
     2844// Processor forward declaration
     2845struct processor;
     2846
     2847// Construct clusters with a preemption rate
     2848void ?{}(cluster& this, unsigned int rate);
     2849// Construct processor and add it to cluster
     2850void ?{}(processor& this, cluster& cluster);
     2851// Construct thread and schedule it on cluster
     2852void ?{}(thread& this, cluster& cluster);
     2853
     2854// Declare two clusters
     2855cluster thread_cluster = { 10`ms };                     // Preempt every 10 ms
     2856cluster fibers_cluster = { 0 };                         // Never preempt
     2857
     2858// Construct 4 processors
     2859processor processors[4] = {
     2860        //2 for the thread cluster
     2861        thread_cluster;
     2862        thread_cluster;
     2863        //2 for the fibers cluster
     2864        fibers_cluster;
     2865        fibers_cluster;
     2866};
     2867
     2868// Declares thread
     2869thread UThread {};
     2870void ?{}(UThread& this) {
     2871        // Construct underlying thread to automatically
     2872        // be scheduled on the thread cluster
     2873        (this){ thread_cluster }
     2874}
     2875
     2876void main(UThread & this);
     2877
     2878// Declares fibers
     2879thread Fiber {};
     2880void ?{}(Fiber& this) {
     2881        // Construct underlying thread to automatically
     2882        // be scheduled on the fiber cluster
     2883        (this.__thread){ fibers_cluster }
     2884}
     2885
     2886void main(Fiber & this);
     2887\end{cfa}
     2888\end{figure}
     2889
     2890
     2891% ======================================================================
     2892% ======================================================================
     2893\section{Performance Results} \label{results}
     2894% ======================================================================
     2895% ======================================================================
     2896\section{Machine Setup}
     2897Table \ref{tab:machine} shows the characteristics of the machine used to run the benchmarks.
     2898All tests were made on this machine.
    25112899\begin{table}
    2512 \caption{Object property composition}
    2513 \centering
    2514 \label{t:ObjectPropertyComposition}
    2515 \renewcommand{\arraystretch}{1.25}
    2516 %\setlength{\tabcolsep}{5pt}
    2517 \begin{tabular}{c|c||l|l}
    2518 \multicolumn{2}{c||}{object properties} & \multicolumn{2}{c}{mutual exclusion} \\
     2900\begin{center}
     2901\begin{tabular}{| l | r | l | r |}
    25192902\hline
    2520 thread  & stateful                              & \multicolumn{1}{c|}{No} & \multicolumn{1}{c}{Yes} \\
     2903Architecture            & x86\_64                       & NUMA node(s)  & 8 \\
     2904\hline
     2905CPU op-mode(s)          & 32-bit, 64-bit                & Model name    & AMD Opteron\texttrademark  Processor 6380 \\
     2906\hline
     2907Byte Order                      & Little Endian                 & CPU Freq              & 2.5\si{\giga\hertz} \\
     2908\hline
     2909CPU(s)                  & 64                            & L1d cache     & \SI{16}{\kibi\byte} \\
     2910\hline
     2911Thread(s) per core      & 2                             & L1i cache     & \SI{64}{\kibi\byte} \\
     2912\hline
     2913Core(s) per socket      & 8                             & L2 cache              & \SI{2048}{\kibi\byte} \\
     2914\hline
     2915Socket(s)                       & 4                             & L3 cache              & \SI{6144}{\kibi\byte} \\
    25212916\hline
    25222917\hline
    2523 No              & No                                    & \textbf{1}\ \ \ aggregate type                & \textbf{2}\ \ \ @monitor@ aggregate type \\
     2918Operating system                & Ubuntu 16.04.3 LTS    & Kernel                & Linux 4.4-97-generic \\
    25242919\hline
    2525 No              & Yes (stackless)               & \textbf{3}\ \ \ @generator@                   & \textbf{4}\ \ \ @monitor@ @generator@ \\
     2920Compiler                        & GCC 6.3               & Translator    & CFA 1 \\
    25262921\hline
    2527 No              & Yes (stackful)                & \textbf{5}\ \ \ @coroutine@                   & \textbf{6}\ \ \ @monitor@ @coroutine@ \\
     2922Java version            & OpenJDK-9             & Go version    & 1.9.2 \\
    25282923\hline
    2529 Yes             & No / Yes (stackless)  & \textbf{7}\ \ \ {\color{red}rejected} & \textbf{8}\ \ \ {\color{red}rejected} \\
     2924\end{tabular}
     2925\end{center}
     2926\caption{Machine setup used for the tests}
     2927\label{tab:machine}
     2928\end{table}
     2929
     2930\section{Micro Benchmarks}
     2931All benchmarks are run using the same harness to produce the results, seen as the @BENCH()@ macro in the following examples.
     2932This macro uses the following logic to benchmark the code:
     2933\begin{cfa}
     2934#define BENCH(run, result) \
     2935        before = gettime(); \
     2936        run; \
     2937        after  = gettime(); \
     2938        result = (after - before) / N;
     2939\end{cfa}
     2940The method used to get time is @clock_gettime(CLOCK_THREAD_CPUTIME_ID);@.
     2941Each benchmark is using many iterations of a simple call to measure the cost of the call.
     2942The specific number of iterations depends on the specific benchmark.
     2943
     2944\subsection{Context-Switching}
     2945The first interesting benchmark is to measure how long context-switches take.
     2946The simplest approach to do this is to yield on a thread, which executes a 2-step context switch.
     2947Yielding causes the thread to context-switch to the scheduler and back, more precisely: from the \textbf{uthread} to the \textbf{kthread} then from the \textbf{kthread} back to the same \textbf{uthread} (or a different one in the general case).
     2948In order to make the comparison fair, coroutines also execute a 2-step context-switch by resuming another coroutine which does nothing but suspending in a tight loop, which is a resume/suspend cycle instead of a yield.
     2949Figure~\ref{f:ctx-switch} shows the code for coroutines and threads with the results in table \ref{tab:ctx-switch}.
     2950All omitted tests are functionally identical to one of these tests.
     2951The difference between coroutines and threads can be attributed to the cost of scheduling.
     2952\begin{figure}
     2953\begin{multicols}{2}
     2954\CFA Coroutines
     2955\begin{cfa}
     2956coroutine GreatSuspender {};
     2957void main(GreatSuspender& this) {
     2958        while(true) { suspend(); }
     2959}
     2960int main() {
     2961        GreatSuspender s;
     2962        resume(s);
     2963        BENCH(
     2964                for(size_t i=0; i<n; i++) {
     2965                        resume(s);
     2966                },
     2967                result
     2968        )
     2969        printf("%llu\n", result);
     2970}
     2971\end{cfa}
     2972\columnbreak
     2973\CFA Threads
     2974\begin{cfa}
     2975
     2976
     2977
     2978
     2979int main() {
     2980
     2981
     2982        BENCH(
     2983                for(size_t i=0; i<n; i++) {
     2984                        yield();
     2985                },
     2986                result
     2987        )
     2988        printf("%llu\n", result);
     2989}
     2990\end{cfa}
     2991\end{multicols}
     2992\begin{cfa}[caption={\CFA benchmark code used to measure context-switches for coroutines and threads.},label={f:ctx-switch}]
     2993\end{cfa}
     2994\end{figure}
     2995
     2996\begin{table}
     2997\begin{center}
     2998\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
     2999\cline{2-4}
     3000\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
    25303001\hline
    2531 Yes             & Yes (stackful)                & \textbf{9}\ \ \ @thread@                              & \textbf{10}\ \ @monitor@ @thread@ \\
     3002Kernel Thread   & 241.5 & 243.86        & 5.08 \\
     3003\CFA Coroutine  & 38            & 38            & 0    \\
     3004\CFA Thread             & 103           & 102.96        & 2.96 \\
     3005\uC Coroutine   & 46            & 45.86 & 0.35 \\
     3006\uC Thread              & 98            & 99.11 & 1.42 \\
     3007Goroutine               & 150           & 149.96        & 3.16 \\
     3008Java Thread             & 289           & 290.68        & 8.72 \\
     3009\hline
    25323010\end{tabular}
     3011\end{center}
     3012\caption{Context Switch comparison.
     3013All numbers are in nanoseconds(\si{\nano\second})}
     3014\label{tab:ctx-switch}
    25333015\end{table}
    25343016
    2535 
    2536 \subsection{Low-level Locks}
    2537 
    2538 For completeness and efficiency, \CFA provides a standard set of low-level locks: recursive mutex, condition, semaphore, barrier, \etc, and atomic instructions: @fetchAssign@, @fetchAdd@, @testSet@, @compareSet@, \etc.
    2539 Some of these low-level mechanism are used in the \CFA runtime, but we strongly advocate using high-level mechanisms whenever possible.
    2540 
    2541 
    2542 % \section{Parallelism}
    2543 % \label{s:Parallelism}
    2544 %
    2545 % Historically, computer performance was about processor speeds.
    2546 % However, with heat dissipation being a direct consequence of speed increase, parallelism is the new source for increased performance~\cite{Sutter05, Sutter05b}.
    2547 % Therefore, high-performance applications must care about parallelism, which requires concurrency.
    2548 % The lowest-level approach of parallelism is to use \newterm{kernel threads} in combination with semantics like @fork@, @join@, \etc.
    2549 % However, kernel threads are better as an implementation tool because of complexity and higher cost.
    2550 % Therefore, different abstractions are often layered onto kernel threads to simplify them, \eg pthreads.
    2551 %
    2552 %
    2553 % \subsection{User Threads}
    2554 %
    2555 % A direct improvement on kernel threads is user threads, \eg Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
    2556 % This approach provides an interface that matches the language paradigms, gives more control over concurrency by the language runtime, and an abstract (and portable) interface to the underlying kernel threads across operating systems.
    2557 % In many cases, user threads can be used on a much larger scale (100,000 threads).
    2558 % Like kernel threads, user threads support preemption, which maximizes nondeterminism, but increases the potential for concurrency errors: race, livelock, starvation, and deadlock.
    2559 % \CFA adopts user-threads to provide more flexibility and a low-cost mechanism to build any other concurrency approach, \eg thread pools and actors~\cite{Actors}.
    2560 %
    2561 % A variant of user thread is \newterm{fibres}, which removes preemption, \eg Go~\cite{Go} @goroutine@s.
    2562 % Like functional programming, which removes mutation and its associated problems, removing preemption from concurrency reduces nondeterminism, making race and deadlock errors more difficult to generate.
    2563 % However, preemption is necessary for fairness and to reduce tail-latency.
    2564 % For concurrency that relies on spinning, if all cores spin the system is livelocked, whereas preemption breaks the livelock.
    2565 
    2566 
    2567 \begin{comment}
    2568 \subsection{Thread Pools}
    2569 
    2570 In contrast to direct threading is indirect \newterm{thread pools}, \eg Java @executor@, where small jobs (work units) are inserted into a work pool for execution.
    2571 If the jobs are dependent, \ie interact, there is an implicit/explicit dependency graph that ties them together.
    2572 While removing direct concurrency, and hence the amount of context switching, thread pools significantly limit the interaction that can occur among jobs.
    2573 Indeed, jobs should not block because that also blocks the underlying thread, which effectively means the CPU utilization, and therefore throughput, suffers.
    2574 While it is possible to tune the thread pool with sufficient threads, it becomes difficult to obtain high throughput and good core utilization as job interaction increases.
    2575 As well, concurrency errors return, which threads pools are suppose to mitigate.
     3017\subsection{Mutual-Exclusion}
     3018The next interesting benchmark is to measure the overhead to enter/leave a critical-section.
     3019For monitors, the simplest approach is to measure how long it takes to enter and leave a monitor routine.
     3020Figure~\ref{f:mutex} shows the code for \CFA.
     3021To put the results in context, the cost of entering a non-inline routine and the cost of acquiring and releasing a @pthread_mutex@ lock is also measured.
     3022The results can be shown in table \ref{tab:mutex}.
    25763023
    25773024\begin{figure}
    2578 \centering
    2579 \begin{tabular}{@{}l|l@{}}
    2580 \begin{cfa}
    2581 struct Adder {
    2582     int * row, cols;
    2583 };
    2584 int operator()() {
    2585         subtotal = 0;
    2586         for ( int c = 0; c < cols; c += 1 )
    2587                 subtotal += row[c];
    2588         return subtotal;
    2589 }
    2590 void ?{}( Adder * adder, int row[$\,$], int cols, int & subtotal ) {
    2591         adder.[rows, cols, subtotal] = [rows, cols, subtotal];
    2592 }
    2593 
    2594 
    2595 
    2596 
    2597 \end{cfa}
    2598 &
    2599 \begin{cfa}
     3025\begin{cfa}[caption={\CFA benchmark code used to measure mutex routines.},label={f:mutex}]
     3026monitor M {};
     3027void __attribute__((noinline)) call( M & mutex m /*, m2, m3, m4*/ ) {}
     3028
    26003029int main() {
    2601         const int rows = 10, cols = 10;
    2602         int matrix[rows][cols], subtotals[rows], total = 0;
    2603         // read matrix
    2604         Executor executor( 4 ); // kernel threads
    2605         Adder * adders[rows];
    2606         for ( r; rows ) { // send off work for executor
    2607                 adders[r] = new( matrix[r], cols, &subtotal[r] );
    2608                 executor.send( *adders[r] );
    2609         }
    2610         for ( r; rows ) {       // wait for results
    2611                 delete( adders[r] );
    2612                 total += subtotals[r];
    2613         }
    2614         sout | total;
    2615 }
    2616 \end{cfa}
     3030        M m/*, m2, m3, m4*/;
     3031        BENCH(
     3032                for(size_t i=0; i<n; i++) {
     3033                        call(m/*, m2, m3, m4*/);
     3034                },
     3035                result
     3036        )
     3037        printf("%llu\n", result);
     3038}
     3039\end{cfa}
     3040\end{figure}
     3041
     3042\begin{table}
     3043\begin{center}
     3044\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
     3045\cline{2-4}
     3046\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
     3047\hline
     3048C routine                                               & 2             & 2             & 0    \\
     3049FetchAdd + FetchSub                             & 26            & 26            & 0    \\
     3050Pthreads Mutex Lock                             & 31            & 31.86 & 0.99 \\
     3051\uC @monitor@ member routine            & 30            & 30            & 0    \\
     3052\CFA @mutex@ routine, 1 argument        & 41            & 41.57 & 0.9  \\
     3053\CFA @mutex@ routine, 2 argument        & 76            & 76.96 & 1.57 \\
     3054\CFA @mutex@ routine, 4 argument        & 145           & 146.68        & 3.85 \\
     3055Java synchronized routine                       & 27            & 28.57 & 2.6  \\
     3056\hline
    26173057\end{tabular}
    2618 \caption{Executor}
     3058\end{center}
     3059\caption{Mutex routine comparison.
     3060All numbers are in nanoseconds(\si{\nano\second})}
     3061\label{tab:mutex}
     3062\end{table}
     3063
     3064\subsection{Internal Scheduling}
     3065The internal-scheduling benchmark measures the cost of waiting on and signalling a condition variable.
     3066Figure~\ref{f:int-sched} shows the code for \CFA, with results table \ref{tab:int-sched}.
     3067As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
     3068
     3069\begin{figure}
     3070\begin{cfa}[caption={Benchmark code for internal scheduling},label={f:int-sched}]
     3071volatile int go = 0;
     3072condition c;
     3073monitor M {};
     3074M m1;
     3075
     3076void __attribute__((noinline)) do_call( M & mutex a1 ) { signal(c); }
     3077
     3078thread T {};
     3079void ^?{}( T & mutex this ) {}
     3080void main( T & this ) {
     3081        while(go == 0) { yield(); }
     3082        while(go == 1) { do_call(m1); }
     3083}
     3084int  __attribute__((noinline)) do_wait( M & mutex a1 ) {
     3085        go = 1;
     3086        BENCH(
     3087                for(size_t i=0; i<n; i++) {
     3088                        wait(c);
     3089                },
     3090                result
     3091        )
     3092        printf("%llu\n", result);
     3093        go = 0;
     3094        return 0;
     3095}
     3096int main() {
     3097        T t;
     3098        return do_wait(m1);
     3099}
     3100\end{cfa}
    26193101\end{figure}
    2620 \end{comment}
    2621 
    2622 
    2623 \section{Runtime Structure}
    2624 \label{s:CFARuntimeStructure}
    2625 
    2626 Figure~\ref{f:RunTimeStructure} illustrates the runtime structure of a \CFA program.
    2627 In addition to the new kinds of objects introduced by \CFA, there are two more runtime entities used to control parallel execution: cluster and (virtual) processor.
    2628 An executing thread is illustrated by its containment in a processor.
     3102
     3103\begin{table}
     3104\begin{center}
     3105\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
     3106\cline{2-4}
     3107\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
     3108\hline
     3109Pthreads Condition Variable                     & 5902.5        & 6093.29       & 714.78 \\
     3110\uC @signal@                                    & 322           & 323   & 3.36   \\
     3111\CFA @signal@, 1 @monitor@      & 352.5 & 353.11        & 3.66   \\
     3112\CFA @signal@, 2 @monitor@      & 430           & 430.29        & 8.97   \\
     3113\CFA @signal@, 4 @monitor@      & 594.5 & 606.57        & 18.33  \\
     3114Java @notify@                           & 13831.5       & 15698.21      & 4782.3 \\
     3115\hline
     3116\end{tabular}
     3117\end{center}
     3118\caption{Internal scheduling comparison.
     3119All numbers are in nanoseconds(\si{\nano\second})}
     3120\label{tab:int-sched}
     3121\end{table}
     3122
     3123\subsection{External Scheduling}
     3124The Internal scheduling benchmark measures the cost of the @waitfor@ statement (@_Accept@ in \uC).
     3125Figure~\ref{f:ext-sched} shows the code for \CFA, with results in table \ref{tab:ext-sched}.
     3126As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
    26293127
    26303128\begin{figure}
    2631 \centering
    2632 \input{RunTimeStructure}
    2633 \caption{\CFA Runtime structure}
    2634 \label{f:RunTimeStructure}
     3129\begin{cfa}[caption={Benchmark code for external scheduling},label={f:ext-sched}]
     3130volatile int go = 0;
     3131monitor M {};
     3132M m1;
     3133thread T {};
     3134
     3135void __attribute__((noinline)) do_call( M & mutex a1 ) {}
     3136
     3137void ^?{}( T & mutex this ) {}
     3138void main( T & this ) {
     3139        while(go == 0) { yield(); }
     3140        while(go == 1) { do_call(m1); }
     3141}
     3142int  __attribute__((noinline)) do_wait( M & mutex a1 ) {
     3143        go = 1;
     3144        BENCH(
     3145                for(size_t i=0; i<n; i++) {
     3146                        waitfor(call, a1);
     3147                },
     3148                result
     3149        )
     3150        printf("%llu\n", result);
     3151        go = 0;
     3152        return 0;
     3153}
     3154int main() {
     3155        T t;
     3156        return do_wait(m1);
     3157}
     3158\end{cfa}
    26353159\end{figure}
    26363160
    2637 
    2638 \subsection{Cluster}
    2639 \label{s:RuntimeStructureCluster}
    2640 
    2641 A \newterm{cluster} is a collection of threads and virtual processors (abstract kernel-thread) that execute the (user) threads from its own ready queue (like an OS executing kernel threads).
    2642 The purpose of a cluster is to control the amount of parallelism that is possible among threads, plus scheduling and other execution defaults.
    2643 The default cluster-scheduler is single-queue multi-server, which provides automatic load-balancing of threads on processors.
    2644 However, the design allows changing the scheduler, \eg multi-queue multi-server with work-stealing/sharing across the virtual processors.
    2645 If several clusters exist, both threads and virtual processors, can be explicitly migrated from one cluster to another.
    2646 No automatic load balancing among clusters is performed by \CFA.
    2647 
    2648 When a \CFA program begins execution, it creates a user cluster with a single processor and a special processor to handle preemption that does not execute user threads.
    2649 The user cluster is created to contain the application user-threads.
    2650 Having all threads execute on the one cluster often maximizes utilization of processors, which minimizes runtime.
    2651 However, because of limitations of scheduling requirements (real-time), NUMA architecture, heterogeneous hardware, or issues with the underlying operating system, multiple clusters are sometimes necessary.
    2652 
    2653 
    2654 \subsection{Virtual Processor}
    2655 \label{s:RuntimeStructureProcessor}
    2656 
    2657 A virtual processor is implemented by a kernel thread (\eg UNIX process), which are scheduled for execution on a hardware processor by the underlying operating system.
    2658 Programs may use more virtual processors than hardware processors.
    2659 On a multiprocessor, kernel threads are distributed across the hardware processors resulting in virtual processors executing in parallel.
    2660 (It is possible to use affinity to lock a virtual processor onto a particular hardware processor~\cite{affinityLinux, affinityWindows, affinityFreebsd, affinityNetbsd, affinityMacosx}, which is used when caching issues occur or for heterogeneous hardware processors.)
    2661 The \CFA runtime attempts to block unused processors and unblock processors as the system load increases;
    2662 balancing the workload with processors is difficult because it requires future knowledge, \ie what will the applicaton workload do next.
    2663 Preemption occurs on virtual processors rather than user threads, via operating-system interrupts.
    2664 Thus virtual processors execute user threads, where preemption frequency applies to a virtual processor, so preemption occurs randomly across the executed user threads.
    2665 Turning off preemption transforms user threads into fibres.
    2666 
    2667 
    2668 \begin{comment}
    2669 \section{Implementation}
    2670 \label{s:Implementation}
    2671 
    2672 A primary implementation challenge is avoiding contention from dynamically allocating memory because of bulk acquire, \eg the internal-scheduling design is (almost) free of allocations.
    2673 All blocking operations are made by parking threads onto queues, therefore all queues are designed with intrusive nodes, where each node has preallocated link fields for chaining.
    2674 Furthermore, several bulk-acquire operations need a variable amount of memory.
    2675 This storage is allocated at the base of a thread's stack before blocking, which means programmers must add a small amount of extra space for stacks.
    2676 
    2677 In \CFA, ordering of monitor acquisition relies on memory ordering to prevent deadlock~\cite{Havender68}, because all objects have distinct non-overlapping memory layouts, and mutual-exclusion for a monitor is only defined for its lifetime.
    2678 When a mutex call is made, pointers to the concerned monitors are aggregated into a variable-length array and sorted.
    2679 This array persists for the entire duration of the mutual exclusion and is used extensively for synchronization operations.
    2680 
    2681 To improve performance and simplicity, context switching occurs inside a function call, so only callee-saved registers are copied onto the stack and then the stack register is switched;
    2682 the corresponding registers are then restored for the other context.
    2683 Note, the instruction pointer is untouched since the context switch is always inside the same function.
    2684 Experimental results (not presented) for a stackless or stackful scheduler (1 versus 2 context switches) (see Section~\ref{s:Concurrency}) show the performance is virtually equivalent, because both approaches are dominated by locking to prevent a race condition.
    2685 
    2686 All kernel threads (@pthreads@) created a stack.
    2687 Each \CFA virtual processor is implemented as a coroutine and these coroutines run directly on the kernel-thread stack, effectively stealing this stack.
    2688 The exception to this rule is the program main, \ie the initial kernel thread that is given to any program.
    2689 In order to respect C expectations, the stack of the initial kernel thread is used by program main rather than the main processor, allowing it to grow dynamically as in a normal C program.
    2690 \end{comment}
    2691 
    2692 
    2693 \subsection{Preemption}
    2694 
    2695 Nondeterministic preemption provides fairness from long-running threads, and forces concurrent programmers to write more robust programs, rather than relying on code between cooperative scheduling to be atomic.
    2696 This atomic reliance can fail on multi-core machines, because execution across cores is nondeterministic.
    2697 A different reason for not supporting preemption is that it significantly complicates the runtime system, \eg Microsoft runtime does not support interrupts and on Linux systems, interrupts are complex (see below).
    2698 Preemption is normally handled by setting a countdown timer on each virtual processor.
    2699 When the timer expires, an interrupt is delivered, and the interrupt handler resets the countdown timer, and if the virtual processor is executing in user code, the signal handler performs a user-level context-switch, or if executing in the language runtime kernel, the preemption is ignored or rolled forward to the point where the runtime kernel context switches back to user code.
    2700 Multiple signal handlers may be pending.
    2701 When control eventually switches back to the signal handler, it returns normally, and execution continues in the interrupted user thread, even though the return from the signal handler may be on a different kernel thread than the one where the signal is delivered.
    2702 The only issue with this approach is that signal masks from one kernel thread may be restored on another as part of returning from the signal handler;
    2703 therefore, the same signal mask is required for all virtual processors in a cluster.
    2704 Because preemption frequency is usually long (1 millisecond) performance cost is negligible.
    2705 
    2706 Linux switched a decade ago from specific to arbitrary process signal-delivery for applications with multiple kernel threads.
    2707 \begin{cquote}
    2708 A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked.
    2709 If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which it will deliver the signal.
    2710 SIGNAL(7) - Linux Programmer's Manual
    2711 \end{cquote}
    2712 Hence, the timer-expiry signal, which is generated \emph{externally} by the Linux kernel to an application, is delivered to any of its Linux subprocesses (kernel threads).
    2713 To ensure each virtual processor receives a preemption signal, a discrete-event simulation is run on a special virtual processor, and only it sets and receives timer events.
    2714 Virtual processors register an expiration time with the discrete-event simulator, which is inserted in sorted order.
    2715 The simulation sets the countdown timer to the value at the head of the event list, and when the timer expires, all events less than or equal to the current time are processed.
    2716 Processing a preemption event sends an \emph{internal} @SIGUSR1@ signal to the registered virtual processor, which is always delivered to that processor.
    2717 
    2718 
    2719 \subsection{Debug Kernel}
    2720 
    2721 There are two versions of the \CFA runtime kernel: debug and non-debug.
    2722 The debugging version has many runtime checks and internal assertions, \eg stack (non-writable) guard page, and checks for stack overflow whenever context switches occur among coroutines and threads, which catches most stack overflows.
    2723 After a program is debugged, the non-debugging version can be used to significantly decrease space and increase performance.
    2724 
    2725 
    2726 \section{Performance}
    2727 \label{s:Performance}
    2728 
    2729 To verify the implementation of the \CFA runtime, a series of microbenchmarks are performed comparing \CFA with pthreads, Java OpenJDK-9, Go 1.12.6 and \uC 7.0.0.
    2730 For comparison, the package must be multi-processor (M:N), which excludes libdill/libmil~\cite{libdill} (M:1)), and use a shared-memory programming model, \eg not message passing.
    2731 The benchmark computer is an AMD Opteron\texttrademark\ 6380 NUMA 64-core, 8 socket, 2.5 GHz processor, running Ubuntu 16.04.6 LTS, and \CFA/\uC are compiled with gcc 6.5.
    2732 
    2733 All benchmarks are run using the following harness. (The Java harness is augmented to circumvent JIT issues.)
    2734 \begin{cfa}
    2735 unsigned int N = 10_000_000;
    2736 #define BENCH( `run` ) Time before = getTimeNsec();  `run;`  Duration result = (getTimeNsec() - before) / N;
    2737 \end{cfa}
    2738 The method used to get time is @clock_gettime( CLOCK_REALTIME )@.
    2739 Each benchmark is performed @N@ times, where @N@ varies depending on the benchmark;
    2740 the total time is divided by @N@ to obtain the average time for a benchmark.
    2741 Each benchmark experiment is run 31 times.
    2742 All omitted tests for other languages are functionally identical to the \CFA tests and available online~\cite{CforallBenchMarks}.
    2743 % tar --exclude=.deps --exclude=Makefile --exclude=Makefile.in --exclude=c.c --exclude=cxx.cpp --exclude=fetch_add.c -cvhf benchmark.tar benchmark
    2744 
    2745 \paragraph{Object Creation}
    2746 
    2747 Object creation is measured by creating/deleting the specific kind of concurrent object.
    2748 Figure~\ref{f:creation} shows the code for \CFA, with results in Table~\ref{tab:creation}.
    2749 The only note here is that the call stacks of \CFA coroutines are lazily created, therefore without priming the coroutine to force stack creation, the creation cost is artificially low.
    2750 
    2751 \begin{multicols}{2}
    2752 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2753 \begin{cfa}
    2754 @thread@ MyThread {};
    2755 void @main@( MyThread & ) {}
    2756 int main() {
    2757         BENCH( for ( N ) { @MyThread m;@ } )
    2758         sout | result`ns;
    2759 }
    2760 \end{cfa}
    2761 \captionof{figure}{\CFA object-creation benchmark}
    2762 \label{f:creation}
    2763 
    2764 \columnbreak
    2765 
    2766 \vspace*{-16pt}
    2767 \captionof{table}{Object creation comparison (nanoseconds)}
    2768 \label{tab:creation}
    2769 
    2770 \begin{tabular}[t]{@{}r*{3}{D{.}{.}{5.2}}@{}}
    2771 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2772 \CFA Coroutine Lazy             & 13.2          & 13.1          & 0.44          \\
    2773 \CFA Coroutine Eager    & 531.3         & 536.0         & 26.54         \\
    2774 \CFA Thread                             & 2074.9        & 2066.5        & 170.76        \\
    2775 \uC Coroutine                   & 89.6          & 90.5          & 1.83          \\
    2776 \uC Thread                              & 528.2         & 528.5         & 4.94          \\
    2777 Goroutine                               & 4068.0        & 4113.1        & 414.55        \\
    2778 Java Thread                             & 103848.5      & 104295.4      & 2637.57       \\
    2779 Pthreads                                & 33112.6       & 33127.1       & 165.90
     3161\begin{table}
     3162\begin{center}
     3163\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
     3164\cline{2-4}
     3165\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
     3166\hline
     3167\uC @Accept@                                    & 350           & 350.61        & 3.11  \\
     3168\CFA @waitfor@, 1 @monitor@     & 358.5 & 358.36        & 3.82  \\
     3169\CFA @waitfor@, 2 @monitor@     & 422           & 426.79        & 7.95  \\
     3170\CFA @waitfor@, 4 @monitor@     & 579.5 & 585.46        & 11.25 \\
     3171\hline
    27803172\end{tabular}
    2781 \end{multicols}
    2782 
    2783 
    2784 \paragraph{Context-Switching}
    2785 
    2786 In procedural programming, the cost of a function call is important as modularization (refactoring) increases.
    2787 (In many cases, a compiler inlines function calls to eliminate this cost.)
    2788 Similarly, when modularization extends to coroutines/tasks, the time for a context switch becomes a relevant factor.
    2789 The coroutine test is from resumer to suspender and from suspender to resumer, which is two context switches.
    2790 The thread test is using yield to enter and return from the runtime kernel, which is two context switches.
    2791 The difference in performance between coroutine and thread context-switch is the cost of scheduling for threads, whereas coroutines are self-scheduling.
    2792 Figure~\ref{f:ctx-switch} only shows the \CFA code for coroutines/threads (other systems are similar) with all results in Table~\ref{tab:ctx-switch}.
    2793 
    2794 \begin{multicols}{2}
    2795 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2796 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2797 @coroutine@ C {} c;
    2798 void main( C & ) { for ( ;; ) { @suspend;@ } }
    2799 int main() { // coroutine test
    2800         BENCH( for ( N ) { @resume( c );@ } )
    2801         sout | result`ns;
    2802 }
    2803 int main() { // task test
    2804         BENCH( for ( N ) { @yield();@ } )
    2805         sout | result`ns;
    2806 }
    2807 \end{cfa}
    2808 \captionof{figure}{\CFA context-switch benchmark}
    2809 \label{f:ctx-switch}
    2810 
    2811 \columnbreak
    2812 
    2813 \vspace*{-16pt}
    2814 \captionof{table}{Context switch comparison (nanoseconds)}
    2815 \label{tab:ctx-switch}
    2816 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    2817 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2818 C function              & 1.8   & 1.8   & 0.01  \\
    2819 \CFA generator  & 2.4   & 2.2   & 0.25  \\
    2820 \CFA Coroutine  & 36.2  & 36.2  & 0.25  \\
    2821 \CFA Thread             & 93.2  & 93.5  & 2.09  \\
    2822 \uC Coroutine   & 52.0  & 52.1  & 0.51  \\
    2823 \uC Thread              & 96.2  & 96.3  & 0.58  \\
    2824 Goroutine               & 141.0 & 141.3 & 3.39  \\
    2825 Java Thread             & 374.0 & 375.8 & 10.38 \\
    2826 Pthreads Thread & 361.0 & 365.3 & 13.19
    2827 \end{tabular}
    2828 \end{multicols}
    2829 
    2830 
    2831 \paragraph{Mutual-Exclusion}
    2832 
    2833 Uncontented mutual exclusion, which frequently occurs, is measured by entering/leaving a critical section.
    2834 For monitors, entering and leaving a monitor function is measured.
    2835 To put the results in context, the cost of entering a non-inline function and the cost of acquiring and releasing a @pthread_mutex@ lock is also measured.
    2836 Figure~\ref{f:mutex} shows the code for \CFA with all results in Table~\ref{tab:mutex}.
    2837 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    2838 
    2839 \begin{multicols}{2}
    2840 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2841 \begin{cfa}
    2842 @monitor@ M {} m1/*, m2, m3, m4*/;
    2843 void __attribute__((noinline))
    2844 do_call( M & @mutex m/*, m2, m3, m4*/@ ) {}
     3173\end{center}
     3174\caption{External scheduling comparison.
     3175All numbers are in nanoseconds(\si{\nano\second})}
     3176\label{tab:ext-sched}
     3177\end{table}
     3178
     3179
     3180\subsection{Object Creation}
     3181Finally, the last benchmark measures the cost of creation for concurrent objects.
     3182Figure~\ref{f:creation} shows the code for @pthread@s and \CFA threads, with results shown in table \ref{tab:creation}.
     3183As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
     3184The only note here is that the call stacks of \CFA coroutines are lazily created, therefore without priming the coroutine, the creation cost is very low.
     3185
     3186\begin{figure}
     3187\begin{center}
     3188@pthread@
     3189\begin{cfa}
    28453190int main() {
    28463191        BENCH(
    2847                 for( N ) do_call( m1/*, m2, m3, m4*/ );
     3192                for(size_t i=0; i<n; i++) {
     3193                        pthread_t thread;
     3194                        if(pthread_create(&thread,NULL,foo,NULL)<0) {
     3195                                perror( "failure" );
     3196                                return 1;
     3197                        }
     3198
     3199                        if(pthread_join(thread, NULL)<0) {
     3200                                perror( "failure" );
     3201                                return 1;
     3202                        }
     3203                },
     3204                result
    28483205        )
    2849         sout | result`ns;
    2850 }
    2851 \end{cfa}
    2852 \captionof{figure}{\CFA acquire/release mutex benchmark}
    2853 \label{f:mutex}
    2854 
    2855 \columnbreak
    2856 
    2857 \vspace*{-16pt}
    2858 \captionof{table}{Mutex comparison (nanoseconds)}
    2859 \label{tab:mutex}
    2860 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    2861 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2862 test and test-and-test lock             & 19.1  & 18.9  & 0.40  \\
    2863 \CFA @mutex@ function, 1 arg.   & 45.9  & 46.6  & 1.45  \\
    2864 \CFA @mutex@ function, 2 arg.   & 105.0 & 104.7 & 3.08  \\
    2865 \CFA @mutex@ function, 4 arg.   & 165.0 & 167.6 & 5.65  \\
    2866 \uC @monitor@ member rtn.               & 54.0  & 53.7  & 0.82  \\
    2867 Java synchronized method                & 31.0  & 31.1  & 0.50  \\
    2868 Pthreads Mutex Lock                             & 33.6  & 32.6  & 1.14
     3206        printf("%llu\n", result);
     3207}
     3208\end{cfa}
     3209
     3210
     3211
     3212\CFA Threads
     3213\begin{cfa}
     3214int main() {
     3215        BENCH(
     3216                for(size_t i=0; i<n; i++) {
     3217                        MyThread m;
     3218                },
     3219                result
     3220        )
     3221        printf("%llu\n", result);
     3222}
     3223\end{cfa}
     3224\end{center}
     3225\caption{Benchmark code for \protect\lstinline|pthread|s and \CFA to measure object creation}
     3226\label{f:creation}
     3227\end{figure}
     3228
     3229\begin{table}
     3230\begin{center}
     3231\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
     3232\cline{2-4}
     3233\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
     3234\hline
     3235Pthreads                        & 26996 & 26984.71      & 156.6  \\
     3236\CFA Coroutine Lazy     & 6             & 5.71  & 0.45   \\
     3237\CFA Coroutine Eager    & 708           & 706.68        & 4.82   \\
     3238\CFA Thread                     & 1173.5        & 1176.18       & 15.18  \\
     3239\uC Coroutine           & 109           & 107.46        & 1.74   \\
     3240\uC Thread                      & 526           & 530.89        & 9.73   \\
     3241Goroutine                       & 2520.5        & 2530.93       & 61,56  \\
     3242Java Thread                     & 91114.5       & 92272.79      & 961.58 \\
     3243\hline
    28693244\end{tabular}
    2870 \end{multicols}
    2871 
    2872 
    2873 \paragraph{External Scheduling}
    2874 
    2875 External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement.
    2876 Figure~\ref{f:ext-sched} shows the code for \CFA, with results in Table~\ref{tab:ext-sched}.
    2877 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    2878 
    2879 \begin{multicols}{2}
    2880 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2881 \vspace*{-16pt}
    2882 \begin{cfa}
    2883 volatile int go = 0;
    2884 @monitor@ M {} m;
    2885 thread T {};
    2886 void __attribute__((noinline))
    2887 do_call( M & @mutex@ ) {}
    2888 void main( T & ) {
    2889         while ( go == 0 ) { yield(); }
    2890         while ( go == 1 ) { do_call( m ); }
    2891 }
    2892 int __attribute__((noinline))
    2893 do_wait( M & @mutex@ m ) {
    2894         go = 1; // continue other thread
    2895         BENCH( for ( N ) { @waitfor( do_call, m );@ } )
    2896         go = 0; // stop other thread
    2897         sout | result`ns;
    2898 }
    2899 int main() {
    2900         T t;
    2901         do_wait( m );
    2902 }
    2903 \end{cfa}
    2904 \captionof{figure}{\CFA external-scheduling benchmark}
    2905 \label{f:ext-sched}
    2906 
    2907 \columnbreak
    2908 
    2909 \vspace*{-16pt}
    2910 \captionof{table}{External-scheduling comparison (nanoseconds)}
    2911 \label{tab:ext-sched}
    2912 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    2913 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2914 \CFA @waitfor@, 1 @monitor@     & 376.4 & 376.8 & 7.63  \\
    2915 \CFA @waitfor@, 2 @monitor@     & 491.4 & 492.0 & 13.31 \\
    2916 \CFA @waitfor@, 4 @monitor@     & 681.0 & 681.7 & 19.10 \\
    2917 \uC @_Accept@                           & 331.1 & 331.4 & 2.66
    2918 \end{tabular}
    2919 \end{multicols}
    2920 
    2921 
    2922 \paragraph{Internal Scheduling}
    2923 
    2924 Internal scheduling is measured using a cycle of two threads signalling and waiting.
    2925 Figure~\ref{f:int-sched} shows the code for \CFA, with results in Table~\ref{tab:int-sched}.
    2926 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    2927 Java scheduling is significantly greater because the benchmark explicitly creates multiple thread in order to prevent the JIT from making the program sequential, \ie removing all locking.
    2928 
    2929 \begin{multicols}{2}
    2930 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2931 \begin{cfa}
    2932 volatile int go = 0;
    2933 @monitor@ M { @condition c;@ } m;
    2934 void __attribute__((noinline))
    2935 do_call( M & @mutex@ a1 ) { @signal( c );@ }
    2936 thread T {};
    2937 void main( T & this ) {
    2938         while ( go == 0 ) { yield(); }
    2939         while ( go == 1 ) { do_call( m ); }
    2940 }
    2941 int  __attribute__((noinline))
    2942 do_wait( M & mutex m ) with(m) {
    2943         go = 1; // continue other thread
    2944         BENCH( for ( N ) { @wait( c );@ } );
    2945         go = 0; // stop other thread
    2946         sout | result`ns;
    2947 }
    2948 int main() {
    2949         T t;
    2950         do_wait( m );
    2951 }
    2952 \end{cfa}
    2953 \captionof{figure}{\CFA Internal-scheduling benchmark}
    2954 \label{f:int-sched}
    2955 
    2956 \columnbreak
    2957 
    2958 \vspace*{-16pt}
    2959 \captionof{table}{Internal-scheduling comparison (nanoseconds)}
    2960 \label{tab:int-sched}
    2961 \bigskip
    2962 
    2963 \begin{tabular}{@{}r*{3}{D{.}{.}{5.2}}@{}}
    2964 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2965 \CFA @signal@, 1 @monitor@      & 372.6         & 374.3         & 14.17         \\
    2966 \CFA @signal@, 2 @monitor@      & 492.7         & 494.1         & 12.99         \\
    2967 \CFA @signal@, 4 @monitor@      & 749.4         & 750.4         & 24.74         \\
    2968 \uC @signal@                            & 320.5         & 321.0         & 3.36          \\
    2969 Java @notify@                           & 10160.5       & 10169.4       & 267.71        \\
    2970 Pthreads Cond. Variable         & 4949.6        & 5065.2        & 363
    2971 \end{tabular}
    2972 \end{multicols}
     3245\end{center}
     3246\caption{Creation comparison.
     3247All numbers are in nanoseconds(\si{\nano\second}).}
     3248\label{tab:creation}
     3249\end{table}
     3250
    29733251
    29743252
    29753253\section{Conclusion}
    2976 
    2977 Advanced control-flow will always be difficult, especially when there is temporal ordering and nondeterminism.
    2978 However, many systems exacerbate the difficulty through their presentation mechanisms.
    2979 This paper shows it is possible to present a hierarchy of control-flow features, generator, coroutine, thread, and monitor, providing an integrated set of high-level, efficient, and maintainable control-flow features.
    2980 Eliminated from \CFA are spurious wakeup and barging, which are nonintuitive and lead to errors, and having to work with a bewildering set of low-level locks and acquisition techniques.
    2981 \CFA high-level race-free monitors and tasks provide the core mechanisms for mutual exclusion and synchronization, without having to resort to magic qualifiers like @volatile@/@atomic@.
    2982 Extending these mechanisms to handle high-level deadlock-free bulk acquire across both mutual exclusion and synchronization is a unique contribution.
    2983 The \CFA runtime provides concurrency based on a preemptive M:N user-level threading-system, executing in clusters, which encapsulate scheduling of work on multiple kernel threads providing parallelism.
    2984 The M:N model is judged to be efficient and provide greater flexibility than a 1:1 threading model.
    2985 These concepts and the \CFA runtime-system are written in the \CFA language, extensively leveraging the \CFA type-system, which demonstrates the expressiveness of the \CFA language.
    2986 Performance comparisons with other concurrent systems/languages show the \CFA approach is competitive across all low-level operations, which translates directly into good performance in well-written concurrent applications.
    2987 C programmers should feel comfortable using these mechanisms for developing complex control-flow in applications, with the ability to obtain maximum available performance by selecting mechanisms at the appropriate level of need.
    2988 
    2989 
     3254This paper has achieved a minimal concurrency \textbf{api} that is simple, efficient and usable as the basis for higher-level features.
     3255The approach presented is based on a lightweight thread-system for parallelism, which sits on top of clusters of processors.
     3256This M:N model is judged to be both more efficient and allow more flexibility for users.
     3257Furthermore, this document introduces monitors as the main concurrency tool for users.
     3258This paper also offers a novel approach allowing multiple monitors to be accessed simultaneously without running into the Nested Monitor Problem~\cite{Lister77}.
     3259It also offers a full implementation of the concurrency runtime written entirely in \CFA, effectively the largest \CFA code base to date.
     3260
     3261
     3262% ======================================================================
     3263% ======================================================================
    29903264\section{Future Work}
    2991 
    2992 While control flow in \CFA has a strong start, development is still underway to complete a number of missing features.
    2993 
    2994 \paragraph{Flexible Scheduling}
    2995 \label{futur:sched}
    2996 
     3265% ======================================================================
     3266% ======================================================================
     3267
     3268\subsection{Performance} \label{futur:perf}
     3269This paper presents a first implementation of the \CFA concurrency runtime.
     3270Therefore, there is still significant work to improve performance.
     3271Many of the data structures and algorithms may change in the future to more efficient versions.
     3272For example, the number of monitors in a single bulk acquire is only bound by the stack size, this is probably unnecessarily generous.
     3273It may be possible that limiting the number helps increase performance.
     3274However, it is not obvious that the benefit would be significant.
     3275
     3276\subsection{Flexible Scheduling} \label{futur:sched}
    29973277An important part of concurrency is scheduling.
    29983278Different scheduling algorithms can affect performance (both in terms of average and variation).
    29993279However, no single scheduler is optimal for all workloads and therefore there is value in being able to change the scheduler for given programs.
    3000 One solution is to offer various tuning options, allowing the scheduler to be adjusted to the requirements of the workload.
    3001 However, to be truly flexible, a pluggable scheduler is necessary.
    3002 Currently, the \CFA pluggable scheduler is too simple to handle complex scheduling, \eg quality of service and real-time, where the scheduler must interact with mutex objects to deal with issues like priority inversion~\cite{Buhr00b}.
    3003 
    3004 \paragraph{Non-Blocking I/O}
    3005 \label{futur:nbio}
    3006 
    3007 Many modern workloads are not bound by computation but IO operations, a common case being web servers and XaaS~\cite{XaaS} (anything as a service).
    3008 These types of workloads require significant engineering to amortizing costs of blocking IO-operations.
    3009 At its core, non-blocking I/O is an operating-system level feature queuing IO operations, \eg network operations, and registering for notifications instead of waiting for requests to complete.
    3010 Current trends use asynchronous programming like callbacks, futures, and/or promises, \eg Node.js~\cite{NodeJs} for JavaScript, Spring MVC~\cite{SpringMVC} for Java, and Django~\cite{Django} for Python.
    3011 However, these solutions lead to code that is hard to create, read and maintain.
    3012 A better approach is to tie non-blocking I/O into the concurrency system to provide ease of use with low overhead, \eg thread-per-connection web-services.
    3013 A non-blocking I/O library is currently under development for \CFA.
    3014 
    3015 \paragraph{Other Concurrency Tools}
    3016 \label{futur:tools}
    3017 
    3018 While monitors offer flexible and powerful concurrency for \CFA, other concurrency tools are also necessary for a complete multi-paradigm concurrency package.
    3019 Examples of such tools can include futures and promises~\cite{promises}, executors and actors.
    3020 These additional features are useful for applications that can be constructed without shared data and direct blocking.
    3021 As well, new \CFA extensions should make it possible to create a uniform interface for virtually all mutual exclusion, including monitors and low-level locks.
    3022 
    3023 \paragraph{Implicit Threading}
    3024 \label{futur:implcit}
    3025 
    3026 Basic concurrent (embarrassingly parallel) applications can benefit greatly from implicit concurrency, where sequential programs are converted to concurrent, possibly with some help from pragmas to guide the conversion.
    3027 This type of concurrency can be achieved both at the language level and at the library level.
    3028 The canonical example of implicit concurrency is concurrent nested @for@ loops, which are amenable to divide and conquer algorithms~\cite{uC++book}.
    3029 The \CFA language features should make it possible to develop a reasonable number of implicit concurrency mechanism to solve basic HPC data-concurrency problems.
    3030 However, implicit concurrency is a restrictive solution with significant limitations, so it can never replace explicit concurrent programming.
    3031 
    3032 
     3280One solution is to offer various tweaking options to users, allowing the scheduler to be adjusted to the requirements of the workload.
     3281However, in order to be truly flexible, it would be interesting to allow users to add arbitrary data and arbitrary scheduling algorithms.
     3282For example, a web server could attach Type-of-Service information to threads and have a ``ToS aware'' scheduling algorithm tailored to this specific web server.
     3283This path of flexible schedulers will be explored for \CFA.
     3284
     3285\subsection{Non-Blocking I/O} \label{futur:nbio}
     3286While most of the parallelism tools are aimed at data parallelism and control-flow parallelism, many modern workloads are not bound on computation but on IO operations, a common case being web servers and XaaS (anything as a service).
     3287These types of workloads often require significant engineering around amortizing costs of blocking IO operations.
     3288At its core, non-blocking I/O is an operating system level feature that allows queuing IO operations (\eg network operations) and registering for notifications instead of waiting for requests to complete.
     3289In this context, the role of the language makes Non-Blocking IO easily available and with low overhead.
     3290The current trend is to use asynchronous programming using tools like callbacks and/or futures and promises, which can be seen in frameworks like Node.js~\cite{NodeJs} for JavaScript, Spring MVC~\cite{SpringMVC} for Java and Django~\cite{Django} for Python.
     3291However, while these are valid solutions, they lead to code that is harder to read and maintain because it is much less linear.
     3292
     3293\subsection{Other Concurrency Tools} \label{futur:tools}
     3294While monitors offer a flexible and powerful concurrent core for \CFA, other concurrency tools are also necessary for a complete multi-paradigm concurrency package.
     3295Examples of such tools can include simple locks and condition variables, futures and promises~\cite{promises}, executors and actors.
     3296These additional features are useful when monitors offer a level of abstraction that is inadequate for certain tasks.
     3297
     3298\subsection{Implicit Threading} \label{futur:implcit}
     3299Simpler applications can benefit greatly from having implicit parallelism.
     3300That is, parallelism that does not rely on the user to write concurrency.
     3301This type of parallelism can be achieved both at the language level and at the library level.
     3302The canonical example of implicit parallelism is parallel for loops, which are the simplest example of a divide and conquer algorithms~\cite{uC++book}.
     3303Table \ref{f:parfor} shows three different code examples that accomplish point-wise sums of large arrays.
     3304Note that none of these examples explicitly declare any concurrency or parallelism objects.
     3305
     3306\begin{table}
     3307\begin{center}
     3308\begin{tabular}[t]{|c|c|c|}
     3309Sequential & Library Parallel & Language Parallel \\
     3310\begin{cfa}[tabsize=3]
     3311void big_sum(
     3312        int* a, int* b,
     3313        int* o,
     3314        size_t len)
     3315{
     3316        for(
     3317                int i = 0;
     3318                i < len;
     3319                ++i )
     3320        {
     3321                o[i]=a[i]+b[i];
     3322        }
     3323}
     3324
     3325
     3326
     3327
     3328
     3329int* a[10000];
     3330int* b[10000];
     3331int* c[10000];
     3332//... fill in a & b
     3333big_sum(a,b,c,10000);
     3334\end{cfa} &\begin{cfa}[tabsize=3]
     3335void big_sum(
     3336        int* a, int* b,
     3337        int* o,
     3338        size_t len)
     3339{
     3340        range ar(a, a+len);
     3341        range br(b, b+len);
     3342        range or(o, o+len);
     3343        parfor( ai, bi, oi,
     3344        [](     int* ai,
     3345                int* bi,
     3346                int* oi)
     3347        {
     3348                oi=ai+bi;
     3349        });
     3350}
     3351
     3352
     3353int* a[10000];
     3354int* b[10000];
     3355int* c[10000];
     3356//... fill in a & b
     3357big_sum(a,b,c,10000);
     3358\end{cfa}&\begin{cfa}[tabsize=3]
     3359void big_sum(
     3360        int* a, int* b,
     3361        int* o,
     3362        size_t len)
     3363{
     3364        parfor (ai,bi,oi)
     3365            in (a, b, o )
     3366        {
     3367                oi = ai + bi;
     3368        }
     3369}
     3370
     3371
     3372
     3373
     3374
     3375
     3376
     3377int* a[10000];
     3378int* b[10000];
     3379int* c[10000];
     3380//... fill in a & b
     3381big_sum(a,b,c,10000);
     3382\end{cfa}
     3383\end{tabular}
     3384\end{center}
     3385\caption{For loop to sum numbers: Sequential, using library parallelism and language parallelism.}
     3386\label{f:parfor}
     3387\end{table}
     3388
     3389Implicit parallelism is a restrictive solution and therefore has its limitations.
     3390However, it is a quick and simple approach to parallelism, which may very well be sufficient for smaller applications and reduces the amount of boilerplate needed to start benefiting from parallelism in modern CPUs.
     3391
     3392
     3393% A C K N O W L E D G E M E N T S
     3394% -------------------------------
    30333395\section{Acknowledgements}
    30343396
    3035 The authors would like to recognize the design assistance of Aaron Moss, Rob Schluntz, Andrew Beach and Michael Brooks on the features described in this paper.
    3036 Funding for this project has been provided by Huawei Ltd.\ (\url{http://www.huawei.com}). %, and Peter Buhr is partially funded by the Natural Sciences and Engineering Research Council of Canada.
    3037 
    3038 {%
    3039 \fontsize{9bp}{12bp}\selectfont%
     3397Thanks to Aaron Moss, Rob Schluntz and Andrew Beach for their work on the \CFA project as well as all the discussions which helped concretize the ideas in this paper.
     3398Partial funding was supplied by the Natural Sciences and Engineering Research Council of Canada and a corporate partnership with Huawei Ltd.
     3399
     3400
     3401% B I B L I O G R A P H Y
     3402% -----------------------------
     3403%\bibliographystyle{plain}
    30403404\bibliography{pl,local}
    3041 }%
     3405
    30423406
    30433407\end{document}
  • doc/papers/concurrency/annex/local.bib

    rb067d9b r7951100  
    4646    title       = {Thread Building Blocks},
    4747    howpublished= {Intel, \url{https://www.threadingbuildingblocks.org}},
    48     optnote     = {Accessed: 2018-3},
     48    note        = {Accessed: 2018-3},
    4949}
    5050
     
    6666}
    6767
    68 @misc{BankTransfer,
     68@article{BankTransfer,
    6969        key     = {Bank Transfer},
    7070        keywords        = {Bank Transfer},
    7171        title   = {Bank Account Transfer Problem},
    72         howpublished    = {Wiki Wiki Web, \url{http://wiki.c2.com/?BankAccountTransferProblem}},
     72        publisher       = {Wiki Wiki Web},
     73        address = {http://wiki.c2.com},
    7374        year            = 2010
    7475}
  • doc/papers/concurrency/figures/ext_monitor.fig

    rb067d9b r7951100  
    88-2
    991200 2
    10 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 3600.000 1500 3300 1200 3600 1500 3900
    11 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 4500.000 1500 4200 1200 4500 1500 4800
    12 6 4200 2100 4500 2400
    13 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2250 105 105 4350 2250 4455 2355
    14 4 1 -1 0 0 0 10 0.0000 2 105 90 4350 2310 d\001
     105 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 3450.000 3150 3150 2850 3450 3150 3750
     115 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 4350.000 3150 4050 2850 4350 3150 4650
     126 5850 1950 6150 2250
     131 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2100 105 105 6000 2100 6105 2205
     144 1 -1 0 0 0 10 0.0000 2 105 90 6000 2160 d\001
    1515-6
    16 6 4200 1800 4500 2100
    17 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1950 105 105 4350 1950 4455 2055
    18 4 1 -1 0 0 0 10 0.0000 2 105 90 4350 2010 b\001
     166 5100 2100 5400 2400
     171 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
     184 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
    1919-6
    20 6 1420 5595 5625 5805
    21 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1500 5700 80 80 1500 5700 1580 5780
    22 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 5700 105 105 2850 5700 2955 5805
    23 1 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4350 5700 105 105 4350 5700 4455 5805
    24 4 0 -1 0 0 0 12 0.0000 2 135 1035 3075 5775 blocked task\001
    25 4 0 -1 0 0 0 12 0.0000 2 135 870 1650 5775 active task\001
    26 4 0 -1 0 0 0 12 0.0000 2 135 1050 4575 5775 routine mask\001
     206 5100 1800 5400 2100
     211 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 1950 105 105 5250 1950 5355 1950
     224 1 -1 0 0 0 10 0.0000 2 105 120 5250 2010 Y\001
    2723-6
    28 6 3450 1950 3750 2550
    29 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3600 2100 105 105 3600 2100 3705 2100
     246 5850 1650 6150 1950
     251 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
     264 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
     27-6
     286 3070 5445 7275 5655
     291 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3150 5550 80 80 3150 5550 3230 5630
     301 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4500 5550 105 105 4500 5550 4605 5655
     311 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 6000 5550 105 105 6000 5550 6105 5655
     324 0 -1 0 0 0 12 0.0000 2 135 1035 4725 5625 blocked task\001
     334 0 -1 0 0 0 12 0.0000 2 135 870 3300 5625 active task\001
     344 0 -1 0 0 0 12 0.0000 2 135 1050 6225 5625 routine mask\001
     35-6
     361 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3300 3600 105 105 3300 3600 3405 3705
     371 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3600 3600 105 105 3600 3600 3705 3705
     381 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6600 3900 105 105 6600 3900 6705 4005
     391 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6900 3900 105 105 6900 3900 7005 4005
     401 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2700 105 105 6000 2700 6105 2805
     411 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2400 105 105 6000 2400 6105 2505
     421 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 5100 4575 80 80 5100 4575 5180 4655
    30432 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    31          3450 1950 3750 1950 3750 2550 3450 2550 3450 1950
    32 4 1 4 0 0 0 10 0.0000 2 105 120 3600 2160 Y\001
    33 -6
    34 6 3450 2250 3750 2550
    35 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3600 2400 105 105 3600 2400 3705 2400
    36 4 1 4 0 0 0 10 0.0000 2 105 120 3600 2445 X\001
    37 -6
    38 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1650 3750 105 105 1650 3750 1755 3855
    39 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1950 3750 105 105 1950 3750 2055 3855
    40 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 4050 105 105 4950 4050 5055 4155
    41 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5250 4050 105 105 5250 4050 5355 4155
    42 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2850 105 105 4350 2850 4455 2955
    43 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2550 105 105 4350 2550 4455 2655
    44 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 4725 80 80 3450 4725 3530 4805
     44         4050 2925 5475 2925 5475 3225 4050 3225 4050 2925
     452 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
     46         3150 3750 3750 3750 3750 4050 3150 4050
     472 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
     48         3150 3450 3750 3450 3900 3675
     492 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     50         3750 3150 3600 3375
     512 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
     52         3150 4350 3750 4350 3900 4575
     532 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     54         3750 4050 3600 4275
     552 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
     56         3150 4650 3750 4650 3750 4950 4950 4950
     572 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     58         6450 3750 6300 3975
     592 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     60         4950 4950 5175 5100
     612 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
     62         5250 4950 6450 4950 6450 4050 7050 4050 7050 3750 6450 3750
     63         6450 2850 6150 2850 6150 1650
     642 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
     65         5850 4200 5850 3300 4350 3300 4350 4200 5850 4200
     662 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
     67        1 1 1.00 60.00 120.00
     68        7 1 1.00 60.00 120.00
     69         5250 3150 5250 2400
     702 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
     71         3150 3150 3750 3150 3750 2850 5700 2850 5700 1650
     722 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
     73         5700 2850 6150 3000
    45742 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    46          2400 3075 3825 3075 3825 3375 2400 3375 2400 3075
    47 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    48          1500 3900 2100 3900 2100 4200 1500 4200
    49 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    50          1500 3600 2100 3600 2250 3825
    51 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    52          2100 3300 1950 3525
    53 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    54          1500 4500 2100 4500 2250 4725
    55 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    56          2100 4200 1950 4425
    57 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    58          1500 4800 2100 4800 2100 5100 3300 5100
    59 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    60          4800 3900 4650 4125
    61 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    62          3300 5100 3525 5250
    63 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
    64          3600 5100 4800 5100 4800 4200 5400 4200 5400 3900 4800 3900
    65          4800 3000 4500 3000 4500 1800
    66 2 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    67          4200 4350 4200 3450 2700 3450 2700 4350 4200 4350
    68 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    69         1 1 1.00 60.00 120.00
    70          3600 3225 3600 2550
    71 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    72          4050 3000 4500 3150
    73 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    74          1500 3300 2100 3300 2100 3000 4050 3000 4050 1800
    75 4 1 -1 0 0 0 10 0.0000 2 75 75 4350 2895 a\001
    76 4 1 -1 0 0 0 10 0.0000 2 75 75 4350 2595 c\001
    77 4 1 -1 0 0 0 12 0.0000 2 135 315 3450 5475 exit\001
    78 4 1 -1 0 0 0 12 0.0000 2 135 135 1650 3225 A\001
    79 4 1 -1 0 0 0 12 0.0000 2 135 795 1650 5025 condition\001
    80 4 1 -1 0 0 0 12 0.0000 2 135 135 1650 5250 B\001
    81 4 0 -1 0 0 0 12 0.0000 2 135 420 4950 3825 stack\001
    82 4 0 -1 0 0 0 12 0.0000 2 180 750 4950 3375 acceptor/\001
    83 4 0 -1 0 0 0 12 0.0000 2 180 750 4950 3600 signalled\001
    84 4 1 -1 0 0 0 12 0.0000 2 135 795 1650 3000 condition\001
    85 4 0 -1 0 0 0 12 0.0000 2 135 525 4650 2550 arrival\001
    86 4 0 -1 0 0 0 12 0.0000 2 135 630 4650 2325 order of\001
    87 4 1 -1 0 0 0 12 0.0000 2 135 525 3450 3825 shared\001
    88 4 1 -1 0 0 0 12 0.0000 2 135 735 3450 4125 variables\001
    89 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 2025 X\001
    90 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 2325 Y\001
    91 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 2625 Y\001
    92 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 2925 X\001
    93 4 0 -1 0 0 3 12 0.0000 2 150 540 4950 4425 urgent\001
    94 4 1 0 50 -1 0 11 0.0000 2 165 600 3075 3300 accepted\001
    95 4 1 -1 0 0 0 12 0.0000 2 165 960 4275 1725 entry queue\001
     75         5100 1800 5400 1800 5400 2400 5100 2400 5100 1800
     764 1 -1 0 0 0 10 0.0000 2 75 75 6000 2745 a\001
     774 1 -1 0 0 0 10 0.0000 2 75 75 6000 2445 c\001
     784 1 -1 0 0 0 12 0.0000 2 135 315 5100 5325 exit\001
     794 1 -1 0 0 0 12 0.0000 2 135 135 3300 3075 A\001
     804 1 -1 0 0 0 12 0.0000 2 135 795 3300 4875 condition\001
     814 1 -1 0 0 0 12 0.0000 2 135 135 3300 5100 B\001
     824 0 -1 0 0 0 12 0.0000 2 135 420 6600 3675 stack\001
     834 0 -1 0 0 0 12 0.0000 2 180 750 6600 3225 acceptor/\001
     844 0 -1 0 0 0 12 0.0000 2 180 750 6600 3450 signalled\001
     854 1 -1 0 0 0 12 0.0000 2 135 795 3300 2850 condition\001
     864 1 -1 0 0 0 12 0.0000 2 165 420 6000 1350 entry\001
     874 1 -1 0 0 0 12 0.0000 2 135 495 6000 1575 queue\001
     884 0 -1 0 0 0 12 0.0000 2 135 525 6300 2400 arrival\001
     894 0 -1 0 0 0 12 0.0000 2 135 630 6300 2175 order of\001
     904 1 -1 0 0 0 12 0.0000 2 135 525 5100 3675 shared\001
     914 1 -1 0 0 0 12 0.0000 2 135 735 5100 3975 variables\001
     924 0 0 50 -1 0 11 0.0000 2 165 855 4275 3150 Acceptables\001
     934 0 0 50 -1 0 11 0.0000 2 120 165 5775 2700 W\001
     944 0 0 50 -1 0 11 0.0000 2 120 135 5775 2400 X\001
     954 0 0 50 -1 0 11 0.0000 2 120 105 5775 2100 Z\001
     964 0 0 50 -1 0 11 0.0000 2 120 135 5775 1800 Y\001
  • doc/papers/concurrency/figures/monitor.fig

    rb067d9b r7951100  
    88-2
    991200 2
    10 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 3300.000 1500 3000 1200 3300 1500 3600
    11 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 4200.000 1500 3900 1200 4200 1500 4500
    12 6 1350 5250 5325 5550
    13 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1500 5400 80 80 1500 5400 1580 5480
    14 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 5400 105 105 2850 5400 2955 5505
    15 1 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4350 5400 105 105 4350 5400 4455 5505
    16 4 0 -1 0 0 0 12 0.0000 2 180 765 4575 5475 duplicate\001
    17 4 0 -1 0 0 0 12 0.0000 2 135 1035 3075 5475 blocked task\001
    18 4 0 -1 0 0 0 12 0.0000 2 135 870 1650 5475 active task\001
     105 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 2700.000 1500 2400 1200 2700 1500 3000
     115 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 3600.000 1500 3300 1200 3600 1500 3900
     126 4200 1200 4500 1500
     131 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1350 105 105 4350 1350 4455 1455
     144 1 -1 0 0 0 10 0.0000 2 105 90 4350 1410 d\001
    1915-6
    20 6 4200 1800 4500 2100
     166 4200 900 4500 1200
     171 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1050 105 105 4350 1050 4455 1155
     184 1 -1 0 0 0 10 0.0000 2 105 90 4350 1110 b\001
     19-6
     206 2400 1500 2700 1800
     211 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 2550 1650 105 105 2550 1650 2655 1650
     224 1 -1 0 0 0 10 0.0000 2 105 90 2550 1710 b\001
     23-6
     246 2400 1800 2700 2100
     251 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 2550 1950 105 105 2550 1950 2655 1950
     264 1 -1 0 0 0 10 0.0000 2 75 75 2550 1995 a\001
     27-6
     286 3300 1500 3600 1800
     291 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3450 1650 105 105 3450 1650 3555 1650
     304 1 -1 0 0 0 10 0.0000 2 105 90 3450 1710 d\001
     31-6
     326 1350 4650 5325 4950
     331 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1500 4800 80 80 1500 4800 1580 4880
     341 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 4800 105 105 2850 4800 2955 4905
     351 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4350 4800 105 105 4350 4800 4455 4905
     364 0 -1 0 0 0 12 0.0000 2 180 765 4575 4875 duplicate\001
     374 0 -1 0 0 0 12 0.0000 2 135 1035 3075 4875 blocked task\001
     384 0 -1 0 0 0 12 0.0000 2 135 870 1650 4875 active task\001
     39-6
     401 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1650 2850 105 105 1650 2850 1755 2955
     411 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1950 2850 105 105 1950 2850 2055 2955
     421 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 3150 105 105 4950 3150 5055 3255
     431 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5250 3150 105 105 5250 3150 5355 3255
    21441 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1950 105 105 4350 1950 4455 2055
    22 4 1 -1 0 0 0 10 0.0000 2 105 90 4350 2010 d\001
    23 -6
    24 6 4200 1500 4500 1800
    25451 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1650 105 105 4350 1650 4455 1755
    26 4 1 -1 0 0 0 10 0.0000 2 105 90 4350 1710 b\001
    27 -6
    28 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1650 3450 105 105 1650 3450 1755 3555
    29 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1950 3450 105 105 1950 3450 2055 3555
    30 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 3750 105 105 4950 3750 5055 3855
    31 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5250 3750 105 105 5250 3750 5355 3855
    32 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 4425 80 80 3450 4425 3530 4505
    33 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2550 105 105 4350 2550 4455 2655
    34 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2250 105 105 4350 2250 4455 2355
     461 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 3825 80 80 3450 3825 3530 3905
     471 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3450 1950 105 105 3450 1950 3555 1950
     482 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     49         2400 2100 2625 2250
     502 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     51         3300 2100 3525 2250
     522 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     53         4200 2100 4425 2250
    35542 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 5
    36          1500 3000 2100 3000 2100 2700 2400 2700 2400 2100
     55         1500 2400 2100 2400 2100 2100 2400 2100 2400 1500
    37562 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    38          1500 3600 2100 3600 2100 3900 1500 3900
     57         1500 3000 2100 3000 2100 3300 1500 3300
    39582 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    40          1500 3300 2100 3300 2250 3525
     59         1500 2700 2100 2700 2250 2925
    41602 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    42          2100 3000 1950 3225
     61         2100 2400 1950 2625
    43622 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    44          1500 4200 2100 4200 2250 4425
     63         1500 3600 2100 3600 2250 3825
    45642 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    46          2100 3900 1950 4125
     65         2100 3300 1950 3525
    47662 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    48          1500 4500 2100 4500 2100 4800 3300 4800
     67         1500 3900 2100 3900 2100 4200 3300 4200
    49682 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    50          4800 3600 4650 3825
     69         4800 3000 4650 3225
    51702 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    52          3300 4800 3525 4950
     71         3300 4200 3525 4350
     722 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
     73         3600 1500 3600 2100 4200 2100 4200 900
     742 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
     75         2700 1500 2700 2100 3300 2100 3300 1500
     762 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
     77         3600 4200 4800 4200 4800 3300 5400 3300 5400 3000 4800 3000
     78         4800 2100 4500 2100 4500 900
    53792 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    54          4200 4050 4200 3150 2700 3150 2700 4050 4200 4050
    55 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    56          3600 2100 3600 2700 4050 2700 4050 1500
    57 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 9
    58          3600 4800 4800 4800 4800 3900 5400 3900 5400 3600 4800 3600
    59          4800 2700 4500 2700 4500 1500
    60 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    61          4050 2700 4500 2850
    62 4 1 -1 0 0 0 12 0.0000 2 135 315 3450 5175 exit\001
    63 4 1 -1 0 0 0 12 0.0000 2 135 795 1650 4725 condition\001
    64 4 1 -1 0 0 0 12 0.0000 2 135 135 1650 4950 B\001
    65 4 0 -1 0 0 0 12 0.0000 2 135 420 4950 3525 stack\001
    66 4 0 -1 0 0 0 12 0.0000 2 180 750 4950 3075 acceptor/\001
    67 4 0 -1 0 0 0 12 0.0000 2 180 750 4950 3300 signalled\001
    68 4 1 -1 0 0 0 12 0.0000 2 135 525 3450 3525 shared\001
    69 4 1 -1 0 0 0 12 0.0000 2 135 735 3450 3825 variables\001
    70 4 0 -1 0 0 3 12 0.0000 2 150 540 4950 4125 urgent\001
    71 4 1 -1 0 0 0 10 0.0000 2 75 75 4350 2595 a\001
    72 4 1 -1 0 0 0 10 0.0000 2 75 75 4350 2295 c\001
    73 4 0 -1 0 0 0 12 0.0000 2 135 525 4650 2250 arrival\001
    74 4 0 -1 0 0 0 12 0.0000 2 135 630 4650 2025 order of\001
    75 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 1725 X\001
    76 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 2025 Y\001
    77 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 2325 Y\001
    78 4 0 4 50 -1 0 11 0.0000 2 120 135 4075 2625 X\001
    79 4 1 -1 0 0 0 12 0.0000 2 165 960 4275 1425 entry queue\001
     80         4200 3450 4200 2550 2700 2550 2700 3450 4200 3450
     814 1 -1 0 0 0 10 0.0000 2 75 75 4350 1995 a\001
     824 1 -1 0 0 0 10 0.0000 2 75 75 4350 1695 c\001
     834 1 -1 0 0 0 12 0.0000 2 135 315 3450 4575 exit\001
     844 1 -1 0 0 0 12 0.0000 2 135 135 1650 2325 A\001
     854 1 -1 0 0 0 12 0.0000 2 135 795 1650 4125 condition\001
     864 1 -1 0 0 0 12 0.0000 2 135 135 1650 4350 B\001
     874 0 -1 0 0 0 12 0.0000 2 135 420 4950 2925 stack\001
     884 0 -1 0 0 0 12 0.0000 2 180 750 4950 2475 acceptor/\001
     894 0 -1 0 0 0 12 0.0000 2 180 750 4950 2700 signalled\001
     904 1 -1 0 0 0 12 0.0000 2 135 795 1650 2100 condition\001
     914 1 -1 0 0 0 12 0.0000 2 135 135 2550 1425 X\001
     924 1 -1 0 0 0 12 0.0000 2 135 135 3450 1425 Y\001
     934 1 -1 0 0 0 12 0.0000 2 165 420 4350 600 entry\001
     944 1 -1 0 0 0 12 0.0000 2 135 495 4350 825 queue\001
     954 0 -1 0 0 0 12 0.0000 2 135 525 4650 1650 arrival\001
     964 0 -1 0 0 0 12 0.0000 2 135 630 4650 1425 order of\001
     974 1 -1 0 0 0 12 0.0000 2 135 525 3450 2925 shared\001
     984 1 -1 0 0 0 12 0.0000 2 135 735 3450 3225 variables\001
     994 1 -1 0 0 0 12 0.0000 2 120 510 3000 975 mutex\001
     1004 1 -1 0 0 0 10 0.0000 2 75 75 3450 1995 c\001
     1014 1 -1 0 0 0 12 0.0000 2 135 570 3000 1200 queues\001
  • doc/papers/general/.gitignore

    rb067d9b r7951100  
    44*.ps
    55
     6Paper.tex.plain
    67mail
    78Paper.out.ps
  • doc/papers/general/Makefile

    rb067d9b r7951100  
    44Figures = figures
    55Macros = ../AMA/AMA-stix/ama
    6 TeXLIB = .:${Macros}:${Build}:
     6TeXLIB = .:${Macros}:${Build}:../../bibliography:
    77LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    8 BibTeX = BIBINPUTS=../../bibliography: && export BIBINPUTS && bibtex
     8BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
    99
    1010MAKEFLAGS = --no-print-directory # --silent
     
    4646
    4747Paper.zip :
    48         zip -x general/.gitignore -x general/Paper.out.ps -x general/Paper.tex.plain -x -x general/WileyNJD-AMA.bst general/"*evaluation*" -x general/evaluation.zip \
    49                 -x general/mail -x general/response -x general/test.c -x general/Paper.ps -x general/"*build*" -r Paper.zip general pl.bib
     48        zip -x general/.gitignore -x general/"*AMA*" -x general/Paper.out.ps -x general/Paper.tex.plain -x general/evaluation.zip -x general/mail -x general/response -x general/test.c -x general/evaluation.zip -x general/Paper.tex.plain -x general/Paper.ps -x general/Paper.pdf -x general/"*build*" -x general/evaluation/.gitignore -x general/evaluation/timing.xlsx -r Paper.zip general
    5049
    5150evaluation.zip :
    52         zip -x evaluation/.gitignore -x evaluation/timing.xlsx -x evaluation/timing.dat -r evaluation.zip evaluation
     51        zip -x evaluation/.gitignore  -x evaluation/timing.xlsx -x evaluation/timing.dat -r evaluation.zip evaluation
    5352
    5453# File Dependencies #
     
    6059        dvips ${Build}/$< -o $@
    6160
    62 ${BASE}.dvi : Makefile ${BASE}.out.ps ${Macros}/WileyNJD-v2.cls WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    63                 ../../bibliography/pl.bib | ${Build}
     61${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     62                ../../bibliography/pl.bib
    6463        # Must have *.aux file containing citations for bibtex
    6564        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    7675        mkdir -p ${Build}
    7776
    78 ${BASE}.out.ps : | ${Build}
     77${BASE}.out.ps : ${Build}
    7978        ln -fs ${Build}/Paper.out.ps .
    8079
     
    8584        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    8685
    87 %.tex : %.fig | ${Build}
     86%.tex : %.fig ${Build}
    8887        fig2dev -L eepic $< > ${Build}/$@
    8988
    90 %.ps : %.fig | ${Build}
     89%.ps : %.fig ${Build}
    9190        fig2dev -L ps $< > ${Build}/$@
    9291
    93 %.pstex : %.fig | ${Build}
     92%.pstex : %.fig ${Build}
    9493        fig2dev -L pstex $< > ${Build}/$@
    9594        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/general/Paper.tex

    rb067d9b r7951100  
    11\documentclass[AMA,STIX1COL]{WileyNJD-v2}
    2 \setlength\typewidth{170mm}
    3 \setlength\textwidth{170mm}
    42
    53\articletype{RESEARCH ARTICLE}%
    64
    7 \received{12 March 2018}
    8 \revised{8 May 2018}
    9 \accepted{28 June 2018}
    10 
    11 \setlength\typewidth{168mm}
    12 \setlength\textwidth{168mm}
     5\received{26 April 2016}
     6\revised{6 June 2016}
     7\accepted{6 June 2016}
     8
    139\raggedbottom
    1410
     
    191187}
    192188
    193 \title{\texorpdfstring{\protect\CFA : Adding modern programming language features to C}{Cforall : Adding modern programming language features to C}}
     189\title{\texorpdfstring{\protect\CFA : Adding Modern Programming Language Features to C}{Cforall : Adding Modern Programming Language Features to C}}
    194190
    195191\author[1]{Aaron Moss}
    196192\author[1]{Robert Schluntz}
    197 \author[1]{Peter A. Buhr}
     193\author[1]{Peter A. Buhr*}
    198194\authormark{MOSS \textsc{et al}}
    199195
    200 \address[1]{\orgdiv{Cheriton School of Computer Science}, \orgname{University of Waterloo}, \orgaddress{\state{Waterloo, Ontario}, \country{Canada}}}
    201 
    202 \corres{Peter A. Buhr, Cheriton School of Computer Science, University of Waterloo, 200 University Avenue West, Waterloo, ON N2L 3G1, Canada. \email{pabuhr{\char`\@}uwaterloo.ca}}
     196\address[1]{\orgdiv{Cheriton School of Computer Science}, \orgname{University of Waterloo}, \orgaddress{\state{Waterloo, ON}, \country{Canada}}}
     197
     198\corres{*Peter A. Buhr, Cheriton School of Computer Science, University of Waterloo, 200 University Avenue West, Waterloo, ON, N2L 3G1, Canada. \email{pabuhr{\char`\@}uwaterloo.ca}}
    203199
    204200\fundingInfo{Natural Sciences and Engineering Research Council of Canada}
    205201
    206202\abstract[Summary]{
    207 The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from hobby projects to commercial operating systems.
    208 This installation base and the programmers producing it represent a massive software engineering investment spanning decades and likely to continue for decades more.
    209 Nevertheless, C, which was first standardized almost 30 years ago, lacks many features that make programming in more modern languages safer and more productive.
    210 The goal of the \CFA project (pronounced ``C for all'') is to create an extension of C that provides modern safety and productivity features while still ensuring strong backward compatibility with C and its programmers.
    211 Prior projects have attempted similar goals but failed to honor the C programming style;
    212 for instance, adding object-oriented or functional programming with garbage collection is a nonstarter for many C developers.
    213 Specifically, \CFA is designed to have an orthogonal feature set based closely on the C programming paradigm, so that \CFA features can be added \emph{incrementally} to existing C code bases, and C programmers can learn \CFA extensions on an as-needed basis, preserving investment in existing code and programmers.
    214 This paper presents a quick tour of \CFA features, showing how their design avoids shortcomings of similar features in C and other C-like languages.
    215 Experimental results are presented to validate several of the new features.
     203The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from hobby projects to commercial operating-systems.
     204This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
     205Nevertheless, C, first standardized almost forty years ago, lacks many features that make programming in more modern languages safer and more productive.
     206
     207The goal of the \CFA project (pronounced ``C-for-all'') is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers.
     208Prior projects have attempted similar goals but failed to honour C programming-style;
     209for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers.
     210Specifically, \CFA is designed to have an orthogonal feature-set based closely on the C programming paradigm, so that \CFA features can be added \emph{incrementally} to existing C code-bases, and C programmers can learn \CFA extensions on an as-needed basis, preserving investment in existing code and programmers.
     211This paper presents a quick tour of \CFA features showing how their design avoids shortcomings of similar features in C and other C-like languages.
     212Finally, experimental results are presented to validate several of the new features.
    216213}%
    217214
    218 \keywords{C, Cforall, generic types, polymorphic functions, tuple types, variadic types}
     215\keywords{generic types, tuple types, variadic types, polymorphic functions, C, Cforall}
    219216
    220217
    221218\begin{document}
    222 %\linenumbers                                            % comment out to turn off line numbering
     219\linenumbers                                            % comment out to turn off line numbering
    223220
    224221\maketitle
    225222
    226223
    227 \vspace*{-10pt}
    228224\section{Introduction}
    229225
    230 The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from hobby projects to commercial operating systems.
    231 This installation base and the programmers producing it represent a massive software engineering investment spanning decades and likely to continue for decades more.
    232 The TIOBE index~\cite{TIOBE} ranks the top five most \emph{popular} programming languages as Java 15\%, \Textbf{C 12\%}, \Textbf{\CC 5.5\%}, and Python 5\%, \Csharp 4.5\% = 42\%, where the next 50 languages are less than 4\% each with a long tail.
    233 The top three rankings over the past 30 years are as follows.
     226The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from hobby projects to commercial operating-systems.
     227This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
     228The TIOBE~\cite{TIOBE} ranks the top 5 most \emph{popular} programming languages as: Java 15\%, \Textbf{C 12\%}, \Textbf{\CC 5.5\%}, Python 5\%, \Csharp 4.5\% = 42\%, where the next 50 languages are less than 4\% each with a long tail.
     229The top 3 rankings over the past 30 years are:
    234230\begin{center}
    235231\setlength{\tabcolsep}{10pt}
    236 \fontsize{9bp}{11bp}\selectfont
    237 \lstDeleteShortInline@%
    238 \begin{tabular}{@{}cccccccc@{}}
    239                 & 2018  & 2013  & 2008  & 2003  & 1998  & 1993  & 1988  \\
    240 Java    & 1             & 2             & 1             & 1             & 18    & --    & --    \\
     232\lstDeleteShortInline@%
     233\begin{tabular}{@{}rccccccc@{}}
     234                & 2018  & 2013  & 2008  & 2003  & 1998  & 1993  & 1988  \\ \hline
     235Java    & 1             & 2             & 1             & 1             & 18    & -             & -             \\
    241236\Textbf{C}& \Textbf{2} & \Textbf{1} & \Textbf{2} & \Textbf{2} & \Textbf{1} & \Textbf{1} & \Textbf{1} \\
    242237\CC             & 3             & 4             & 3             & 3             & 2             & 2             & 5             \\
     
    246241Love it or hate it, C is extremely popular, highly used, and one of the few systems languages.
    247242In many cases, \CC is often used solely as a better C.
    248 Nevertheless, C, which was first standardized almost 30 years ago~\cite{ANSI89:C}, lacks many features that make programming in more modern languages safer and more productive.
    249 
    250 \CFA (pronounced ``C for all'' and written \CFA or Cforall) is an evolutionary extension of the C programming language that adds modern language features to C, while maintaining source and runtime compatibility in the familiar C programming model.
    251 The four key design goals for \CFA~\cite{Bilson03} are as follows:
    252 (1) the behavior of standard C code must remain the same when translated by a \CFA compiler as when translated by a C compiler;
    253 (2) the standard C code must be as fast and as small when translated by a \CFA compiler as when translated by a C compiler;
    254 (3) the \CFA code must be at least as portable as standard C code;
    255 (4) extensions introduced by \CFA must be translated in the most efficient way possible.
    256 These goals ensure that the existing C code bases can be converted into \CFA incrementally with minimal effort, and C programmers can productively generate \CFA code without training beyond the features being used.
    257 \CC is used similarly but has the disadvantages of multiple legacy design choices that cannot be updated and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project.
    258 
    259 All language features discussed in this paper are working, except some advanced exception-handling features.
    260 Not discussed in this paper are the integrated concurrency constructs and user-level threading library~\cite{Delisle18}.
     243Nevertheless, C, first standardized almost forty years ago~\cite{ANSI89:C}, lacks many features that make programming in more modern languages safer and more productive.
     244
     245\CFA (pronounced ``C-for-all'', and written \CFA or Cforall) is an evolutionary extension of the C programming language that adds modern language-features to C, while maintaining source and runtime compatibility in the familiar C programming model.
     246The four key design goals for \CFA~\cite{Bilson03} are:
     247(1) The behaviour of standard C code must remain the same when translated by a \CFA compiler as when translated by a C compiler;
     248(2) Standard C code must be as fast and as small when translated by a \CFA compiler as when translated by a C compiler;
     249(3) \CFA code must be at least as portable as standard C code;
     250(4) Extensions introduced by \CFA must be translated in the most efficient way possible.
     251These goals ensure existing C code-bases can be converted to \CFA incrementally with minimal effort, and C programmers can productively generate \CFA code without training beyond the features being used.
     252\CC is used similarly, but has the disadvantages of multiple legacy design-choices that cannot be updated and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project.
     253
     254All languages features discussed in this paper are working, except some advanced exception-handling features.
     255Not discussed in this paper are the integrated concurrency-constructs and user-level threading-library~\cite{Delisle18}.
    261256\CFA is an \emph{open-source} project implemented as a source-to-source translator from \CFA to the gcc-dialect of C~\cite{GCCExtensions}, allowing it to leverage the portability and code optimizations provided by gcc, meeting goals (1)--(3).
     257Ultimately, a compiler is necessary for advanced features and optimal performance.
    262258% @plg2[9]% cd cfa-cc/src; cloc ArgTweak CodeGen CodeTools Common Concurrency ControlStruct Designators GenPoly InitTweak MakeLibCfa.cc MakeLibCfa.h Parser ResolvExpr SymTab SynTree Tuples driver prelude main.cc
    263259% -------------------------------------------------------------------------------
     
    274270% SUM:                           223           8203           8263          46479
    275271% -------------------------------------------------------------------------------
    276 The \CFA translator is 200+ files and 46\,000+ lines of code written in C/\CC.
    277 A translator versus a compiler makes it easier and faster to generate and debug the C object code rather than the intermediate, assembler, or machine code;
    278 ultimately, a compiler is necessary for advanced features and optimal performance.
    279 % The translator design is based on the \emph{visitor pattern}, allowing multiple passes over the abstract code-tree, which works well for incrementally adding new feature through additional visitor passes.
    280 Two key translator components are expression analysis, determining expression validity and what operations are required for its implementation, and code generation, dealing with multiple forms of overloading, polymorphism, and multiple return values by converting them into the C code for a C compiler that supports none of these features.
    281 Details of these components are available in chapters 2 and 3 in the work of Bilson~\cite{Bilson03} and form the base for the current \CFA translator.
     272The \CFA translator is 200+ files and 46,000+ lines of code written in C/\CC.
     273Starting with a translator versus a compiler makes it easier and faster to generate and debug C object-code rather than intermediate, assembler or machine code.
     274The translator design is based on the \emph{visitor pattern}, allowing multiple passes over the abstract code-tree, which works well for incrementally adding new feature through additional visitor passes.
     275At the heart of the translator is the type resolver, which handles the polymorphic function/type overload-resolution.
    282276% @plg2[8]% cd cfa-cc/src; cloc libcfa
    283277% -------------------------------------------------------------------------------
     
    294288% SUM:                           100           1895           2785          11763
    295289% -------------------------------------------------------------------------------
    296 The \CFA runtime system is 100+ files and 11\,000+ lines of code, written in \CFA.
     290The \CFA runtime system is 100+ files and 11,000+ lines of code, written in \CFA.
    297291Currently, the \CFA runtime is the largest \emph{user} of \CFA providing a vehicle to test the language features and implementation.
    298292% @plg2[6]% cd cfa-cc/src; cloc tests examples benchmark
     
    311305% SUM:                           290          13175           3400          27776
    312306% -------------------------------------------------------------------------------
    313 % The \CFA tests are 290+ files and 27,000+ lines of code.
    314 % The tests illustrate syntactic and semantic features in \CFA, plus a growing number of runtime benchmarks.
    315 % The tests check for correctness and are used for daily regression testing of 3800+ commits.
    316 
    317 Finally, it is impossible to describe a programming language without usage before definition.
    318 Therefore, syntax and semantics appear before explanations;
    319 hence, patience is necessary until sufficient details are presented and discussed.
    320 Similarly, a detailed comparison with other programming languages is postponed until Section~\ref{s:RelatedWork}.
    321 
    322 
    323 \vspace*{-6pt}
     307The \CFA tests are 290+ files and 27,000+ lines of code.
     308The tests illustrate syntactic and semantic features in \CFA, plus a growing number of runtime benchmarks.
     309The tests check for correctness and are used for daily regression testing of 3800+ commits.
     310
     311Finally, it is impossible to describe a programming language without usages before definitions.
     312Therefore, syntax and semantics appear before explanations, and related work (Section~\ref{s:RelatedWork}) is deferred until \CFA is presented;
     313hence, patience is necessary until details are discussed.
     314
     315
    324316\section{Polymorphic Functions}
    325317
    326 \CFA introduces both ad hoc and parametric polymorphism to C, with a design originally formalized by Ditchfield~\cite{Ditchfield92} and first implemented by Bilson~\cite{Bilson03}.
    327 Shortcomings are identified in the existing approaches to generic and variadic data types in C-like languages and how these shortcomings are avoided in \CFA.
    328 Specifically, the solution is both reusable and type checked, as well as conforming to the design goals of \CFA with ergonomic use of existing C abstractions.
     318\CFA introduces both ad-hoc and parametric polymorphism to C, with a design originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.
     319Shortcomings are identified in existing approaches to generic and variadic data types in C-like languages and how these shortcomings are avoided in \CFA.
     320Specifically, the solution is both reusable and type-checked, as well as conforming to the design goals of \CFA with ergonomic use of existing C abstractions.
    329321The new constructs are empirically compared with C and \CC approaches via performance experiments in Section~\ref{sec:eval}.
    330322
    331323
    332 \vspace*{-6pt}
    333 \subsection{Name overloading}
     324\subsection{Name Overloading}
    334325\label{s:NameOverloading}
    335326
    336327\begin{quote}
    337 ``There are only two hard things in Computer Science: cache invalidation and \emph{naming things}.''---Phil Karlton
     328There are only two hard things in Computer Science: cache invalidation and \emph{naming things} -- Phil Karlton
    338329\end{quote}
    339330\vspace{-9pt}
    340 C already has a limited form of ad hoc polymorphism in its basic arithmetic operators, which apply to a variety of different types using identical syntax.
     331C already has a limited form of ad-hoc polymorphism in its basic arithmetic operators, which apply to a variety of different types using identical syntax.
    341332\CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable;
    342333Section~\ref{sec:libraries} includes a number of examples of how this overloading simplifies \CFA programming relative to C.
    343334Code generation for these overloaded functions and variables is implemented by the usual approach of mangling the identifier names to include a representation of their type, while \CFA decides which overload to apply based on the same ``usual arithmetic conversions'' used in C to disambiguate operator overloads.
    344 
    345 \newpage
     335As an example:
    346336\begin{cfa}
    347337int max = 2147483647;                                           $\C[4in]{// (1)}$
     
    349339int max( int a, int b ) { return a < b ? b : a; }  $\C{// (3)}$
    350340double max( double a, double b ) { return a < b ? b : a; }  $\C{// (4)}\CRT$
    351 max( 7, -max );                                         $\C[3in]{// uses (3) and (1), by matching int from constant 7}$
     341max( 7, -max );                                         $\C{// uses (3) and (1), by matching int from constant 7}$
    352342max( max, 3.14 );                                       $\C{// uses (4) and (2), by matching double from constant 3.14}$
    353343max( max, -max );                                       $\C{// ERROR, ambiguous}$
    354 int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}\CRT$
     344int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}$
    355345\end{cfa}
    356346
     
    358348In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction.
    359349In the above, the name @max@ has a consistent meaning, and a programmer only needs to remember the single concept: maximum.
    360 To prevent significant ambiguities, \CFA uses the return type in selecting overloads, \eg in the assignment to @m@, the compiler uses @m@'s type to unambiguously select the most appropriate call to function @max@ (as does Ada).
     350To prevent significant ambiguities, \CFA uses the return type in selecting overloads, \eg in the assignment to @m@, the compiler use @m@'s type to unambiguously select the most appropriate call to function @max@ (as does Ada).
    361351As is shown later, there are a number of situations where \CFA takes advantage of available type information to disambiguate, where other programming languages generate ambiguities.
    362352
    363 \Celeven added @_Generic@ expressions (see section~6.5.1.1 of the ISO/IEC 9899~\cite{C11}), which is used with preprocessor macros to provide ad hoc polymorphism;
     353\Celeven added @_Generic@ expressions~\cite[\S~6.5.1.1]{C11}, which is used with preprocessor macros to provide ad-hoc polymorphism;
    364354however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading.
    365 The macro wrapping the generic expression imposes some limitations, for instance, it cannot implement the example above, because the variables @max@ are ambiguous with the functions @max@.
     355The macro wrapping the generic expression imposes some limitations;
     356\eg, it cannot implement the example above, because the variables @max@ are ambiguous with the functions @max@.
    366357Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the dispatch functions, which must all have distinct names.
    367 \CFA supports @_Generic@ expressions for backward compatibility, but it is an unnecessary mechanism.
     358\CFA supports @_Generic@ expressions for backwards compatibility, but it is an unnecessary mechanism. \TODO{actually implement that}
    368359
    369360% http://fanf.livejournal.com/144696.html
     
    372363
    373364
    374 \vspace*{-10pt}
    375 \subsection{\texorpdfstring{\protect\lstinline{forall} functions}{forall functions}}
     365\subsection{\texorpdfstring{\protect\lstinline{forall} Functions}{forall Functions}}
    376366\label{sec:poly-fns}
    377367
    378 The signature feature of \CFA is parametric-polymorphic functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a @forall@ clause (giving the language its name).
     368The signature feature of \CFA is parametric-polymorphic functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a @forall@ clause (giving the language its name):
    379369\begin{cfa}
    380370`forall( otype T )` T identity( T val ) { return val; }
     
    383373This @identity@ function can be applied to any complete \newterm{object type} (or @otype@).
    384374The type variable @T@ is transformed into a set of additional implicit parameters encoding sufficient information about @T@ to create and return a variable of that type.
    385 The \CFA implementation passes the size and alignment of the type represented by an @otype@ parameter, as well as an assignment operator, constructor, copy constructor, and destructor.
    386 If this extra information is not needed, for instance, for a pointer, the type parameter can be declared as a \newterm{data type} (or @dtype@).
    387 
    388 In \CFA, the polymorphic runtime cost is spread over each polymorphic call, because more arguments are passed to polymorphic functions;
    389 the experiments in Section~\ref{sec:eval} show this overhead is similar to \CC virtual function calls.
    390 A design advantage is that, unlike \CC template functions, \CFA polymorphic functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat.
    391 
    392 Since bare polymorphic types provide a restricted set of available operations, \CFA provides a \newterm{type assertion}~\cite[pp.~37-44]{Alphard} mechanism to provide further type information, where type assertions may be variable or function declarations that depend on a polymorphic type variable.
    393 For example, the function @twice@ can be defined using the \CFA syntax for operator overloading.
     375The \CFA implementation passes the size and alignment of the type represented by an @otype@ parameter, as well as an assignment operator, constructor, copy constructor and destructor.
     376If this extra information is not needed, \eg for a pointer, the type parameter can be declared as a \newterm{data type} (or @dtype@).
     377
     378In \CFA, the polymorphic runtime-cost is spread over each polymorphic call, because more arguments are passed to polymorphic functions;
     379the experiments in Section~\ref{sec:eval} show this overhead is similar to \CC virtual-function calls.
     380A design advantage is that, unlike \CC template-functions, \CFA polymorphic-functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat.
     381
     382Since bare polymorphic-types provide a restricted set of available operations, \CFA provides a \newterm{type assertion}~\cite[pp.~37-44]{Alphard} mechanism to provide further type information, where type assertions may be variable or function declarations that depend on a polymorphic type-variable.
     383For example, the function @twice@ can be defined using the \CFA syntax for operator overloading:
    394384\begin{cfa}
    395385forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x `+` x; }  $\C{// ? denotes operands}$
    396386int val = twice( twice( 3.7 ) );  $\C{// val == 14}$
    397387\end{cfa}
    398 This works for any type @T@ with a matching addition operator.
    399 The polymorphism is achieved by creating a wrapper function for calling @+@ with the @T@ bound to @double@ and then passing this function to the first call of @twice@.
    400 There is now the option of using the same @twice@ and converting the result into @int@ on assignment or creating another @twice@ with the type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} in its type analysis.
    401 The first approach has a late conversion from @double@ to @int@ on the final assignment, whereas the second has an early conversion to @int@.
    402 \CFA minimizes the number of conversions and their potential to lose information;
    403 hence, it selects the first approach, which corresponds with C programmer intuition.
     388which works for any type @T@ with a matching addition operator.
     389The polymorphism is achieved by creating a wrapper function for calling @+@ with @T@ bound to @double@, then passing this function to the first call of @twice@.
     390There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} in its type analysis.
     391The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an early conversion to @int@.
     392\CFA minimizes the number of conversions and their potential to lose information, so it selects the first approach, which corresponds with C-programmer intuition.
    404393
    405394Crucial to the design of a new programming language are the libraries to access thousands of external software features.
    406 Like \CC, \CFA inherits a massive compatible library base, where other programming languages must rewrite or provide fragile interlanguage communication with C.
    407 A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array.
     395Like \CC, \CFA inherits a massive compatible library-base, where other programming languages must rewrite or provide fragile inter-language communication with C.
     396A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array:
    408397\begin{cfa}
    409398void * bsearch( const void * key, const void * base, size_t nmemb, size_t size,
     
    415404double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$
    416405\end{cfa}
    417 This can be augmented simply with generalized, type-safe, \CFA-overloaded wrappers.
     406which can be augmented simply with generalized, type-safe, \CFA-overloaded wrappers:
    418407\begin{cfa}
    419408forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
     
    429418\end{cfa}
    430419The nested function @comp@ provides the hidden interface from typed \CFA to untyped (@void *@) C, plus the cast of the result.
    431 % FIX
    432 Providing a hidden @comp@ function in \CC is awkward as lambdas do not use C calling conventions and template declarations cannot appear in block scope.
    433 In addition, an alternate kind of return is made available: position versus pointer to found element.
    434 \CC's type system cannot disambiguate between the two versions of @bsearch@ because it does not use the return type in overload resolution, nor can \CC separately compile a template @bsearch@.
     420Providing a hidden @comp@ function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
     421As well, an alternate kind of return is made available: position versus pointer to found element.
     422\CC's type-system cannot disambiguate between the two versions of @bsearch@ because it does not use the return type in overload resolution, nor can \CC separately compile a template @bsearch@.
    435423
    436424\CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations (see Section~\ref{sec:libraries}).
     
    442430\end{cfa}
    443431
    444 Call site inferencing and nested functions provide a localized form of inheritance.
     432Call-site inferencing and nested functions provide a localized form of inheritance.
    445433For example, the \CFA @qsort@ only sorts in ascending order using @<@.
    446 However, it is trivial to locally change this behavior.
     434However, it is trivial to locally change this behaviour:
    447435\begin{cfa}
    448436forall( otype T | { int ?<?( T, T ); } ) void qsort( const T * arr, size_t size ) { /* use C qsort */ }
    449437int main() {
    450         int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behavior}$
     438        int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behaviour}$
    451439        qsort( vals, 10 );                                                      $\C{// descending sort}$
    452440}
    453441\end{cfa}
    454442The local version of @?<?@ performs @?>?@ overriding the built-in @?<?@ so it is passed to @qsort@.
    455 Therefore, programmers can easily form local environments, adding and modifying appropriate functions, to maximize the reuse of other existing functions and types.
    456 
    457 To reduce duplication, it is possible to distribute a group of @forall@ (and storage-class qualifiers) over functions/types, such that each block declaration is prefixed by the group (see the example in Appendix~\ref{s:CforallStack}).
     443Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types.
     444
     445To reduce duplication, it is possible to distribute a group of @forall@ (and storage-class qualifiers) over functions/types, so each block declaration is prefixed by the group (see example in Appendix~\ref{s:CforallStack}).
    458446\begin{cfa}
    459447forall( otype `T` ) {                                                   $\C{// distribution block, add forall qualifier to declarations}$
     
    466454
    467455
     456\vspace*{-2pt}
    468457\subsection{Traits}
    469458
    470 \CFA provides \newterm{traits} to name a group of type assertions, where the trait name allows specifying the same set of assertions in multiple locations, preventing repetition mistakes at each function declaration.
     459\CFA provides \newterm{traits} to name a group of type assertions, where the trait name allows specifying the same set of assertions in multiple locations, preventing repetition mistakes at each function declaration:
     460
    471461\begin{cquote}
    472462\lstDeleteShortInline@%
     
    495485\end{cquote}
    496486
    497 Note that the @sumable@ trait does not include a copy constructor needed for the right side of @?+=?@ and return;
    498 it is provided by @otype@, which is syntactic sugar for the following trait.
     487Note, the @sumable@ trait does not include a copy constructor needed for the right side of @?+=?@ and return;
     488it is provided by @otype@, which is syntactic sugar for the following trait:
    499489\begin{cfa}
    500490trait otype( dtype T | sized(T) ) {  // sized is a pseudo-trait for types with known size and alignment
     
    505495};
    506496\end{cfa}
    507 Given the information provided for an @otype@, variables of polymorphic type can be treated as if they were a complete type: stack allocatable, default or copy initialized, assigned, and deleted.
    508 
    509 In summation, the \CFA type system uses \newterm{nominal typing} for concrete types, matching with the C type system, and \newterm{structural typing} for polymorphic types.
     497Given the information provided for an @otype@, variables of polymorphic type can be treated as if they were a complete type: stack-allocatable, default or copy-initialized, assigned, and deleted.
     498
     499In summation, the \CFA type-system uses \newterm{nominal typing} for concrete types, matching with the C type-system, and \newterm{structural typing} for polymorphic types.
    510500Hence, trait names play no part in type equivalence;
    511501the names are simply macros for a list of polymorphic assertions, which are expanded at usage sites.
    512 Nevertheless, trait names form a logical subtype hierarchy with @dtype@ at the top, where traits often contain overlapping assertions, \eg operator @+@.
    513 Traits are used like interfaces in Java or abstract base classes in \CC, but without the nominal inheritance relationships.
    514 Instead, each polymorphic function (or generic type) defines the structural type needed for its execution (polymorphic type key), and this key is fulfilled at each call site from the lexical environment, which is similar to the Go~\cite{Go} interfaces.
    515 Hence, new lexical scopes and nested functions are used extensively to create local subtypes, as in the @qsort@ example, without having to manage a nominal inheritance hierarchy.
     502Nevertheless, trait names form a logical subtype-hierarchy with @dtype@ at the top, where traits often contain overlapping assertions, \eg operator @+@.
     503Traits are used like interfaces in Java or abstract base-classes in \CC, but without the nominal inheritance-relationships.
     504Instead, each polymorphic function (or generic type) defines the structural type needed for its execution (polymorphic type-key), and this key is fulfilled at each call site from the lexical environment, which is similar to Go~\cite{Go} interfaces.
     505Hence, new lexical scopes and nested functions are used extensively to create local subtypes, as in the @qsort@ example, without having to manage a nominal-inheritance hierarchy.
    516506% (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.)
    517507
     
    544534
    545535A significant shortcoming of standard C is the lack of reusable type-safe abstractions for generic data structures and algorithms.
    546 Broadly speaking, there are three approaches to implement abstract data structures in C.
    547 One approach is to write bespoke data structures for each context in which they are needed.
    548 While this approach is flexible and supports integration with the C type checker and tooling, it is also tedious and error prone, especially for more complex data structures.
    549 A second approach is to use @void *@-based polymorphism, \eg the C standard library functions @bsearch@ and @qsort@, which allow for the reuse of code with common functionality.
    550 However, basing all polymorphism on @void *@ eliminates the type checker's ability to ensure that argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that is otherwise not needed.
    551 A third approach to generic code is to use preprocessor macros, which does allow the generated code to be both generic and type checked, but errors may be difficult to interpret.
     536Broadly speaking, there are three approaches to implement abstract data-structures in C.
     537One approach is to write bespoke data-structures for each context in which they are needed.
     538While this approach is flexible and supports integration with the C type-checker and tooling, it is also tedious and error-prone, especially for more complex data structures.
     539A second approach is to use @void *@-based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@, which allow reuse of code with common functionality.
     540However, basing all polymorphism on @void *@ eliminates the type-checker's ability to ensure that argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that is not otherwise needed.
     541A third approach to generic code is to use preprocessor macros, which does allow the generated code to be both generic and type-checked, but errors may be difficult to interpret.
    552542Furthermore, writing and using preprocessor macros is unnatural and inflexible.
    553543
    554 \CC, Java, and other languages use \newterm{generic types} to produce type-safe abstract data types.
    555 \CFA generic types integrate efficiently and naturally with the existing polymorphic functions, while retaining backward compatibility with C and providing separate compilation.
     544\CC, Java, and other languages use \newterm{generic types} to produce type-safe abstract data-types.
     545\CFA generic types integrate efficiently and naturally with the existing polymorphic functions, while retaining backwards compatibility with C and providing separate compilation.
    556546However, for known concrete parameters, the generic-type definition can be inlined, like \CC templates.
    557547
    558 A generic type can be declared by placing a @forall@ specifier on a @struct@ or @union@ declaration and instantiated using a parenthesized list of types after the type name.
     548A generic type can be declared by placing a @forall@ specifier on a @struct@ or @union@ declaration, and instantiated using a parenthesized list of types after the type name:
    559549\begin{cquote}
    560550\lstDeleteShortInline@%
     
    584574
    585575\CFA classifies generic types as either \newterm{concrete} or \newterm{dynamic}.
    586 Concrete types have a fixed memory layout regardless of type parameters, whereas dynamic types vary in memory layout depending on their type parameters.
     576Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters.
    587577A \newterm{dtype-static} type has polymorphic parameters but is still concrete.
    588578Polymorphic pointers are an example of dtype-static types;
    589 given some type variable @T@, @T@ is a polymorphic type, as is @T *@, but @T *@ has a fixed size and can, therefore, be represented by @void *@ in code generation.
    590 
    591 \CFA generic types also allow checked argument constraints.
    592 For example, the following declaration of a sorted set type ensures the set key supports equality and relational comparison.
     579given some type variable @T@, @T@ is a polymorphic type, as is @T *@, but @T *@ has a fixed size and can therefore be represented by @void *@ in code generation.
     580
     581\CFA generic types also allow checked argument-constraints.
     582For example, the following declaration of a sorted set-type ensures the set key supports equality and relational comparison:
    593583\begin{cfa}
    594584forall( otype Key | { _Bool ?==?(Key, Key); _Bool ?<?(Key, Key); } ) struct sorted_set;
     
    596586
    597587
    598 \subsection{Concrete generic types}
    599 
    600 The \CFA translator template expands concrete generic types into new structure types, affording maximal inlining.
    601 To enable interoperation among equivalent instantiations of a generic type, the translator saves the set of instantiations currently in scope and reuses the generated structure declarations where appropriate.
    602 A function declaration that accepts or returns a concrete generic type produces a declaration for the instantiated structure in the same scope, which all callers may reuse.
    603 For example, the concrete instantiation for @pair( const char *, int )@ is
     588\subsection{Concrete Generic-Types}
     589
     590The \CFA translator template-expands concrete generic-types into new structure types, affording maximal inlining.
     591To enable inter-operation among equivalent instantiations of a generic type, the translator saves the set of instantiations currently in scope and reuses the generated structure declarations where appropriate.
     592A function declaration that accepts or returns a concrete generic-type produces a declaration for the instantiated structure in the same scope, which all callers may reuse.
     593For example, the concrete instantiation for @pair( const char *, int )@ is:
    604594\begin{cfa}
    605595struct _pair_conc0 {
     
    608598\end{cfa}
    609599
    610 A concrete generic type with dtype-static parameters is also expanded to a structure type, but this type is used for all matching instantiations.
    611 In the above example, the @pair( F *, T * )@ parameter to @value@ is such a type; its expansion is below, and it is used as the type of the variables @q@ and @r@ as well, with casts for member access where appropriate.
     600A concrete generic-type with dtype-static parameters is also expanded to a structure type, but this type is used for all matching instantiations.
     601In the above example, the @pair( F *, T * )@ parameter to @value@ is such a type; its expansion is below and it is used as the type of the variables @q@ and @r@ as well, with casts for member access where appropriate:
    612602\begin{cfa}
    613603struct _pair_conc1 {
     
    617607
    618608
    619 \subsection{Dynamic generic types}
    620 
    621 Though \CFA implements concrete generic types efficiently, it also has a fully general system for dynamic generic types.
    622 As mentioned in Section~\ref{sec:poly-fns}, @otype@ function parameters (in fact, all @sized@ polymorphic parameters) come with implicit size and alignment parameters provided by the caller.
    623 Dynamic generic types also have an \newterm{offset array} containing structure-member offsets.
    624 A dynamic generic @union@ needs no such offset array, as all members are at offset 0, but size and alignment are still necessary.
    625 Access to members of a dynamic structure is provided at runtime via base displacement addressing
    626 % FIX
    627 using the structure pointer and the member offset (similar to the @offsetof@ macro), moving a compile-time offset calculation to runtime.
     609\subsection{Dynamic Generic-Types}
     610
     611Though \CFA implements concrete generic-types efficiently, it also has a fully general system for dynamic generic types.
     612As mentioned in Section~\ref{sec:poly-fns}, @otype@ function parameters (in fact all @sized@ polymorphic parameters) come with implicit size and alignment parameters provided by the caller.
     613Dynamic generic-types also have an \newterm{offset array} containing structure-member offsets.
     614A dynamic generic-@union@ needs no such offset array, as all members are at offset 0, but size and alignment are still necessary.
     615Access to members of a dynamic structure is provided at runtime via base-displacement addressing with the structure pointer and the member offset (similar to the @offsetof@ macro), moving a compile-time offset calculation to runtime.
    628616
    629617The offset arrays are statically generated where possible.
    630 If a dynamic generic type is declared to be passed or returned by value from a polymorphic function, the translator can safely assume that the generic type is complete (\ie has a known layout) at any call site, and the offset array is passed from the caller;
     618If a dynamic generic-type is declared to be passed or returned by value from a polymorphic function, the translator can safely assume the generic type is complete (\ie has a known layout) at any call-site, and the offset array is passed from the caller;
    631619if the generic type is concrete at the call site, the elements of this offset array can even be statically generated using the C @offsetof@ macro.
    632 As an example, the body of the second @value@ function is implemented as
     620As an example, the body of the second @value@ function is implemented as:
    633621\begin{cfa}
    634622_assign_T( _retval, p + _offsetof_pair[1] ); $\C{// return *p.second}$
    635623\end{cfa}
    636 \newpage
    637 \noindent
    638 Here, @_assign_T@ is passed in as an implicit parameter from @otype T@, and takes two @T *@ (@void *@ in the generated code), a destination and a source, and @_retval@ is the pointer to a caller-allocated buffer for the return value, the usual \CFA method to handle dynamically sized return types.
    639 @_offsetof_pair@ is the offset array passed into @value@;
    640 this array is generated at the call site as
     624@_assign_T@ is passed in as an implicit parameter from @otype T@, and takes two @T *@ (@void *@ in the generated code), a destination and a source; @_retval@ is the pointer to a caller-allocated buffer for the return value, the usual \CFA method to handle dynamically-sized return types.
     625@_offsetof_pair@ is the offset array passed into @value@; this array is generated at the call site as:
    641626\begin{cfa}
    642627size_t _offsetof_pair[] = { offsetof( _pair_conc0, first ), offsetof( _pair_conc0, second ) }
    643628\end{cfa}
    644629
    645 In some cases, the offset arrays cannot be statically generated.
    646 For instance, modularity is generally provided in C by including an opaque forward declaration of a structure and associated accessor and mutator functions in a header file, with the actual implementations in a separately compiled @.c@ file.
    647 \CFA supports this pattern for generic types, but the caller does not know the actual layout or size of the dynamic generic type and only holds it by a pointer.
     630In some cases the offset arrays cannot be statically generated.
     631For instance, modularity is generally provided in C by including an opaque forward-declaration of a structure and associated accessor and mutator functions in a header file, with the actual implementations in a separately-compiled @.c@ file.
     632\CFA supports this pattern for generic types, but the caller does not know the actual layout or size of the dynamic generic-type, and only holds it by a pointer.
    648633The \CFA translator automatically generates \newterm{layout functions} for cases where the size, alignment, and offset array of a generic struct cannot be passed into a function from that function's caller.
    649634These layout functions take as arguments pointers to size and alignment variables and a caller-allocated array of member offsets, as well as the size and alignment of all @sized@ parameters to the generic structure (un@sized@ parameters are forbidden from being used in a context that affects layout).
     
    655640Whether a type is concrete, dtype-static, or dynamic is decided solely on the @forall@'s type parameters.
    656641This design allows opaque forward declarations of generic types, \eg @forall(otype T)@ @struct Box@ -- like in C, all uses of @Box(T)@ can be separately compiled, and callers from other translation units know the proper calling conventions to use.
    657 If the definition of a structure type is included in deciding whether a generic type is dynamic or concrete, some further types may be recognized as dtype-static (\eg @forall(otype T)@ @struct unique_ptr { T * p }@ does not depend on @T@ for its layout, but the existence of an @otype@ parameter means that it \emph{could}.);
    658 however, preserving separate compilation (and the associated C compatibility) in the existing design is judged to be an appropriate trade-off.
     642If the definition of a structure type is included in deciding whether a generic type is dynamic or concrete, some further types may be recognized as dtype-static (\eg @forall(otype T)@ @struct unique_ptr { T * p }@ does not depend on @T@ for its layout, but the existence of an @otype@ parameter means that it \emph{could}.), but preserving separate compilation (and the associated C compatibility) in the existing design is judged to be an appropriate trade-off.
    659643
    660644
     
    669653}
    670654\end{cfa}
    671 Since @pair( T *, T * )@ is a concrete type, there are no implicit parameters passed to @lexcmp@;
    672 hence, the generated code is identical to a function written in standard C using @void *@, yet the \CFA version is type checked to ensure members of both pairs and arguments to the comparison function match in type.
    673 
    674 Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \newterm{tag structures}.
    675 Sometimes, information is only used for type checking and can be omitted at runtime.
     655Since @pair( T *, T * )@ is a concrete type, there are no implicit parameters passed to @lexcmp@, so the generated code is identical to a function written in standard C using @void *@, yet the \CFA version is type-checked to ensure the members of both pairs and the arguments to the comparison function match in type.
     656
     657Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \newterm{tag-structures}.
     658Sometimes information is only used for type-checking and can be omitted at runtime, \eg:
    676659\begin{cquote}
    677660\lstDeleteShortInline@%
     
    692675                                                        half_marathon;
    693676scalar(litres) two_pools = pool + pool;
    694 `marathon + pool;` // ERROR, mismatched types
     677`marathon + pool;`      // ERROR, mismatched types
    695678\end{cfa}
    696679\end{tabular}
    697680\lstMakeShortInline@%
    698681\end{cquote}
    699 Here, @scalar@ is a dtype-static type;
    700 hence, all uses have a single structure definition, containing @unsigned long@, and can share the same implementations of common functions like @?+?@.
     682@scalar@ is a dtype-static type, so all uses have a single structure definition, containing @unsigned long@, and can share the same implementations of common functions like @?+?@.
    701683These implementations may even be separately compiled, unlike \CC template functions.
    702 However, the \CFA type checker ensures matching types are used by all calls to @?+?@, preventing nonsensical computations like adding a length to a volume.
     684However, the \CFA type-checker ensures matching types are used by all calls to @?+?@, preventing nonsensical computations like adding a length to a volume.
    703685
    704686
     
    706688\label{sec:tuples}
    707689
    708 In many languages, functions can return, at most, one value;
     690In many languages, functions can return at most one value;
    709691however, many operations have multiple outcomes, some exceptional.
    710692Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and float values, respectively.
     
    717699double r = remquo( 13.5, 5.2, &q );                     $\C{// return remainder, alias quotient}$
    718700\end{cfa}
    719 Here, @div@ aggregates the quotient/remainder in a structure, whereas @remquo@ aliases a parameter to an argument.
     701@div@ aggregates the quotient/remainder in a structure, while @remquo@ aliases a parameter to an argument.
    720702Both approaches are awkward.
    721 % FIX
    722 Alternatively, a programming language can directly support returning multiple values, \eg \CFA provides the following.
     703Alternatively, a programming language can directly support returning multiple values, \eg in \CFA:
    723704\begin{cfa}
    724705[ int, int ] div( int num, int den );           $\C{// return two integers}$
     
    731712This approach is straightforward to understand and use;
    732713therefore, why do few programming languages support this obvious feature or provide it awkwardly?
    733 To answer, there are complex consequences that cascade through multiple aspects of the language, especially the type system.
    734 This section shows these consequences and how \CFA handles them.
     714To answer, there are complex consequences that cascade through multiple aspects of the language, especially the type-system.
     715This section show these consequences and how \CFA handles them.
    735716
    736717
    737718\subsection{Tuple Expressions}
    738719
    739 The addition of multiple-return-value functions (MRVFs) is \emph{useless} without a syntax for accepting multiple values at the call site.
     720The addition of multiple-return-value functions (MRVF) are \emph{useless} without a syntax for accepting multiple values at the call-site.
    740721The simplest mechanism for capturing the return values is variable assignment, allowing the values to be retrieved directly.
    741722As such, \CFA allows assigning multiple values from a function into multiple variables, using a square-bracketed list of lvalue expressions (as above), called a \newterm{tuple}.
    742723
    743 However, functions also use \newterm{composition} (nested calls), with the direct consequence that MRVFs must also support composition to be orthogonal with single-returning-value functions (SRVFs), \eg, \CFA provides the following.
     724However, functions also use \newterm{composition} (nested calls), with the direct consequence that MRVFs must also support composition to be orthogonal with single-returning-value functions (SRVF), \eg:
    744725\begin{cfa}
    745726printf( "%d %d\n", div( 13, 5 ) );                      $\C{// return values seperated into arguments}$
    746727\end{cfa}
    747728Here, the values returned by @div@ are composed with the call to @printf@ by flattening the tuple into separate arguments.
    748 However, the \CFA type-system must support significantly more complex composition.
     729However, the \CFA type-system must support significantly more complex composition:
    749730\begin{cfa}
    750731[ int, int ] foo$\(_1\)$( int );                        $\C{// overloaded foo functions}$
     
    753734`bar`( foo( 3 ), foo( 3 ) );
    754735\end{cfa}
    755 The type resolver only has the tuple return types to resolve the call to @bar@ as the @foo@ parameters are identical, which involves unifying the possible @foo@ functions with @bar@'s parameter list.
    756 No combination of @foo@s is an exact match with @bar@'s parameters;
    757 thus, the resolver applies C conversions.
    758 % FIX
     736The type-resolver only has the tuple return-types to resolve the call to @bar@ as the @foo@ parameters are identical, which involves unifying the possible @foo@ functions with @bar@'s parameter list.
     737No combination of @foo@s are an exact match with @bar@'s parameters, so the resolver applies C conversions.
    759738The minimal cost is @bar( foo@$_1$@( 3 ), foo@$_2$@( 3 ) )@, giving (@int@, {\color{ForestGreen}@int@}, @double@) to (@int@, {\color{ForestGreen}@double@}, @double@) with one {\color{ForestGreen}safe} (widening) conversion from @int@ to @double@ versus ({\color{red}@double@}, {\color{ForestGreen}@int@}, {\color{ForestGreen}@int@}) to ({\color{red}@int@}, {\color{ForestGreen}@double@}, {\color{ForestGreen}@double@}) with one {\color{red}unsafe} (narrowing) conversion from @double@ to @int@ and two safe conversions.
    760739
    761740
    762 \subsection{Tuple variables}
     741\subsection{Tuple Variables}
    763742
    764743An important observation from function composition is that new variable names are not required to initialize parameters from an MRVF.
    765 \CFA also allows declaration of tuple variables that can be initialized from an MRVF, since it can be awkward to declare multiple variables of different types.
    766 \newpage
     744\CFA also allows declaration of tuple variables that can be initialized from an MRVF, since it can be awkward to declare multiple variables of different types, \eg:
    767745\begin{cfa}
    768746[ int, int ] qr = div( 13, 5 );                         $\C{// tuple-variable declaration and initialization}$
    769747[ double, double ] qr = div( 13.5, 5.2 );
    770748\end{cfa}
    771 Here, the tuple variable name serves the same purpose as the parameter name(s).
     749where the tuple variable-name serves the same purpose as the parameter name(s).
    772750Tuple variables can be composed of any types, except for array types, since array sizes are generally unknown in C.
    773751
    774 One way to access the tuple variable components is with assignment or composition.
     752One way to access the tuple-variable components is with assignment or composition:
    775753\begin{cfa}
    776754[ q, r ] = qr;                                                          $\C{// access tuple-variable components}$
    777755printf( "%d %d\n", qr );
    778756\end{cfa}
    779 \CFA also supports \newterm{tuple indexing} to access single components of a tuple expression.
     757\CFA also supports \newterm{tuple indexing} to access single components of a tuple expression:
    780758\begin{cfa}
    781759[int, int] * p = &qr;                                           $\C{// tuple pointer}$
     
    788766
    789767
    790 \subsection{Flattening and restructuring}
     768\subsection{Flattening and Restructuring}
    791769
    792770In function call contexts, tuples support implicit flattening and restructuring conversions.
    793771Tuple flattening recursively expands a tuple into the list of its basic components.
    794 Tuple structuring packages a list of expressions into a value of tuple type.
     772Tuple structuring packages a list of expressions into a value of tuple type, \eg:
    795773\begin{cfa}
    796774int f( int, int );
     
    803781h( x, y );                                                                      $\C{// flatten and structure}$
    804782\end{cfa}
    805 In the call to @f@, @x@ is implicitly flattened so the components of @x@ are passed as two arguments.
     783In the call to @f@, @x@ is implicitly flattened so the components of @x@ are passed as the two arguments.
    806784In the call to @g@, the values @y@ and @10@ are structured into a single argument of type @[int, int]@ to match the parameter type of @g@.
    807785Finally, in the call to @h@, @x@ is flattened to yield an argument list of length 3, of which the first component of @x@ is passed as the first parameter of @h@, and the second component of @x@ and @y@ are structured into the second argument of type @[int, int]@.
    808 The flexible structure of tuples permits a simple and expressive function call syntax to work seamlessly with both SRVFs and MRVFs with any number of arguments of arbitrarily complex structure.
    809 
    810 
    811 \subsection{Tuple assignment}
    812 
    813 \enlargethispage{-10pt}
     786The flexible structure of tuples permits a simple and expressive function call syntax to work seamlessly with both SRVF and MRVF, and with any number of arguments of arbitrarily complex structure.
     787
     788
     789\subsection{Tuple Assignment}
     790
    814791An assignment where the left side is a tuple type is called \newterm{tuple assignment}.
    815 There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a tuple type or a nontuple type, called \newterm{multiple} and \newterm{mass assignment}, respectively.
     792There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a tuple type or a non-tuple type, called \newterm{multiple} and \newterm{mass assignment}, respectively.
    816793\begin{cfa}
    817794int x = 10;
     
    823800[y, x] = 3.14;                                                          $\C{// mass assignment}$
    824801\end{cfa}
    825 Both kinds of tuple assignment have parallel semantics, so that each value on the left and right sides is evaluated before any assignments occur.
     802Both kinds of tuple assignment have parallel semantics, so that each value on the left and right side is evaluated before any assignments occur.
    826803As a result, it is possible to swap the values in two variables without explicitly creating any temporary variables or calling a function, \eg, @[x, y] = [y, x]@.
    827804This semantics means mass assignment differs from C cascading assignment (\eg @a = b = c@) in that conversions are applied in each individual assignment, which prevents data loss from the chain of conversions that can happen during a cascading assignment.
    828 For example, @[y, x] = 3.14@ performs the assignments @y = 3.14@ and @x = 3.14@, yielding @y == 3.14@ and @x == 3@, whereas C cascading assignment @y = x = 3.14@ performs the assignments @x = 3.14@ and @y = x@, yielding @3@ in @y@ and @x@.
     805For example, @[y, x] = 3.14@ performs the assignments @y = 3.14@ and @x = 3.14@, yielding @y == 3.14@ and @x == 3@;
     806whereas, C cascading assignment @y = x = 3.14@ performs the assignments @x = 3.14@ and @y = x@, yielding @3@ in @y@ and @x@.
    829807Finally, tuple assignment is an expression where the result type is the type of the left-hand side of the assignment, just like all other assignment expressions in C.
    830 This example shows mass, multiple, and cascading assignment used in one expression.
     808This example shows mass, multiple, and cascading assignment used in one expression:
    831809\begin{cfa}
    832810[void] f( [int, int] );
     
    835813
    836814
    837 \subsection{Member access}
    838 
    839 It is also possible to access multiple members from a single expression using a \newterm{member access}.
    840 The result is a single tuple-valued expression whose type is the tuple of the types of the members.
     815\subsection{Member Access}
     816
     817It is also possible to access multiple members from a single expression using a \newterm{member-access}.
     818The result is a single tuple-valued expression whose type is the tuple of the types of the members, \eg:
    841819\begin{cfa}
    842820struct S { int x; double y; char * z; } s;
     
    852830[int, int, int] y = x.[2, 0, 2];                        $\C{// duplicate: [y.0, y.1, y.2] = [x.2, x.0.x.2]}$
    853831\end{cfa}
    854 It is also possible for a member access to contain other member accesses.
     832It is also possible for a member access to contain other member accesses, \eg:
    855833\begin{cfa}
    856834struct A { double i; int j; };
     
    919897
    920898Tuples also integrate with \CFA polymorphism as a kind of generic type.
    921 Due to the implicit flattening and structuring conversions involved in argument passing, @otype@ and @dtype@ parameters are restricted to matching only with nontuple types.
     899Due to the implicit flattening and structuring conversions involved in argument passing, @otype@ and @dtype@ parameters are restricted to matching only with non-tuple types, \eg:
    922900\begin{cfa}
    923901forall( otype T, dtype U ) void f( T x, U * y );
    924902f( [5, "hello"] );
    925903\end{cfa}
    926 Here, @[5, "hello"]@ is flattened, giving argument list @5, "hello"@, and @T@ binds to @int@ and @U@ binds to @const char@.
     904where @[5, "hello"]@ is flattened, giving argument list @5, "hello"@, and @T@ binds to @int@ and @U@ binds to @const char@.
    927905Tuples, however, may contain polymorphic components.
    928906For example, a plus operator can be written to sum two triples.
     
    942920g( 5, 10.21 );
    943921\end{cfa}
    944 \newpage
    945922Hence, function parameter and return lists are flattened for the purposes of type unification allowing the example to pass expression resolution.
    946923This relaxation is possible by extending the thunk scheme described by Bilson~\cite{Bilson03}.
     
    953930
    954931
    955 \subsection{Variadic tuples}
     932\subsection{Variadic Tuples}
    956933\label{sec:variadic-tuples}
    957934
    958 To define variadic functions, \CFA adds a new kind of type parameter, \ie @ttype@ (tuple type).
    959 Matching against a @ttype@ parameter consumes all the remaining argument components and packages them into a tuple, binding to the resulting tuple of types.
    960 In a given parameter list, there must be, at most, one @ttype@ parameter that occurs last, which matches normal variadic semantics, with a strong feeling of similarity to \CCeleven variadic templates.
     935To define variadic functions, \CFA adds a new kind of type parameter, @ttype@ (tuple type).
     936Matching against a @ttype@ parameter consumes all remaining argument components and packages them into a tuple, binding to the resulting tuple of types.
     937In a given parameter list, there must be at most one @ttype@ parameter that occurs last, which matches normal variadic semantics, with a strong feeling of similarity to \CCeleven variadic templates.
    961938As such, @ttype@ variables are also called \newterm{argument packs}.
    962939
     
    964941Since nothing is known about a parameter pack by default, assertion parameters are key to doing anything meaningful.
    965942Unlike variadic templates, @ttype@ polymorphic functions can be separately compiled.
    966 For example, the following is a generalized @sum@ function.
     943For example, a generalized @sum@ function:
    967944\begin{cfa}
    968945int sum$\(_0\)$() { return 0; }
     
    973950\end{cfa}
    974951Since @sum@\(_0\) does not accept any arguments, it is not a valid candidate function for the call @sum(10, 20, 30)@.
    975 In order to call @sum@\(_1\), @10@ is matched with @x@, and the argument resolution moves on to the argument pack @rest@, which consumes the remainder of the argument list, and @Params@ is bound to @[20, 30]@.
     952In order to call @sum@\(_1\), @10@ is matched with @x@, and the argument resolution moves on to the argument pack @rest@, which consumes the remainder of the argument list and @Params@ is bound to @[20, 30]@.
    976953The process continues until @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.
    977954Effectively, this algorithm traces as @sum(10, 20, 30)@ $\rightarrow$ @10 + sum(20, 30)@ $\rightarrow$ @10 + (20 + sum(30))@ $\rightarrow$ @10 + (20 + (30 + sum()))@ $\rightarrow$ @10 + (20 + (30 + 0))@.
    978955
    979 It is reasonable to take the @sum@ function a step further to enforce a minimum number of arguments.
     956It is reasonable to take the @sum@ function a step further to enforce a minimum number of arguments:
    980957\begin{cfa}
    981958int sum( int x, int y ) { return x + y; }
     
    984961}
    985962\end{cfa}
    986 One more step permits the summation of any sumable type with all arguments of the same type.
     963One more step permits the summation of any sumable type with all arguments of the same type:
    987964\begin{cfa}
    988965trait sumable( otype T ) {
     
    1013990This example showcases a variadic-template-like decomposition of the provided argument list.
    1014991The individual @print@ functions allow printing a single element of a type.
    1015 The polymorphic @print@ allows printing any list of types, where each individual type has a @print@ function.
     992The polymorphic @print@ allows printing any list of types, where as each individual type has a @print@ function.
    1016993The individual print functions can be used to build up more complicated @print@ functions, such as @S@, which cannot be done with @printf@ in C.
    1017994This mechanism is used to seamlessly print tuples in the \CFA I/O library (see Section~\ref{s:IOLibrary}).
    1018995
    1019996Finally, it is possible to use @ttype@ polymorphism to provide arbitrary argument forwarding functions.
    1020 For example, it is possible to write @new@ as a library function.
     997For example, it is possible to write @new@ as a library function:
    1021998\begin{cfa}
    1022999forall( otype R, otype S ) void ?{}( pair(R, S) *, R, S );
     
    10271004\end{cfa}
    10281005The @new@ function provides the combination of type-safe @malloc@ with a \CFA constructor call, making it impossible to forget constructing dynamically allocated objects.
    1029 This function provides the type safety of @new@ in \CC, without the need to specify the allocated type again, due to return-type inference.
     1006This function provides the type-safety of @new@ in \CC, without the need to specify the allocated type again, thanks to return-type inference.
    10301007
    10311008
     
    10331010
    10341011Tuples are implemented in the \CFA translator via a transformation into \newterm{generic types}.
    1035 For each $N$, the first time an $N$-tuple is seen in a scope, a generic type with $N$ type parameters is generated.
    1036 For example, the following
     1012For each $N$, the first time an $N$-tuple is seen in a scope a generic type with $N$ type parameters is generated, \eg:
    10371013\begin{cfa}
    10381014[int, int] f() {
     
    10411017}
    10421018\end{cfa}
    1043 is transformed into
     1019is transformed into:
    10441020\begin{cfa}
    10451021forall( dtype T0, dtype T1 | sized(T0) | sized(T1) ) struct _tuple2 {
     
    11071083
    11081084The various kinds of tuple assignment, constructors, and destructors generate GNU C statement expressions.
    1109 A variable is generated to store the value produced by a statement expression, since its members may need to be constructed with a nontrivial constructor and it may need to be referred to multiple time, \eg in a unique expression.
     1085A variable is generated to store the value produced by a statement expression, since its members may need to be constructed with a non-trivial constructor and it may need to be referred to multiple time, \eg in a unique expression.
    11101086The use of statement expressions allows the translator to arbitrarily generate additional temporary variables as needed, but binds the implementation to a non-standard extension of the C language.
    11111087However, there are other places where the \CFA translator makes use of GNU C extensions, such as its use of nested functions, so this restriction is not new.
     
    11151091\section{Control Structures}
    11161092
    1117 \CFA identifies inconsistent, problematic, and missing control structures in C, as well as extends, modifies, and adds control structures to increase functionality and safety.
    1118 
    1119 
    1120 \subsection{\texorpdfstring{\protect\lstinline@if@ statement}{if statement}}
    1121 
    1122 The @if@ expression allows declarations, similar to the @for@ declaration expression.
     1093\CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds control structures to increase functionality and safety.
     1094
     1095
     1096\subsection{\texorpdfstring{\protect\lstinline{if} Statement}{if Statement}}
     1097
     1098The @if@ expression allows declarations, similar to @for@ declaration expression:
    11231099\begin{cfa}
    11241100if ( int x = f() ) ...                                          $\C{// x != 0}$
     
    11271103\end{cfa}
    11281104Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the @if@ expression, and the results are combined using the logical @&&@ operator.\footnote{\CC only provides a single declaration always compared not equal to 0.}
    1129 The scope of the declaration(s) is local to the @if@ statement but exists within both the ``then'' and ``else'' clauses.
    1130 
    1131 
    1132 \subsection{\texorpdfstring{\protect\lstinline@switch@ statement}{switch statement}}
     1105The scope of the declaration(s) is local to the @if@ statement but exist within both the ``then'' and ``else'' clauses.
     1106
     1107
     1108\subsection{\texorpdfstring{\protect\lstinline{switch} Statement}{switch Statement}}
    11331109
    11341110There are a number of deficiencies with the C @switch@ statements: enumerating @case@ lists, placement of @case@ clauses, scope of the switch body, and fall through between case clauses.
    11351111
    1136 C has no shorthand for specifying a list of case values, whether the list is noncontiguous or contiguous\footnote{C provides this mechanism via fall through.}.
    1137 \CFA provides a shorthand for a noncontiguous list:
     1112C has no shorthand for specifying a list of case values, whether the list is non-contiguous or contiguous\footnote{C provides this mechanism via fall through.}.
     1113\CFA provides a shorthand for a non-contiguous list:
    11381114\begin{cquote}
    11391115\lstDeleteShortInline@%
     
    11501126\lstMakeShortInline@%
    11511127\end{cquote}
    1152 for a contiguous list:\footnote{gcc has the same mechanism but awkward syntax, \lstinline@2 ...42@, as a space is required after a number;
    1153 otherwise, the first period is a decimal point.}
     1128for a contiguous list:\footnote{gcc has the same mechanism but awkward syntax, \lstinline@2 ...42@, as a space is required after a number, otherwise the first period is a decimal point.}
    11541129\begin{cquote}
    11551130\lstDeleteShortInline@%
     
    11821157}
    11831158\end{cfa}
    1184 \CFA precludes this form of transfer \emph{into} a control structure because it causes an undefined behavior, especially with respect to missed initialization, and provides very limited functionality.
    1185 
    1186 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in an undefined behavior.
     1159\CFA precludes this form of transfer \emph{into} a control structure because it causes undefined behaviour, especially with respect to missed initialization, and provides very limited functionality.
     1160
     1161C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour:
    11871162\begin{cfa}
    11881163switch ( x ) {
     
    12011176
    12021177C @switch@ provides multiple entry points into the statement body, but once an entry point is selected, control continues across \emph{all} @case@ clauses until the end of the @switch@ body, called \newterm{fall through};
    1203 @case@ clauses are made disjoint by the @break@
    1204 \newpage
    1205 \noindent
    1206 statement.
     1178@case@ clauses are made disjoint by the @break@ statement.
    12071179While fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in errors from missing @break@ statements.
    1208 For backward compatibility, \CFA provides a \emph{new} control structure, \ie @choose@, which mimics @switch@, but reverses the meaning of fall through (see Figure~\ref{f:ChooseSwitchStatements}), similar to Go.
     1180For backwards compatibility, \CFA provides a \emph{new} control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through (see Figure~\ref{f:ChooseSwitchStatements}), similar to Go.
    12091181
    12101182\begin{figure}
    12111183\centering
    1212 \fontsize{9bp}{11bp}\selectfont
    12131184\lstDeleteShortInline@%
    12141185\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     
    12471218\end{tabular}
    12481219\lstMakeShortInline@%
    1249 \caption{\lstinline|choose| versus \lstinline|switch| statements}
     1220\caption{\lstinline|choose| versus \lstinline|switch| Statements}
    12501221\label{f:ChooseSwitchStatements}
    1251 \vspace*{-11pt}
    12521222\end{figure}
    12531223
    1254 Finally, Figure~\ref{f:FallthroughStatement} shows @fallthrough@ may appear in contexts other than terminating a @case@ clause and have an explicit transfer label allowing separate cases but common final code for a set of cases.
     1224Finally, Figure~\ref{f:FallthroughStatement} shows @fallthrough@ may appear in contexts other than terminating a @case@ clause, and have an explicit transfer label allowing separate cases but common final-code for a set of cases.
    12551225The target label must be below the @fallthrough@ and may not be nested in a control structure, \ie @fallthrough@ cannot form a loop, and the target label must be at the same or higher level as the containing @case@ clause and located at the same level as a @case@ clause;
    12561226the target label may be case @default@, but only associated with the current @switch@/@choose@ statement.
     
    12581228\begin{figure}
    12591229\centering
    1260 \fontsize{9bp}{11bp}\selectfont
    12611230\lstDeleteShortInline@%
    12621231\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     
    12871256\end{tabular}
    12881257\lstMakeShortInline@%
    1289 \caption{\lstinline|fallthrough| statement}
     1258\caption{\lstinline|fallthrough| Statement}
    12901259\label{f:FallthroughStatement}
    1291 \vspace*{-11pt}
    12921260\end{figure}
    12931261
    12941262
    1295 \vspace*{-8pt}
    1296 \subsection{\texorpdfstring{Labeled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labeled continue / break}}
     1263\subsection{\texorpdfstring{Labelled \protect\lstinline{continue} / \protect\lstinline{break}}{Labelled continue / break}}
    12971264
    12981265While C provides @continue@ and @break@ statements for altering control flow, both are restricted to one level of nesting for a particular control structure.
    1299 Unfortunately, this restriction forces programmers to use @goto@ to achieve the equivalent control flow for more than one level of nesting.
    1300 To prevent having to switch to the @goto@, \CFA extends @continue@ and @break@ with a target label to support static multilevel exit~\cite{Buhr85}, as in Java.
     1266Unfortunately, this restriction forces programmers to use @goto@ to achieve the equivalent control-flow for more than one level of nesting.
     1267To prevent having to switch to the @goto@, \CFA extends the @continue@ and @break@ with a target label to support static multi-level exit~\cite{Buhr85}, as in Java.
    13011268For both @continue@ and @break@, the target label must be directly associated with a @for@, @while@ or @do@ statement;
    13021269for @break@, the target label can also be associated with a @switch@, @if@ or compound (@{}@) statement.
    1303 Figure~\ref{f:MultiLevelExit} shows @continue@ and @break@ indicating the specific control structure and the corresponding C program using only @goto@ and labels.
    1304 The innermost loop has seven exit points, which cause a continuation or termination of one or more of the seven nested control structures.
     1270Figure~\ref{f:MultiLevelExit} shows @continue@ and @break@ indicating the specific control structure, and the corresponding C program using only @goto@ and labels.
     1271The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 nested control-structures.
    13051272
    13061273\begin{figure}
    1307 \fontsize{9bp}{11bp}\selectfont
    13081274\lstDeleteShortInline@%
    13091275\begin{tabular}{@{\hspace{\parindentlnth}}l|@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     
    13701336\end{tabular}
    13711337\lstMakeShortInline@%
    1372 \caption{Multilevel exit}
     1338\caption{Multi-level Exit}
    13731339\label{f:MultiLevelExit}
    1374 \vspace*{-5pt}
    13751340\end{figure}
    13761341
    1377 With respect to safety, both labeled @continue@ and @break@ are @goto@ restricted in the following ways.
    1378 \begin{list}{$\bullet$}{\topsep=4pt\itemsep=0pt\parsep=0pt}
     1342With respect to safety, both labelled @continue@ and @break@ are a @goto@ restricted in the following ways:
     1343\begin{itemize}
    13791344\item
    13801345They cannot create a loop, which means only the looping constructs cause looping.
     
    13821347\item
    13831348They cannot branch into a control structure.
    1384 This restriction prevents missing declarations and/or initializations at the start of a control structure resulting in an undefined behavior.
    1385 \end{list}
    1386 The advantage of the labeled @continue@/@break@ is allowing static multilevel exits without having to use the @goto@ statement and tying control flow to the target control structure rather than an arbitrary point in a program.
    1387 Furthermore, the location of the label at the \emph{beginning} of the target control structure informs the reader (eye candy) that complex control flow is
    1388 occurring in the body of the control structure.
     1349This restriction prevents missing declarations and/or initializations at the start of a control structure resulting in undefined behaviour.
     1350\end{itemize}
     1351The advantage of the labelled @continue@/@break@ is allowing static multi-level exits without having to use the @goto@ statement, and tying control flow to the target control structure rather than an arbitrary point in a program.
     1352Furthermore, the location of the label at the \emph{beginning} of the target control structure informs the reader (eye candy) that complex control-flow is occurring in the body of the control structure.
    13891353With @goto@, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader.
    1390 Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting the existing constructs.
     1354Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs.
    13911355Otherwise, the implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed.
    13921356
    13931357
    1394 \vspace*{-5pt}
    1395 \subsection{Exception handling}
    1396 
    1397 The following framework for \CFA exception handling is in place, excluding some runtime type information and virtual functions.
     1358\subsection{Exception Handling}
     1359
     1360The following framework for \CFA exception-handling is in place, excluding some runtime type-information and virtual functions.
    13981361\CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling})~\cite{Buhr92b,Buhr00a}.
    1399 Both mechanisms provide dynamic call to a handler using dynamic name lookup, where fix-up has dynamic return and recovery has static return from the handler.
     1362Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler.
    14001363\CFA restricts exception types to those defined by aggregate type @exception@.
    14011364The form of the raise dictates the set of handlers examined during propagation: \newterm{resumption propagation} (@resume@) only examines resumption handlers (@catchResume@); \newterm{terminating propagation} (@throw@) only examines termination handlers (@catch@).
    1402 If @resume@ or @throw@ has no exception type, it is a reresume/rethrow, which means that the current exception continues propagation.
     1365If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation.
    14031366If there is no current exception, the reresume/rethrow results in a runtime error.
    14041367
    14051368\begin{figure}
    1406 \fontsize{9bp}{11bp}\selectfont
    1407 \lstDeleteShortInline@%
    14081369\begin{cquote}
     1370\lstDeleteShortInline@%
    14091371\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
    14101372\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{Resumption}}   & \multicolumn{1}{c@{}}{\textbf{Termination}}   \\
     
    14371399\end{cfa}
    14381400\end{tabular}
     1401\lstMakeShortInline@%
    14391402\end{cquote}
    1440 \lstMakeShortInline@%
    1441 \caption{\CFA exception handling}
     1403\caption{\CFA Exception Handling}
    14421404\label{f:CFAExceptionHandling}
    1443 \vspace*{-5pt}
    14441405\end{figure}
    14451406
    1446 The set of exception types in a list of catch clauses may include both a resumption and a termination handler.
     1407The set of exception types in a list of catch clause may include both a resumption and termination handler:
    14471408\begin{cfa}
    14481409try {
     
    14581419The termination handler is available because the resumption propagation did not unwind the stack.
    14591420
    1460 An additional feature is conditional matching in a catch clause.
     1421An additional feature is conditional matching in a catch clause:
    14611422\begin{cfa}
    14621423try {
     
    14671428   catch ( IOError err ) { ... }                        $\C{// handler error from other files}$
    14681429\end{cfa}
    1469 Here, the throw inserts the failing file handle into the I/O exception.
    1470 Conditional catch cannot be trivially mimicked by other mechanisms because once an exception is caught, handler clauses in that @try@ statement are no longer eligible.
    1471 
    1472 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}.
     1430where the throw inserts the failing file-handle into the I/O exception.
     1431Conditional catch cannot be trivially mimicked by other mechanisms because once an exception is caught, handler clauses in that @try@ statement are no longer eligible..
     1432
     1433The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}:
    14731434\begin{cfa}
    14741435resume( $\emph{exception-type}$, $\emph{alternate-stack}$ )
     
    14781439Nonlocal raise is restricted to resumption to provide the exception handler the greatest flexibility because processing the exception does not unwind its stack, allowing it to continue after the handler returns.
    14791440
    1480 To facilitate nonlocal raise, \CFA provides dynamic enabling and disabling of nonlocal exception propagation.
    1481 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and @disable@ blocks.
     1441To facilitate nonlocal raise, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation.
     1442The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks:
    14821443\begin{cquote}
    14831444\lstDeleteShortInline@%
     
    14851446\begin{cfa}
    14861447enable $\emph{exception-type-list}$ {
    1487         // allow nonlocal raise
     1448        // allow non-local raise
    14881449}
    14891450\end{cfa}
     
    14911452\begin{cfa}
    14921453disable $\emph{exception-type-list}$ {
    1493         // disallow nonlocal raise
     1454        // disallow non-local raise
    14941455}
    14951456\end{cfa}
     
    14991460The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively.
    15001461Specifying no exception type is shorthand for specifying all exception types.
    1501 Both @enable@ and @disable@ blocks can be nested;
    1502 turning propagation on/off on entry and on exit, the specified exception types are restored to their prior state.
    1503 Coroutines and tasks start with nonlocal exceptions disabled, allowing handlers to be put in place, before nonlocal exceptions are explicitly enabled.
     1462Both @enable@ and @disable@ blocks can be nested, turning propagation on/off on entry, and on exit, the specified exception types are restored to their prior state.
     1463Coroutines and tasks start with non-local exceptions disabled, allowing handlers to be put in place, before non-local exceptions are explicitly enabled.
    15041464\begin{cfa}
    15051465void main( mytask & t ) {                                       $\C{// thread starts here}$
    1506         // nonlocal exceptions disabled
    1507         try {                                                                   $\C{// establish handles for nonlocal exceptions}$
    1508                 enable {                                                        $\C{// allow nonlocal exception delivery}$
     1466        // non-local exceptions disabled
     1467        try {                                                                   $\C{// establish handles for non-local exceptions}$
     1468                enable {                                                        $\C{// allow non-local exception delivery}$
    15091469                        // task body
    15101470                }
     
    15141474\end{cfa}
    15151475
    1516 Finally, \CFA provides a Java-like  @finally@ clause after the catch clauses.
     1476Finally, \CFA provides a Java like  @finally@ clause after the catch clauses:
    15171477\begin{cfa}
    15181478try {
     
    15231483}
    15241484\end{cfa}
    1525 The finally clause is always executed, \ie, if the try block ends normally or if an exception is raised.
     1485The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised.
    15261486If an exception is raised and caught, the handler is run before the finally clause.
    15271487Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.
    1528 Mimicking the @finally@ clause with mechanisms like Resource Aquisition Is Initialization (RAII) is nontrivial when there are multiple types and local accesses.
    1529 
    1530 
    1531 \subsection{\texorpdfstring{\protect\lstinline{with} statement}{with statement}}
     1488Mimicking the @finally@ clause with mechanisms like RAII is non-trivial when there are multiple types and local accesses.
     1489
     1490
     1491\subsection{\texorpdfstring{\protect\lstinline{with} Statement}{with Statement}}
    15321492\label{s:WithStatement}
    15331493
    1534 Heterogeneous data are often aggregated into a structure/union.
    1535 To reduce syntactic noise, \CFA provides a @with@ statement (see section~4.F in the Pascal User Manual and Report~\cite{Pascal}) to elide aggregate member qualification by opening a scope containing the member identifiers.
     1494Heterogeneous data is often aggregated into a structure/union.
     1495To reduce syntactic noise, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate member-qualification by opening a scope containing the member identifiers.
    15361496\begin{cquote}
    15371497\vspace*{-\baselineskip}%???
     
    15611521Object-oriented programming languages only provide implicit qualification for the receiver.
    15621522
    1563 In detail, the @with@ statement has the form
     1523In detail, the @with@ statement has the form:
    15641524\begin{cfa}
    15651525$\emph{with-statement}$:
     
    15671527\end{cfa}
    15681528and may appear as the body of a function or nested within a function body.
    1569 Each expression in the expression list provides a type and object.
     1529Each expression in the expression-list provides a type and object.
    15701530The type must be an aggregate type.
    15711531(Enumerations are already opened.)
    1572 The object is the implicit qualifier for the open structure members.
     1532The object is the implicit qualifier for the open structure-members.
    15731533
    15741534All expressions in the expression list are open in parallel within the compound statement, which is different from Pascal, which nests the openings from left to right.
    1575 The difference between parallel and nesting occurs for members with the same name and type.
     1535The difference between parallel and nesting occurs for members with the same name and type:
    15761536\begin{cfa}
    15771537struct S { int `i`; int j; double m; } s, w;    $\C{// member i has same type in structure types S and T}$
     
    15871547}
    15881548\end{cfa}
    1589 For parallel semantics, both @s.i@ and @t.i@ are visible and, therefore, @i@ is ambiguous without qualification;
    1590 for nested semantics, @t.i@ hides @s.i@ and, therefore, @i@ implies @t.i@.
     1549For parallel semantics, both @s.i@ and @t.i@ are visible, so @i@ is ambiguous without qualification;
     1550for nested semantics, @t.i@ hides @s.i@, so @i@ implies @t.i@.
    15911551\CFA's ability to overload variables means members with the same name but different types are automatically disambiguated, eliminating most qualification when opening multiple aggregates.
    15921552Qualification or a cast is used to disambiguate.
    15931553
    1594 There is an interesting problem between parameters and the function body @with@.
     1554There is an interesting problem between parameters and the function-body @with@, \eg:
    15951555\begin{cfa}
    15961556void ?{}( S & s, int i ) with ( s ) {           $\C{// constructor}$
     
    15981558}
    15991559\end{cfa}
    1600 Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function body @with@.
    1601 To solve this problem, parameters are treated like an initialized aggregate
     1560Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function-body @with@.
     1561To solve this problem, parameters are treated like an initialized aggregate:
    16021562\begin{cfa}
    16031563struct Params {
     
    16061566} params;
    16071567\end{cfa}
    1608 \newpage
    1609 and implicitly opened \emph{after} a function body open, to give them higher priority
     1568and implicitly opened \emph{after} a function-body open, to give them higher priority:
    16101569\begin{cfa}
    16111570void ?{}( S & s, int `i` ) with ( s ) `{` `with( $\emph{\color{red}params}$ )` {
     
    16131572} `}`
    16141573\end{cfa}
    1615 Finally, a cast may be used to disambiguate among overload variables in a @with@ expression
     1574Finally, a cast may be used to disambiguate among overload variables in a @with@ expression:
    16161575\begin{cfa}
    16171576with ( w ) { ... }                                                      $\C{// ambiguous, same name and no context}$
    16181577with ( (S)w ) { ... }                                           $\C{// unambiguous, cast}$
    16191578\end{cfa}
    1620 and @with@ expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate
     1579and @with@ expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate:
    16211580\begin{cfa}
    16221581struct S { int i, j; } sv;
     
    16421601\CFA attempts to correct and add to C declarations, while ensuring \CFA subjectively ``feels like'' C.
    16431602An important part of this subjective feel is maintaining C's syntax and procedural paradigm, as opposed to functional and object-oriented approaches in other systems languages such as \CC and Rust.
    1644 Maintaining the C approach means that C coding patterns remain not only useable but idiomatic in \CFA, reducing the mental burden of retraining C programmers and switching between C and \CFA development.
     1603Maintaining the C approach means that C coding-patterns remain not only useable but idiomatic in \CFA, reducing the mental burden of retraining C programmers and switching between C and \CFA development.
    16451604Nevertheless, some features from other approaches are undeniably convenient;
    16461605\CFA attempts to adapt these features to the C paradigm.
    16471606
    16481607
    1649 \subsection{Alternative declaration syntax}
     1608\subsection{Alternative Declaration Syntax}
    16501609
    16511610C declaration syntax is notoriously confusing and error prone.
    1652 For example, many C programmers are confused by a declaration as simple as the following.
     1611For example, many C programmers are confused by a declaration as simple as:
    16531612\begin{cquote}
    16541613\lstDeleteShortInline@%
     
    16621621\lstMakeShortInline@%
    16631622\end{cquote}
    1664 Is this an array of five pointers to integers or a pointer to an array of five integers?
     1623Is this an array of 5 pointers to integers or a pointer to an array of 5 integers?
    16651624If there is any doubt, it implies productivity and safety issues even for basic programs.
    16661625Another example of confusion results from the fact that a function name and its parameters are embedded within the return type, mimicking the way the return value is used at the function's call site.
    1667 For example, a function returning a pointer to an array of integers is defined and used in the following way.
     1626For example, a function returning a pointer to an array of integers is defined and used in the following way:
    16681627\begin{cfa}
    16691628int `(*`f`())[`5`]` {...};                                      $\C{// definition}$
     
    16731632While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
    16741633
    1675 \newpage
    1676 \CFA provides its own type, variable, and function declarations, using a different syntax~\cite[pp.~856--859]{Buhr94a}.
    1677 The new declarations place qualifiers to the left of the base type, whereas C declarations place qualifiers to the right.
     1634\CFA provides its own type, variable and function declarations, using a different syntax~\cite[pp.~856--859]{Buhr94a}.
     1635The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right.
    16781636The qualifiers have the same meaning but are ordered left to right to specify a variable's type.
    16791637\begin{cquote}
     
    17011659\lstMakeShortInline@%
    17021660\end{cquote}
    1703 The only exception is bit-field specification, which always appears to the right of the base type.
     1661The only exception is bit-field specification, which always appear to the right of the base type.
    17041662% Specifically, the character @*@ is used to indicate a pointer, square brackets @[@\,@]@ are used to represent an array or function return value, and parentheses @()@ are used to indicate a function parameter.
    17051663However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    1706 For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as
     1664For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as follows:
    17071665\begin{cquote}
    17081666\lstDeleteShortInline@%
     
    17671725\end{comment}
    17681726
    1769 All specifiers (@extern@, @static@, \etc) and qualifiers (@const@, @volatile@, \etc) are used in the normal way with the new declarations and also appear left to right.
     1727All specifiers (@extern@, @static@, \etc) and qualifiers (@const@, @volatile@, \etc) are used in the normal way with the new declarations and also appear left to right, \eg:
    17701728\begin{cquote}
    17711729\lstDeleteShortInline@%
    17721730\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    17731731\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
    1774 \begin{cfa}[basicstyle=\linespread{0.9}\fontsize{9bp}{12bp}\selectfont\sf]
     1732\begin{cfa}
    17751733extern const * const int x;
    17761734static const * [5] const int y;
    17771735\end{cfa}
    17781736&
    1779 \begin{cfa}[basicstyle=\linespread{0.9}\fontsize{9bp}{12bp}\selectfont\sf]
     1737\begin{cfa}
    17801738int extern const * const x;
    17811739static const int (* const y)[5]
    17821740\end{cfa}
    17831741&
    1784 \begin{cfa}[basicstyle=\linespread{0.9}\fontsize{9bp}{12bp}\selectfont\sf]
     1742\begin{cfa}
    17851743// external const pointer to const int
    17861744// internal const pointer to array of 5 const int
     
    17901748\end{cquote}
    17911749Specifiers must appear at the start of a \CFA function declaration\footnote{\label{StorageClassSpecifier}
    1792 The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature (see section~6.11.5(1) in ISO/IEC 9899~\cite{C11}).}.
     1750The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}}.
    17931751
    17941752The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-function @sizeof@:
     
    18111769
    18121770The syntax of the new function-prototype declaration follows directly from the new function-definition syntax;
    1813 also, parameter names are optional.
     1771as well, parameter names are optional, \eg:
    18141772\begin{cfa}
    18151773[ int x ] f ( /* void */ );             $\C[2.5in]{// returning int with no parameters}$
     
    18191777[ * int, int ] j ( int );               $\C{// returning pointer to int and int with int parameter}$
    18201778\end{cfa}
    1821 This syntax allows a prototype declaration to be created by cutting and pasting the source text from the function-definition header (or vice versa).
    1822 Like C, it is possible to declare multiple function prototypes in a single declaration, where the return type is distributed across \emph{all} function names in the declaration list.
     1779This syntax allows a prototype declaration to be created by cutting and pasting source text from the function-definition header (or vice versa).
     1780Like C, it is possible to declare multiple function-prototypes in a single declaration, where the return type is distributed across \emph{all} function names in the declaration list, \eg:
    18231781\begin{cquote}
    18241782\lstDeleteShortInline@%
     
    18351793\lstMakeShortInline@%
    18361794\end{cquote}
    1837 Here, \CFA allows the last function in the list to define its body.
    1838 
    1839 The syntax for pointers to \CFA functions specifies the pointer name on the right.
     1795where \CFA allows the last function in the list to define its body.
     1796
     1797The syntax for pointers to \CFA functions specifies the pointer name on the right, \eg:
    18401798\begin{cfa}
    18411799* [ int x ] () fp;                              $\C{// pointer to function returning int with no parameters}$
     
    18441802* [ * int, int ] ( int ) jp;    $\C{// pointer to function returning pointer to int and int with int parameter}\CRT$
    18451803\end{cfa}
    1846 \newpage
    1847 \noindent
    1848 Note that the name of the function pointer is specified last, as for other variable declarations.
    1849 
    1850 Finally, new \CFA declarations may appear together with C declarations in the same program block but cannot be mixed within a specific declaration.
    1851 Therefore, a programmer has the option of either continuing to use traditional C declarations or taking advantage of the new style.
    1852 Clearly, both styles need to be supported for some time due to existing C-style header files, particularly for UNIX-like systems.
     1804Note, the name of the function pointer is specified last, as for other variable declarations.
     1805
     1806Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
     1807Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
     1808Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems.
    18531809
    18541810
     
    18581814All variables in C have an \newterm{address}, a \newterm{value}, and a \newterm{type};
    18591815at the position in the program's memory denoted by the address, there exists a sequence of bits (the value), with the length and semantic meaning of this bit sequence defined by the type.
    1860 The C type system does not always track the relationship between a value and its address;
    1861 a value that does not have a corresponding address is called an \newterm{rvalue} (for ``right-hand value''), whereas a value that does have an address is called an \newterm{lvalue} (for ``left-hand value'').
    1862 For example, in @int x; x = 42;@ the variable expression @x@ on the left-hand side of the assignment is an lvalue, whereas the constant expression @42@ on the right-hand side of the assignment is an rvalue.
    1863 Despite the nomenclature of ``left-hand'' and ``right-hand'', an expression's classification as an lvalue or an rvalue is entirely dependent on whether it has an address or not; in imperative programming, the address of a value is used for both reading and writing (mutating) a value, and as such, lvalues can be converted into rvalues and read from, but rvalues cannot be mutated because they lack a location to store the updated value.
     1816The C type-system does not always track the relationship between a value and its address;
     1817a value that does not have a corresponding address is called a \newterm{rvalue} (for ``right-hand value''), while a value that does have an address is called a \newterm{lvalue} (for ``left-hand value'').
     1818For example, in @int x; x = 42;@ the variable expression @x@ on the left-hand-side of the assignment is a lvalue, while the constant expression @42@ on the right-hand-side of the assignment is a rvalue.
     1819Despite the nomenclature of ``left-hand'' and ``right-hand'', an expression's classification as lvalue or rvalue is entirely dependent on whether it has an address or not; in imperative programming, the address of a value is used for both reading and writing (mutating) a value, and as such, lvalues can be converted to rvalues and read from, but rvalues cannot be mutated because they lack a location to store the updated value.
    18641820
    18651821Within a lexical scope, lvalue expressions have an \newterm{address interpretation} for writing a value or a \newterm{value interpretation} to read a value.
    1866 For example, in @x = y@, @x@ has an address interpretation, whereas @y@ has a value interpretation.
     1822For example, in @x = y@, @x@ has an address interpretation, while @y@ has a value interpretation.
    18671823While this duality of interpretation is useful, C lacks a direct mechanism to pass lvalues between contexts, instead relying on \newterm{pointer types} to serve a similar purpose.
    18681824In C, for any type @T@ there is a pointer type @T *@, the value of which is the address of a value of type @T@.
    1869 A pointer rvalue can be explicitly \newterm{dereferenced} to the pointed-to lvalue with the dereference operator @*?@, whereas the rvalue representing the address of an lvalue can be obtained with the address-of operator @&?@.
     1825A pointer rvalue can be explicitly \newterm{dereferenced} to the pointed-to lvalue with the dereference operator @*?@, while the rvalue representing the address of a lvalue can be obtained with the address-of operator @&?@.
     1826
    18701827\begin{cfa}
    18711828int x = 1, y = 2, * p1, * p2, ** p3;
     
    18751832*p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15);
    18761833\end{cfa}
     1834
    18771835Unfortunately, the dereference and address-of operators introduce a great deal of syntactic noise when dealing with pointed-to values rather than pointers, as well as the potential for subtle bugs because of pointer arithmetic.
    18781836For both brevity and clarity, it is desirable for the compiler to figure out how to elide the dereference operators in a complex expression such as the assignment to @*p2@ above.
    1879 However, since C defines a number of forms of \newterm{pointer arithmetic}, two similar expressions involving pointers to arithmetic types (\eg @*p1 + x@ and @p1 + x@) may each have well-defined but distinct semantics, introducing the possibility that a programmer may write one when they mean the other and precluding any simple algorithm for elision of dereference operators.
     1837However, since C defines a number of forms of \newterm{pointer arithmetic}, two similar expressions involving pointers to arithmetic types (\eg @*p1 + x@ and @p1 + x@) may each have well-defined but distinct semantics, introducing the possibility that a programmer may write one when they mean the other, and precluding any simple algorithm for elision of dereference operators.
    18801838To solve these problems, \CFA introduces reference types @T &@;
    1881 a @T &@ has exactly the same value as a @T *@, but where the @T *@ takes the address interpretation by default, a @T &@ takes the value interpretation by default, as below.
     1839a @T &@ has exactly the same value as a @T *@, but where the @T *@ takes the address interpretation by default, a @T &@ takes the value interpretation by default, as below:
     1840
    18821841\begin{cfa}
    18831842int x = 1, y = 2, & r1, & r2, && r3;
     
    18871846r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15);       $\C{// implicit dereferencing}$
    18881847\end{cfa}
     1848
    18891849Except for auto-dereferencing by the compiler, this reference example is exactly the same as the previous pointer example.
    1890 Hence, a reference behaves like a variable name---an lvalue expression that is interpreted as a value---but also has the type system track the address of that value.
    1891 One way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator before the reference variable for each reference qualifier in the reference variable declaration;
    1892 thus, the previous example implicitly acts like the following.
     1850Hence, a reference behaves like a variable name -- an lvalue expression which is interpreted as a value -- but also has the type system track the address of that value.
     1851One way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator before the reference variable for each reference qualifier in the reference variable declaration, so the previous example implicitly acts like:
     1852
    18931853\begin{cfa}
    18941854`*`r2 = ((`*`r1 + `*`r2) * (`**`r3 - `*`r1)) / (`**`r3 - 15);
    18951855\end{cfa}
     1856
    18961857References in \CFA are similar to those in \CC, with important improvements, which can be seen in the example above.
    18971858Firstly, \CFA does not forbid references to references.
    1898 This provides a much more orthogonal design for library \mbox{implementors}, obviating the need for workarounds such as @std::reference_wrapper@.
     1859This provides a much more orthogonal design for library implementors, obviating the need for workarounds such as @std::reference_wrapper@.
    18991860Secondly, \CFA references are rebindable, whereas \CC references have a fixed address.
    1900 Rebinding allows \CFA references to be default initialized (\eg to a null pointer\footnote{
    1901 While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any nonmanaged languages (C/\CC), given that it only handles one of many different error situations, \eg using a pointer after its storage is deleted.}) and point to different addresses throughout their lifetime, like pointers.
     1861Rebinding allows \CFA references to be default-initialized (\eg to a null pointer\footnote{
     1862While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any non-managed languages (C/\CC), given that it only handles one of many different error situations, \eg using a pointer after its storage is deleted.}) and point to different addresses throughout their lifetime, like pointers.
    19021863Rebinding is accomplished by extending the existing syntax and semantics of the address-of operator in C.
    19031864
    1904 In C, the address of an lvalue is always an rvalue, as, in general, that address is not stored anywhere in memory and does not itself have an address.
    1905 In \CFA, the address of a @T &@ is an lvalue @T *@, as the address of the underlying @T@ is stored in the reference and can thus be mutated there.
     1865In C, the address of a lvalue is always a rvalue, as in general that address is not stored anywhere in memory, and does not itself have an address.
     1866In \CFA, the address of a @T &@ is a lvalue @T *@, as the address of the underlying @T@ is stored in the reference, and can thus be mutated there.
    19061867The result of this rule is that any reference can be rebound using the existing pointer assignment semantics by assigning a compatible pointer into the address of the reference, \eg @&r1 = &x;@ above.
    19071868This rebinding occurs to an arbitrary depth of reference nesting;
    19081869loosely speaking, nested address-of operators produce a nested lvalue pointer up to the depth of the reference.
    19091870These explicit address-of operators can be thought of as ``cancelling out'' the implicit dereference operators, \eg @(&`*`)r1 = &x@ or @(&(&`*`)`*`)r3 = &(&`*`)r1@ or even @(&`*`)r2 = (&`*`)`*`r3@ for @&r2 = &r3@.
    1910 The precise rules are
     1871More precisely:
    19111872\begin{itemize}
    19121873\item
    1913 If @R@ is an rvalue of type @T &@$_1\cdots$ @&@$_r$, where $r \ge 1$ references (@&@ symbols), than @&R@ has type @T `*`&@$_{\color{red}2}\cdots$ @&@$_{\color{red}r}$, \ie @T@ pointer with $r-1$ references (@&@ symbols).
     1874if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) then @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols).
     1875       
    19141876\item
    1915 If @L@ is an lvalue of type @T &@$_1\cdots$ @&@$_l$, where $l \ge 0$ references (@&@ symbols), than @&L@ has type @T `*`&@$_{\color{red}1}\cdots$ @&@$_{\color{red}l}$, \ie @T@ pointer with $l$ references (@&@ symbols).
     1877if @L@ is an lvalue of type {@T &@$_1 \cdots$@ &@$_l$} where $l \ge 0$ references (@&@ symbols) then @&L@ has type {@T `*`&@$_{\color{red}1} \cdots$@ &@$_{\color{red}l}$}, \\ \ie @T@ pointer with $l$ references (@&@ symbols).
    19161878\end{itemize}
    1917 Since pointers and references share the same internal representation, code using either is equally performant;
    1918 in fact, the \CFA compiler converts references into pointers internally, and the choice between them is made solely on convenience, \eg many pointer or value accesses.
     1879Since pointers and references share the same internal representation, code using either is equally performant; in fact the \CFA compiler converts references to pointers internally, and the choice between them is made solely on convenience, \eg many pointer or value accesses.
    19191880
    19201881By analogy to pointers, \CFA references also allow cv-qualifiers such as @const@:
     
    19311892There are three initialization contexts in \CFA: declaration initialization, argument/parameter binding, and return/temporary binding.
    19321893In each of these contexts, the address-of operator on the target lvalue is elided.
    1933 The syntactic motivation is clearest when considering overloaded operator assignment, \eg @int ?+=?(int &, int)@; given @int x, y@, the expected call syntax is @x += y@, not @&x += y@.
    1934 
    1935 More generally, this initialization of references from lvalues rather than pointers is an instance of an ``lvalue-to-reference'' conversion rather than an elision of the address-of operator;
     1894The syntactic motivation is clearest when considering overloaded operator-assignment, \eg @int ?+=?(int &, int)@; given @int x, y@, the expected call syntax is @x += y@, not @&x += y@.
     1895
     1896More generally, this initialization of references from lvalues rather than pointers is an instance of a ``lvalue-to-reference'' conversion rather than an elision of the address-of operator;
    19361897this conversion is used in any context in \CFA where an implicit conversion is allowed.
    1937 Similarly, use of the value pointed to by a reference in an rvalue context can be thought of as a ``reference-to-rvalue'' conversion, and \CFA also includes a qualifier-adding ``reference-to-reference'' conversion, analogous to the @T *@ to @const T *@ conversion in standard C.
    1938 The final reference conversion included in \CFA is an ``rvalue-to-reference'' conversion, implemented by means of an implicit temporary.
     1898Similarly, use of a the value pointed to by a reference in an rvalue context can be thought of as a ``reference-to-rvalue'' conversion, and \CFA also includes a qualifier-adding ``reference-to-reference'' conversion, analogous to the @T *@ to @const T *@ conversion in standard C.
     1899The final reference conversion included in \CFA is ``rvalue-to-reference'' conversion, implemented by means of an implicit temporary.
    19391900When an rvalue is used to initialize a reference, it is instead used to initialize a hidden temporary value with the same lexical scope as the reference, and the reference is initialized to the address of this temporary.
    19401901\begin{cfa}
     
    19441905f( 3, x + y, (S){ 1.0, 7.0 }, (int [3]){ 1, 2, 3 } ); $\C{// pass rvalue to lvalue \(\Rightarrow\) implicit temporary}$
    19451906\end{cfa}
    1946 This allows complex values to be succinctly and efficiently passed to functions, without the syntactic overhead of the explicit definition of a temporary variable or the runtime cost of pass-by-value.
    1947 \CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const poisoning} problem~\cite{Taylor10}, in which the addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.
    1948 
    1949 
    1950 \subsection{Type nesting}
    1951 
    1952 Nested types provide a mechanism to organize associated types and refactor a subset of members into a named aggregate (\eg subaggregates @name@, @address@, @department@, within aggregate @employe@).
    1953 Java nested types are dynamic (apply to objects), \CC are static (apply to the \lstinline[language=C++]@class@), and C hoists (refactors) nested types into the enclosing scope, which means there is no need for type qualification.
    1954 Since \CFA in not object oriented, adopting dynamic scoping does not make sense;
    1955 instead, \CFA adopts \CC static nesting, using the member-selection operator ``@.@'' for type qualification, as does Java, rather than the \CC type-selection operator ``@::@'' (see Figure~\ref{f:TypeNestingQualification}).
    1956 In the C left example, types @C@, @U@ and @T@ are implicitly hoisted outside of type @S@ into the containing block scope.
    1957 In the \CFA right example, the types are not hoisted and accessible.
    1958 
     1907This allows complex values to be succinctly and efficiently passed to functions, without the syntactic overhead of explicit definition of a temporary variable or the runtime cost of pass-by-value.
     1908\CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const poisoning} problem~\cite{Taylor10}, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.
     1909
     1910
     1911\subsection{Type Nesting}
     1912
     1913Nested types provide a mechanism to organize associated types and refactor a subset of members into a named aggregate (\eg sub-aggregates @name@, @address@, @department@, within aggregate @employe@).
     1914Java nested types are dynamic (apply to objects), \CC are static (apply to the \lstinline[language=C++]@class@), and C hoists (refactors) nested types into the enclosing scope, meaning there is no need for type qualification.
     1915Since \CFA in not object-oriented, adopting dynamic scoping does not make sense;
     1916instead \CFA adopts \CC static nesting, using the member-selection operator ``@.@'' for type qualification, as does Java, rather than the \CC type-selection operator ``@::@'' (see Figure~\ref{f:TypeNestingQualification}).
    19591917\begin{figure}
    19601918\centering
    1961 \fontsize{9bp}{11bp}\selectfont\sf
    19621919\lstDeleteShortInline@%
    19631920\begin{tabular}{@{}l@{\hspace{3em}}l|l@{}}
     
    20211978\end{tabular}
    20221979\lstMakeShortInline@%
    2023 \caption{Type nesting / qualification}
     1980\caption{Type Nesting / Qualification}
    20241981\label{f:TypeNestingQualification}
    2025 \vspace*{-8pt}
    20261982\end{figure}
    2027 
    2028 
    2029 \vspace*{-8pt}
    2030 \subsection{Constructors and destructors}
     1983In the C left example, types @C@, @U@ and @T@ are implicitly hoisted outside of type @S@ into the containing block scope.
     1984In the \CFA right example, the types are not hoisted and accessible.
     1985
     1986
     1987\subsection{Constructors and Destructors}
    20311988\label{s:ConstructorsDestructors}
    20321989
    2033 One of the strengths (and weaknesses) of C is memory-management control, allowing resource release to be precisely specified versus unknown release with garbage-collected memory management.
     1990One of the strengths (and weaknesses) of C is memory-management control, allowing resource release to be precisely specified versus unknown release with garbage-collected memory-management.
    20341991However, this manual approach is verbose, and it is useful to manage resources other than memory (\eg file handles) using the same mechanism as memory.
    2035 \CC addresses these issues using RAII, implemented by means of \newterm{constructor} and \newterm{destructor} functions;
     1992\CC addresses these issues using Resource Aquisition Is Initialization (RAII), implemented by means of \newterm{constructor} and \newterm{destructor} functions;
    20361993\CFA adopts constructors and destructors (and @finally@) to facilitate RAII.
    2037 While constructors and destructors are a common feature of object-oriented programming languages, they are an independent capability allowing \CFA to adopt them while retaining a procedural paradigm.
    2038 Specifically, \CFA constructors and destructors are denoted by name and first parameter type versus name and nesting in an aggregate type.
     1994While constructors and destructors are a common feature of object-oriented programming-languages, they are an independent capability allowing \CFA to adopt them while retaining a procedural paradigm.
     1995Specifically, \CFA constructors and destructors are denoted by name and first parameter-type versus name and nesting in an aggregate type.
    20391996Constructor calls seamlessly integrate with existing C initialization syntax, providing a simple and familiar syntax to C programmers and allowing constructor calls to be inserted into legacy C code with minimal code changes.
    20401997
     
    20452002The constructor and destructor have return type @void@, and the first parameter is a reference to the object type to be constructed or destructed.
    20462003While the first parameter is informally called the @this@ parameter, as in object-oriented languages, any variable name may be used.
    2047 Both constructors and destructors allow additional parameters after the @this@ parameter for specifying values for initialization/deinitialization\footnote{
    2048 Destruction parameters are useful for specifying storage-management actions, such as deinitialize but not deallocate.}.
    2049 \begin{cfa}[basicstyle=\linespread{0.9}\fontsize{9bp}{11bp}\selectfont\sf]
     2004Both constructors and destructors allow additional parameters after the @this@ parameter for specifying values for initialization/de-initialization\footnote{
     2005Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}.
     2006\begin{cfa}
    20502007struct VLA { int size, * data; };                       $\C{// variable length array of integers}$
    20512008void ?{}( VLA & vla ) with ( vla ) { size = 10;  data = alloc( size ); }  $\C{// default constructor}$
     
    20562013\end{cfa}
    20572014@VLA@ is a \newterm{managed type}\footnote{
    2058 A managed type affects the runtime environment versus a self-contained type.}: a type requiring a nontrivial constructor or destructor, or with a member of a managed type.
     2015A managed type affects the runtime environment versus a self-contained type.}: a type requiring a non-trivial constructor or destructor, or with a member of a managed type.
    20592016A managed type is implicitly constructed at allocation and destructed at deallocation to ensure proper interaction with runtime resources, in this case, the @data@ array in the heap.
    2060 For details of the code-generation placement of implicit constructor and destructor calls among complex executable statements, see section~2.2 in the work of Schlintz~\cite{Schluntz17}.
    2061 
    2062 \CFA also provides syntax for \newterm{initialization} and \newterm{copy}.
     2017For details of the code-generation placement of implicit constructor and destructor calls among complex executable statements see~\cite[\S~2.2]{Schluntz17}.
     2018
     2019\CFA also provides syntax for \newterm{initialization} and \newterm{copy}:
    20632020\begin{cfa}
    20642021void ?{}( VLA & vla, int size, char fill = '\0' ) {  $\C{// initialization}$
     
    20692026}
    20702027\end{cfa}
    2071 (Note that the example is purposely simplified using shallow-copy semantics.)
    2072 An initialization constructor call has the same syntax as a C initializer, except that the initialization values are passed as arguments to a matching constructor (number and type of parameters).
     2028(Note, the example is purposely simplified using shallow-copy semantics.)
     2029An initialization constructor-call has the same syntax as a C initializer, except the initialization values are passed as arguments to a matching constructor (number and type of paremeters).
    20732030\begin{cfa}
    20742031VLA va = `{` 20, 0 `}`,  * arr = alloc()`{` 5, 0 `}`;
    20752032\end{cfa}
    2076 Note the use of a \newterm{constructor expression} to initialize the storage from the dynamic storage allocation.
     2033Note, the use of a \newterm{constructor expression} to initialize the storage from the dynamic storage-allocation.
    20772034Like \CC, the copy constructor has two parameters, the second of which is a value parameter with the same type as the first parameter;
    20782035appropriate care is taken to not recursively call the copy constructor when initializing the second parameter.
     
    20802037\CFA constructors may be explicitly called, like Java, and destructors may be explicitly called, like \CC.
    20812038Explicit calls to constructors double as a \CC-style \emph{placement syntax}, useful for construction of members in user-defined constructors and reuse of existing storage allocations.
    2082 Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls.
     2039Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls:
    20832040\begin{cfa}
    20842041{
     
    20962053To provide a uniform type interface for @otype@ polymorphism, the \CFA compiler automatically generates a default constructor, copy constructor, assignment operator, and destructor for all types.
    20972054These default functions can be overridden by user-generated versions.
    2098 For compatibility with the standard behavior of C, the default constructor and destructor for all basic, pointer, and reference types do nothing, whereas the copy constructor and assignment operator are bitwise copies;
    2099 if default zero initialization is desired, the default constructors can be overridden.
     2055For compatibility with the standard behaviour of C, the default constructor and destructor for all basic, pointer, and reference types do nothing, while the copy constructor and assignment operator are bitwise copies;
     2056if default zero-initialization is desired, the default constructors can be overridden.
    21002057For user-generated types, the four functions are also automatically generated.
    21012058@enum@ types are handled the same as their underlying integral type, and unions are also bitwise copied and no-op initialized and destructed.
    21022059For compatibility with C, a copy constructor from the first union member type is also defined.
    2103 For @struct@ types, each of the four functions is implicitly defined to call their corresponding functions on each member of the struct.
    2104 To better simulate the behavior of C initializers, a set of \newterm{member constructors} is also generated for structures.
    2105 A constructor is generated for each nonempty prefix of a structure's member list to copy-construct the members passed as parameters and default-construct the remaining members.
     2060For @struct@ types, each of the four functions are implicitly defined to call their corresponding functions on each member of the struct.
     2061To better simulate the behaviour of C initializers, a set of \newterm{member constructors} is also generated for structures.
     2062A constructor is generated for each non-empty prefix of a structure's member-list to copy-construct the members passed as parameters and default-construct the remaining members.
    21062063To allow users to limit the set of constructors available for a type, when a user declares any constructor or destructor, the corresponding generated function and all member constructors for that type are hidden from expression resolution;
    2107 similarly, the generated default constructor is hidden upon the declaration of any constructor.
     2064similarly, the generated default constructor is hidden upon declaration of any constructor.
    21082065These semantics closely mirror the rule for implicit declaration of constructors in \CC\cite[p.~186]{ANSI98:C++}.
    21092066
    2110 In some circumstance, programmers may not wish to have implicit constructor and destructor generation and calls.
    2111 In these cases, \CFA provides the initialization syntax \lstinline|S x `@=` {}|, and the object becomes unmanaged;
    2112 hence, implicit \mbox{constructor} and destructor calls are not generated.
     2067In some circumstance programmers may not wish to have implicit constructor and destructor generation and calls.
     2068In these cases, \CFA provides the initialization syntax \lstinline|S x `@=` {}|, and the object becomes unmanaged, so implicit constructor and destructor calls are not generated.
    21132069Any C initializer can be the right-hand side of an \lstinline|@=| initializer, \eg \lstinline|VLA a @= { 0, 0x0 }|, with the usual C initialization semantics.
    21142070The same syntax can be used in a compound literal, \eg \lstinline|a = (VLA)`@`{ 0, 0x0 }|, to create a C-style literal.
    2115 The point of \lstinline|@=| is to provide a migration path from legacy C code to \CFA, by providing a mechanism to incrementally convert into implicit initialization.
     2071The point of \lstinline|@=| is to provide a migration path from legacy C code to \CFA, by providing a mechanism to incrementally convert to implicit initialization.
    21162072
    21172073
     
    21212077\section{Literals}
    21222078
    2123 C already includes limited polymorphism for literals---@0@ can be either an integer or a pointer literal, depending on context, whereas the syntactic forms of literals of the various integer and float types are very similar, differing from each other only in suffix.
    2124 In keeping with the general \CFA approach of adding features while respecting the ``C style'' of doing things, C's polymorphic constants and typed literal syntax are extended to interoperate with user-defined types, while maintaining a backward-compatible semantics.
     2079C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and float types are very similar, differing from each other only in suffix.
     2080In keeping with the general \CFA approach of adding features while respecting the ``C-style'' of doing things, C's polymorphic constants and typed literal syntax are extended to interoperate with user-defined types, while maintaining a backwards-compatible semantics.
    21252081
    21262082A simple example is allowing the underscore, as in Ada, to separate prefixes, digits, and suffixes in all \CFA constants, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@, where the underscore is also the standard separator in C identifiers.
    2127 \CC uses a single quote as a separator, but it is restricted among digits, precluding its use in the literal prefix or suffix, \eg @0x1.ffff@@`'@@ffffp128l@, and causes problems with most integrated development environments (IDEs), which must be extended to deal with this alternate use of the single quote.
     2083\CC uses a single quote as a separator but it is restricted among digits, precluding its use in the literal prefix or suffix, \eg @0x1.ffff@@`'@@ffffp128l@, and causes problems with most IDEs, which must be extended to deal with this alternate use of the single quote.
    21282084
    21292085
     
    21682124
    21692125In C, @0@ has the special property that it is the only ``false'' value;
    2170 by the standard, any value that compares equal to @0@ is false, whereas any value that compares unequal to @0@ is true.
    2171 As such, an expression @x@ in any Boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to @&&@, @||@, or @?:@\,) can be rewritten as @x != 0@ without changing its semantics.
     2126by the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true.
     2127As such, an expression @x@ in any boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to @&&@, @||@, or @?:@\,) can be rewritten as @x != 0@ without changing its semantics.
    21722128Operator overloading in \CFA provides a natural means to implement this truth-value comparison for arbitrary types, but the C type system is not precise enough to distinguish an equality comparison with @0@ from an equality comparison with an arbitrary integer or pointer.
    21732129To provide this precision, \CFA introduces a new type @zero_t@ as the type of literal @0@ (somewhat analagous to @nullptr_t@ and @nullptr@ in \CCeleven);
     
    21752131With this addition, \CFA rewrites @if (x)@ and similar expressions to @if ( (x) != 0 )@ or the appropriate analogue, and any type @T@ is ``truthy'' by defining an operator overload @int ?!=?( T, zero_t )@.
    21762132\CC makes types truthy by adding a conversion to @bool@;
    2177 prior to the addition of explicit cast operators in \CCeleven, this approach had the pitfall of making truthy types transitively convertible into any numeric type;
     2133prior to the addition of explicit cast operators in \CCeleven, this approach had the pitfall of making truthy types transitively convertable to any numeric type;
    21782134\CFA avoids this issue.
    21792135
     
    21862142
    21872143
    2188 \subsection{User literals}
     2144\subsection{User Literals}
    21892145
    21902146For readability, it is useful to associate units to scale literals, \eg weight (stone, pound, kilogram) or time (seconds, minutes, hours).
    2191 The left of Figure~\ref{f:UserLiteral} shows the \CFA alternative call syntax (postfix: literal argument before function name), using the backquote, to convert basic literals into user literals.
     2147The left of Figure~\ref{f:UserLiteral} shows the \CFA alternative call-syntax (postfix: literal argument before function name), using the backquote, to convert basic literals into user literals.
    21922148The backquote is a small character, making the unit (function name) predominate.
    2193 For examples, the multiprecision integer type in Section~\ref{s:MultiPrecisionIntegers} has the following user literals.
     2149For examples, the multi-precision integer-type in Section~\ref{s:MultiPrecisionIntegers} has user literals:
    21942150{\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    21952151\begin{cfa}
     
    21972153y = "12345678901234567890123456789"|`mp| + "12345678901234567890123456789"|`mp|;
    21982154\end{cfa}
    2199 Because \CFA uses a standard function, all types and literals are applicable, as well as overloading and conversions, where @?`@ denotes a postfix-function name and @`@  denotes a postfix-function call.
     2155Because \CFA uses a standard function, all types and literals are applicable, as well as overloading and conversions, where @?`@ denotes a postfix-function name and @`@ denotes a postfix-function call.
    22002156}%
    22012157\begin{cquote}
     
    22392195\end{cquote}
    22402196
    2241 The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call syntax.
     2197The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call-syntax.
    22422198However, \CC restricts the types, \eg @unsigned long long int@ and @long double@ to represent integral and floating literals.
    22432199After which, user literals must match (no conversions);
     
    22462202\begin{figure}
    22472203\centering
    2248 \fontsize{9bp}{11bp}\selectfont
    22492204\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    22502205\lstDeleteShortInline@%
     
    23022257\end{tabular}
    23032258\lstMakeShortInline@%
    2304 \caption{User literal}
     2259\caption{User Literal}
    23052260\label{f:UserLiteral}
    23062261\end{figure}
     
    23102265\label{sec:libraries}
    23112266
    2312 As stated in Section~\ref{sec:poly-fns}, \CFA inherits a large corpus of library code, where other programming languages must rewrite or provide fragile interlanguage communication with C.
     2267As stated in Section~\ref{sec:poly-fns}, \CFA inherits a large corpus of library code, where other programming languages must rewrite or provide fragile inter-language communication with C.
    23132268\CFA has replacement libraries condensing hundreds of existing C names into tens of \CFA overloaded names, all without rewriting the actual computations.
    2314 In many cases, the interface is an inline wrapper providing overloading during compilation but of zero cost at runtime.
     2269In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime.
    23152270The following sections give a glimpse of the interface reduction to many C libraries.
    23162271In many cases, @signed@/@unsigned@ @char@, @short@, and @_Complex@ functions are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results.
     
    23202275
    23212276C library @limits.h@ provides lower and upper bound constants for the basic types.
    2322 \CFA name overloading is used to condense these typed constants.
     2277\CFA name overloading is used to condense these typed constants, \eg:
    23232278\begin{cquote}
    23242279\lstDeleteShortInline@%
     
    23392294\lstMakeShortInline@%
    23402295\end{cquote}
    2341 The result is a significant reduction in names to access typed constants.
     2296The result is a significant reduction in names to access typed constants, \eg:
    23422297\begin{cquote}
    23432298\lstDeleteShortInline@%
     
    23652320
    23662321C library @math.h@ provides many mathematical functions.
    2367 \CFA function overloading is used to condense these mathematical functions.
     2322\CFA function overloading is used to condense these mathematical functions, \eg:
    23682323\begin{cquote}
    23692324\lstDeleteShortInline@%
     
    23842339\lstMakeShortInline@%
    23852340\end{cquote}
    2386 The result is a significant reduction in names to access math functions.
     2341The result is a significant reduction in names to access math functions, \eg:
    23872342\begin{cquote}
    23882343\lstDeleteShortInline@%
     
    24032358\lstMakeShortInline@%
    24042359\end{cquote}
    2405 While \Celeven has type-generic math (see section~7.25 of the ISO/IEC 9899\cite{C11}) in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a function name with a single set of floating type(s).
     2360While \Celeven has type-generic math~\cite[\S~7.25]{C11} in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a function name with a single set of floating type(s).
    24062361For example, it is impossible to overload @atan@ for both one and two arguments;
    2407 instead, the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}).
    2408 The key observation is that only a restricted set of type-generic macros is provided for a limited set of function names, which do not generalize across the type system, as in \CFA.
     2362instead the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}).
     2363The key observation is that only a restricted set of type-generic macros are provided for a limited set of function names, which do not generalize across the type system, as in \CFA.
    24092364
    24102365
     
    24122367
    24132368C library @stdlib.h@ provides many general functions.
    2414 \CFA function overloading is used to condense these utility functions.
     2369\CFA function overloading is used to condense these utility functions, \eg:
    24152370\begin{cquote}
    24162371\lstDeleteShortInline@%
     
    24312386\lstMakeShortInline@%
    24322387\end{cquote}
    2433 The result is a significant reduction in names to access the utility functions.
     2388The result is a significant reduction in names to access utility functions, \eg:
    24342389\begin{cquote}
    24352390\lstDeleteShortInline@%
     
    24502405\lstMakeShortInline@%
    24512406\end{cquote}
    2452 In addition, there are polymorphic functions, like @min@ and @max@, that work on any type with operator @?<?@ or @?>?@.
     2407In additon, there are polymorphic functions, like @min@ and @max@, that work on any type with operators @?<?@ or @?>?@.
    24532408
    24542409The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety.
    2455 C/\Celeven provide a number of complex and overlapping storage-management operations to support the following capabilities.
    2456 \begin{list}{}{\itemsep=0pt\parsep=0pt\labelwidth=0pt\leftmargin\parindent\itemindent-\leftmargin\let\makelabel\descriptionlabel}
     2410C/\Celeven provide a number of complex and overlapping storage-management operation to support the following capabilities:
     2411\begin{description}%[topsep=3pt,itemsep=2pt,parsep=0pt]
    24572412\item[fill]
    24582413an allocation with a specified character.
    24592414\item[resize]
    24602415an existing allocation to decrease or increase its size.
    2461 In either case, new storage may or may not be allocated, and if there is a new allocation, as much data from the existing allocation are copied.
     2416In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied.
    24622417For an increase in storage size, new storage after the copied data may be filled.
    2463 \newpage
    24642418\item[align]
    24652419an allocation on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.
     
    24672421allocation with a specified number of elements.
    24682422An array may be filled, resized, or aligned.
    2469 \end{list}
    2470 Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation functions and how all the capabilities can be combined into two \CFA functions.
    2471 \CFA storage-management functions extend the C equivalents by overloading, providing shallow type safety, and removing the need to specify the base allocation size.
    2472 Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage allocation performing the same operations with the same type safety.
     2423\end{description}
     2424Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-functions and how all the capabilities can be combined into two \CFA functions.
     2425\CFA storage-management functions extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size.
     2426Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation performing the same operations with the same type safety.
    24732427
    24742428\begin{table}
    2475 \caption{Storage-management operations}
     2429\caption{Storage-Management Operations}
    24762430\label{t:StorageManagementOperations}
    24772431\centering
    24782432\lstDeleteShortInline@%
    24792433\lstMakeShortInline~%
    2480 \begin{tabular}{@{}rrllll@{}}
    2481 \multicolumn{1}{c}{}&           & \multicolumn{1}{c}{fill}      & resize        & align & array \\
     2434\begin{tabular}{@{}r|r|l|l|l|l@{}}
     2435\multicolumn{1}{c}{}&           & \multicolumn{1}{c|}{fill}     & resize        & align & array \\
     2436\hline
    24822437C               & ~malloc~                      & no                    & no            & no            & no    \\
    24832438                & ~calloc~                      & yes (0 only)  & no            & no            & yes   \\
     
    24852440                & ~memalign~            & no                    & no            & yes           & no    \\
    24862441                & ~posix_memalign~      & no                    & no            & yes           & no    \\
     2442\hline
    24872443C11             & ~aligned_alloc~       & no                    & no            & yes           & no    \\
     2444\hline
    24882445\CFA    & ~alloc~                       & yes/copy              & no/yes        & no            & yes   \\
    24892446                & ~align_alloc~         & yes                   & no            & yes           & yes   \\
     
    24952452\begin{figure}
    24962453\centering
    2497 \fontsize{9bp}{11bp}\selectfont
    24982454\begin{cfa}[aboveskip=0pt,xleftmargin=0pt]
    24992455size_t  dim = 10;                                                       $\C{// array dimension}$
     
    25332489\end{tabular}
    25342490\lstMakeShortInline@%
    2535 \caption{\CFA versus C storage allocation}
     2491\caption{\CFA versus C Storage-Allocation}
    25362492\label{f:StorageAllocation}
    25372493\end{figure}
    25382494
    25392495Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization.
    2540 Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor.
     2496Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor, \eg:
    25412497\begin{cfa}
    25422498struct S { int i, j; };
     
    25452501S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
    25462502\end{cfa}
    2547 Note that \CC can only initialize array elements via the default constructor.
    2548 
    2549 Finally, the \CFA memory allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
     2503Note, \CC can only initialize array elements via the default constructor.
     2504
     2505Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
    25502506When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character.
    25512507
     
    25542510\label{s:IOLibrary}
    25552511
    2556 The goal of \CFA I/O is to simplify the common cases, while fully supporting polymorphism and user-defined types in a consistent way.
     2512The goal of \CFA I/O is to simplify the common cases, while fully supporting polymorphism and user defined types in a consistent way.
    25572513The approach combines ideas from \CC and Python.
    25582514The \CFA header file for the I/O library is @fstream@.
     
    25832539\lstMakeShortInline@%
    25842540\end{cquote}
    2585 The \CFA form has half the characters of the \CC form and is similar to Python I/O with respect to implicit separators.
     2541The \CFA form has half the characters of the \CC form, and is similar to Python I/O with respect to implicit separators.
    25862542Similar simplification occurs for tuple I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
    25872543\begin{cfa}
     
    26162572\lstMakeShortInline@%
    26172573\end{cquote}
    2618 There is a weak similarity between the \CFA logical-or operator and the Shell pipe operator for moving data, where data flow in the correct direction for input but in the opposite direction for output.
     2574There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
    26192575\begin{comment}
    26202576The implicit separator character (space/blank) is a separator not a terminator.
     
    26372593\end{itemize}
    26382594\end{comment}
    2639 There are functions to set and get the separator string and manipulators to toggle separation on and off in the middle of output.
    2640 
    2641 
    2642 \subsection{Multiprecision integers}
     2595There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.
     2596
     2597
     2598\subsection{Multi-precision Integers}
    26432599\label{s:MultiPrecisionIntegers}
    26442600
    2645 \CFA has an interface to the GNU multiple precision (GMP) signed integers~\cite{GMP}, similar to the \CC interface provided by GMP.
    2646 The \CFA interface wraps GMP functions into operator functions to make programming with multiprecision integers identical to using fixed-sized integers.
    2647 The \CFA type name for multiprecision signed integers is @Int@ and the header file is @gmp@.
    2648 Figure~\ref{f:GMPInterface} shows a multiprecision factorial program contrasting the GMP interface in \CFA and C.
    2649 
    2650 \begin{figure}[b]
     2601\CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP.
     2602The \CFA interface wraps GMP functions into operator functions to make programming with multi-precision integers identical to using fixed-sized integers.
     2603The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@.
     2604Figure~\ref{f:GMPInterface} shows a multi-precision factorial-program contrasting the GMP interface in \CFA and C.
     2605
     2606\begin{figure}
    26512607\centering
    2652 \fontsize{9bp}{11bp}\selectfont
    26532608\lstDeleteShortInline@%
    26542609\begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
     
    26812636\end{tabular}
    26822637\lstMakeShortInline@%
    2683 \caption{GMP interface \CFA versus C}
     2638\caption{GMP Interface \CFA versus C}
    26842639\label{f:GMPInterface}
    26852640\end{figure}
    26862641
    26872642
    2688 \vspace{-4pt}
    26892643\section{Polymorphism Evaluation}
    26902644\label{sec:eval}
     
    26952649% Though \CFA provides significant added functionality over C, these features have a low runtime penalty.
    26962650% In fact, it is shown that \CFA's generic programming can enable faster runtime execution than idiomatic @void *@-based C code.
    2697 The experiment is a set of generic-stack microbenchmarks~\cite{CFAStackEvaluation} in C, \CFA, and \CC (see implementations in Appendix~\ref{sec:BenchmarkStackImplementations}).
     2651The experiment is a set of generic-stack micro-benchmarks~\cite{CFAStackEvaluation} in C, \CFA, and \CC (see implementations in Appendix~\ref{sec:BenchmarkStackImplementations}).
    26982652Since all these languages share a subset essentially comprising standard C, maximal-performance benchmarks should show little runtime variance, differing only in length and clarity of source code.
    26992653A more illustrative comparison measures the costs of idiomatic usage of each language's features.
    2700 Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked list.
     2654Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list.
    27012655The benchmark test is similar for the other languages.
    27022656The experiment uses element types @int@ and @pair(short, char)@, and pushes $N=40M$ elements on a generic stack, copies the stack, clears one of the stacks, and finds the maximum value in the other stack.
    27032657
    27042658\begin{figure}
    2705 \fontsize{9bp}{11bp}\selectfont
    27062659\begin{cfa}[xleftmargin=3\parindentlnth,aboveskip=0pt,belowskip=0pt]
    27072660int main() {
     
    27232676}
    27242677\end{cfa}
    2725 \caption{\protect\CFA benchmark test}
     2678\caption{\protect\CFA Benchmark Test}
    27262679\label{fig:BenchmarkTest}
    2727 \vspace*{-10pt}
    27282680\end{figure}
    27292681
    2730 The structure of each benchmark implemented is C with @void *@-based polymorphism, \CFA with parametric polymorphism, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV.
     2682The structure of each benchmark implemented is: C with @void *@-based polymorphism, \CFA with parametric polymorphism, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV.
    27312683The \CCV variant illustrates an alternative object-oriented idiom where all objects inherit from a base @object@ class, mimicking a Java-like interface;
    2732 hence, runtime checks are necessary to safely downcast objects.
    2733 The most notable difference among the implementations is in memory layout of generic types: \CFA and \CC inline the stack and pair elements into corresponding list and pair nodes, whereas C and \CCV lack such capability and, instead, must store generic objects via pointers to separately allocated objects.
    2734 Note that the C benchmark uses unchecked casts as C has no runtime mechanism to perform such checks, whereas \CFA and \CC provide type safety statically.
     2684hence runtime checks are necessary to safely down-cast objects.
     2685The most notable difference among the implementations is in memory layout of generic types: \CFA and \CC inline the stack and pair elements into corresponding list and pair nodes, while C and \CCV lack such a capability and instead must store generic objects via pointers to separately-allocated objects.
     2686Note, the C benchmark uses unchecked casts as C has no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically.
    27352687
    27362688Figure~\ref{fig:eval} and Table~\ref{tab:eval} show the results of running the benchmark in Figure~\ref{fig:BenchmarkTest} and its C, \CC, and \CCV equivalents.
    2737 The graph plots the median of five consecutive runs of each program, with an initial warm-up run omitted.
     2689The graph plots the median of 5 consecutive runs of each program, with an initial warm-up run omitted.
    27382690All code is compiled at \texttt{-O2} by gcc or g++ 6.4.0, with all \CC code compiled as \CCfourteen.
    27392691The benchmarks are run on an Ubuntu 16.04 workstation with 16 GB of RAM and a 6-core AMD FX-6300 CPU with 3.5 GHz maximum clock frequency.
     
    27412693\begin{figure}
    27422694\centering
    2743 \resizebox{0.7\textwidth}{!}{\input{timing}}
    2744 \caption{Benchmark timing results (smaller is better)}
     2695\input{timing}
     2696\caption{Benchmark Timing Results (smaller is better)}
    27452697\label{fig:eval}
    2746 \vspace*{-10pt}
    27472698\end{figure}
    27482699
    27492700\begin{table}
    2750 \vspace*{-10pt}
    27512701\caption{Properties of benchmark code}
    27522702\label{tab:eval}
    27532703\centering
    2754 \vspace*{-4pt}
    27552704\newcommand{\CT}[1]{\multicolumn{1}{c}{#1}}
    2756 \begin{tabular}{lrrrr}
    2757                                                                         & \CT{C}        & \CT{\CFA}     & \CT{\CC}      & \CT{\CCV}             \\
    2758 maximum memory usage (MB)                       & 10\,001       & 2\,502        & 2\,503        & 11\,253               \\
     2705\begin{tabular}{rrrrr}
     2706                                                                        & \CT{C}        & \CT{\CFA}     & \CT{\CC}      & \CT{\CCV}             \\ \hline
     2707maximum memory usage (MB)                       & 10,001        & 2,502         & 2,503         & 11,253                \\
    27592708source code size (lines)                        & 201           & 191           & 125           & 294                   \\
    27602709redundant type annotations (lines)      & 27            & 0                     & 2                     & 16                    \\
    27612710binary size (KB)                                        & 14            & 257           & 14            & 37                    \\
    27622711\end{tabular}
    2763 \vspace*{-16pt}
    27642712\end{table}
    27652713
    2766 \enlargethispage{-10pt}
    2767 The C and \CCV variants are generally the slowest with the largest memory footprint, due to their less-efficient memory layout and the pointer indirection necessary to implement generic types;
     2714The C and \CCV variants are generally the slowest with the largest memory footprint, because of their less-efficient memory layout and the pointer-indirection necessary to implement generic types;
    27682715this inefficiency is exacerbated by the second level of generic types in the pair benchmarks.
    2769 By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair because of the equivalent storage layout, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead.
    2770 \CCV is slower than C largely due to the cost of runtime type checking of downcasts (implemented with @dynamic_cast@).
     2716By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair because of equivalent storage layout, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead.
     2717\CCV is slower than C largely due to the cost of runtime type-checking of down-casts (implemented with @dynamic_cast@);
    27712718The outlier for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code.
    27722719The gcc compiler is unable to optimize some dead code and condense nested calls;
     
    27742721Finally, the binary size for \CFA is larger because of static linking with the \CFA libraries.
    27752722
    2776 \CFA is also competitive in terms of source code size, measured as a proxy for programmer effort. The line counts in Table~\ref{tab:eval} include implementations of @pair@ and @stack@ types for all four languages for purposes of direct comparison, although it should be noted that \CFA and \CC have prewritten data structures in their standard libraries that programmers would generally use instead. Use of these standard library types has minimal impact on the performance benchmarks, but shrinks the \CFA and \CC benchmarks to 39 and 42 lines, respectively.
     2723\CFA is also competitive in terms of source code size, measured as a proxy for programmer effort. The line counts in Table~\ref{tab:eval} include implementations of @pair@ and @stack@ types for all four languages for purposes of direct comparison, though it should be noted that \CFA and \CC have pre-written data structures in their standard libraries that programmers would generally use instead. Use of these standard library types has minimal impact on the performance benchmarks, but shrinks the \CFA and \CC benchmarks to 39 and 42 lines, respectively.
    27772724The difference between the \CFA and \CC line counts is primarily declaration duplication to implement separate compilation; a header-only \CFA library would be similar in length to the \CC version.
    2778 On the other hand, C does not have a generic collections library in its standard distribution, resulting in frequent reimplementation of such collection types by C programmers.
    2779 \CCV does not use the \CC standard template library by construction and, in fact, includes the definition of @object@ and wrapper classes for @char@, @short@, and @int@ in its line count, which inflates this count somewhat, as an actual object-oriented language would include these in the standard library;
     2725On the other hand, C does not have a generic collections-library in its standard distribution, resulting in frequent reimplementation of such collection types by C programmers.
     2726\CCV does not use the \CC standard template library by construction, and in fact includes the definition of @object@ and wrapper classes for @char@, @short@, and @int@ in its line count, which inflates this count somewhat, as an actual object-oriented language would include these in the standard library;
    27802727with their omission, the \CCV line count is similar to C.
    27812728We justify the given line count by noting that many object-oriented languages do not allow implementing new interfaces on library types without subclassing or wrapper types, which may be similarly verbose.
    27822729
    2783 Line count is a fairly rough measure of code complexity;
    2784 another important factor is how much type information the programmer must specify manually, especially where that information is not compiler checked.
    2785 Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of un-type-checked downcasts, \eg @object@ to @integer@ when popping a stack.
     2730Line-count is a fairly rough measure of code complexity;
     2731another important factor is how much type information the programmer must specify manually, especially where that information is not compiler-checked.
     2732Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of un-type-checked downcasts, \eg @object@ to @integer@ when popping a stack.
    27862733To quantify this manual typing, the ``redundant type annotations'' line in Table~\ref{tab:eval} counts the number of lines on which the type of a known variable is respecified, either as a format specifier, explicit downcast, type-specific function, or by name in a @sizeof@, struct literal, or @new@ expression.
    2787 The \CC benchmark uses two redundant type annotations to create a new stack nodes, whereas the C and \CCV benchmarks have several such annotations spread throughout their code.
     2734The \CC benchmark uses two redundant type annotations to create a new stack nodes, while the C and \CCV benchmarks have several such annotations spread throughout their code.
    27882735The \CFA benchmark is able to eliminate all redundant type annotations through use of the polymorphic @alloc@ function discussed in Section~\ref{sec:libraries}.
    27892736
    2790 We conjecture that these results scale across most generic data types as the underlying polymorphism implement is constant.
    2791 
    2792 
    2793 \vspace*{-8pt}
     2737We conjecture these results scale across most generic data-types as the underlying polymorphism implement is constant.
     2738
     2739
    27942740\section{Related Work}
    27952741\label{s:RelatedWork}
     
    28072753\CC provides three disjoint polymorphic extensions to C: overloading, inheritance, and templates.
    28082754The overloading is restricted because resolution does not use the return type, inheritance requires learning object-oriented programming and coping with a restricted nominal-inheritance hierarchy, templates cannot be separately compiled resulting in compilation/code bloat and poor error messages, and determining how these mechanisms interact and which to use is confusing.
    2809 In contrast, \CFA has a single facility for polymorphic code supporting type-safe separate compilation of polymorphic functions and generic (opaque) types, which uniformly leverage the C procedural paradigm.
     2755In contrast, \CFA has a single facility for polymorphic code supporting type-safe separate-compilation of polymorphic functions and generic (opaque) types, which uniformly leverage the C procedural paradigm.
    28102756The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed type properties.
    2811 Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way of specifying the requirements of a generic function beyond compilation errors during template expansion;
     2757Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function beyond compilation errors during template expansion;
    28122758furthermore, \CC concepts are restricted to template polymorphism.
    28132759
    28142760Cyclone~\cite{Grossman06} also provides capabilities for polymorphic functions and existential types, similar to \CFA's @forall@ functions and generic types.
    2815 Cyclone existential types can include function pointers in a construct similar to a virtual function table, but these pointers must be explicitly initialized at some point in the code, which is a tedious and potentially error-prone process.
     2761Cyclone existential types can include function pointers in a construct similar to a virtual function-table, but these pointers must be explicitly initialized at some point in the code, a tedious and potentially error-prone process.
    28162762Furthermore, Cyclone's polymorphic functions and types are restricted to abstraction over types with the same layout and calling convention as @void *@, \ie only pointer types and @int@.
    28172763In \CFA terms, all Cyclone polymorphism must be dtype-static.
    28182764While the Cyclone design provides the efficiency benefits discussed in Section~\ref{sec:generic-apps} for dtype-static polymorphism, it is more restrictive than \CFA's general model.
    2819 Smith and Volpano~\cite{Smith98} present Polymorphic C, an ML dialect with polymorphic functions, C-like syntax, and pointer types;
    2820 it lacks many of C's features, most notably structure types, and hence, is not a practical C replacement.
     2765Smith and Volpano~\cite{Smith98} present Polymorphic C, an ML dialect with polymorphic functions, C-like syntax, and pointer types; it lacks many of C's features, however, most notably structure types, and so is not a practical C replacement.
    28212766
    28222767Objective-C~\cite{obj-c-book} is an industrially successful extension to C.
    2823 However, Objective-C is a radical departure from C, using an object-oriented model with message passing.
     2768However, Objective-C is a radical departure from C, using an object-oriented model with message-passing.
    28242769Objective-C did not support type-checked generics until recently \cite{xcode7}, historically using less-efficient runtime checking of object types.
    2825 The GObject~\cite{GObject} framework also adds object-oriented programming with runtime type-checking and reference-counting garbage collection to C;
    2826 these features are more intrusive additions than those provided by \CFA, in addition to the runtime overhead of reference counting.
    2827 Vala~\cite{Vala} compiles to GObject-based C, adding the burden of learning a separate language syntax to the aforementioned demerits of GObject as a modernization path for existing C code bases.
    2828 Java~\cite{Java8} included generic types in Java~5, which are type checked at compilation and type erased at runtime, similar to \CFA's.
    2829 However, in Java, each object carries its own table of method pointers, whereas \CFA passes the method pointers separately to maintain a C-compatible layout.
     2770The GObject~\cite{GObject} framework also adds object-oriented programming with runtime type-checking and reference-counting garbage-collection to C;
     2771these features are more intrusive additions than those provided by \CFA, in addition to the runtime overhead of reference-counting.
     2772Vala~\cite{Vala} compiles to GObject-based C, adding the burden of learning a separate language syntax to the aforementioned demerits of GObject as a modernization path for existing C code-bases.
     2773Java~\cite{Java8} included generic types in Java~5, which are type-checked at compilation and type-erased at runtime, similar to \CFA's.
     2774However, in Java, each object carries its own table of method pointers, while \CFA passes the method pointers separately to maintain a C-compatible layout.
    28302775Java is also a garbage-collected, object-oriented language, with the associated resource usage and C-interoperability burdens.
    28312776
    2832 D~\cite{D}, Go, and Rust~\cite{Rust} are modern compiled languages with abstraction features similar to \CFA traits, \emph{interfaces} in D and Go, and \emph{traits} in Rust.
     2777D~\cite{D}, Go, and Rust~\cite{Rust} are modern, compiled languages with abstraction features similar to \CFA traits, \emph{interfaces} in D and Go and \emph{traits} in Rust.
    28332778However, each language represents a significant departure from C in terms of language model, and none has the same level of compatibility with C as \CFA.
    28342779D and Go are garbage-collected languages, imposing the associated runtime overhead.
    28352780The necessity of accounting for data transfer between managed runtimes and the unmanaged C runtime complicates foreign-function interfaces to C.
    28362781Furthermore, while generic types and functions are available in Go, they are limited to a small fixed set provided by the compiler, with no language facility to define more.
    2837 D restricts garbage collection to its own heap by default, whereas Rust is not garbage collected and, thus, has a lighter-weight runtime more interoperable with C.
     2782D restricts garbage collection to its own heap by default, while Rust is not garbage-collected, and thus has a lighter-weight runtime more interoperable with C.
    28382783Rust also possesses much more powerful abstraction capabilities for writing generic code than Go.
    2839 On the other hand, Rust's borrow checker provides strong safety guarantees but is complex and difficult to learn and imposes a distinctly idiomatic programming style.
     2784On the other hand, Rust's borrow-checker provides strong safety guarantees but is complex and difficult to learn and imposes a distinctly idiomatic programming style.
    28402785\CFA, with its more modest safety features, allows direct ports of C code while maintaining the idiomatic style of the original source.
    28412786
    28422787
    2843 \vspace*{-18pt}
    2844 \subsection{Tuples/variadics}
    2845 
    2846 \vspace*{-5pt}
     2788\subsection{Tuples/Variadics}
     2789
    28472790Many programming languages have some form of tuple construct and/or variadic functions, \eg SETL, C, KW-C, \CC, D, Go, Java, ML, and Scala.
    28482791SETL~\cite{SETL} is a high-level mathematical programming language, with tuples being one of the primary data types.
    28492792Tuples in SETL allow subscripting, dynamic expansion, and multiple assignment.
    2850 C provides variadic functions through @va_list@ objects, but the programmer is responsible for managing the number of arguments and their types;
    2851 thus, the mechanism is type unsafe.
     2793C provides variadic functions through @va_list@ objects, but the programmer is responsible for managing the number of arguments and their types, so the mechanism is type unsafe.
    28522794KW-C~\cite{Buhr94a}, a predecessor of \CFA, introduced tuples to C as an extension of the C syntax, taking much of its inspiration from SETL.
    28532795The main contributions of that work were adding MRVF, tuple mass and multiple assignment, and record-member access.
    2854 \CCeleven introduced @std::tuple@ as a library variadic-template structure.
     2796\CCeleven introduced @std::tuple@ as a library variadic template structure.
    28552797Tuples are a generalization of @std::pair@, in that they allow for arbitrary length, fixed-size aggregation of heterogeneous values.
    28562798Operations include @std::get<N>@ to extract values, @std::tie@ to create a tuple of references used for assignment, and lexicographic comparisons.
    2857 \CCseventeen proposes \emph{structured bindings}~\cite{Sutter15} to eliminate predeclaring variables and the use of @std::tie@ for binding the results.
    2858 This extension requires the use of @auto@ to infer the types of the new variables; hence, complicated expressions with a nonobvious type must be documented with some other mechanism.
     2799\CCseventeen proposes \emph{structured bindings}~\cite{Sutter15} to eliminate pre-declaring variables and use of @std::tie@ for binding the results.
     2800This extension requires the use of @auto@ to infer the types of the new variables, so complicated expressions with a non-obvious type must be documented with some other mechanism.
    28592801Furthermore, structured bindings are not a full replacement for @std::tie@, as it always declares new variables.
    28602802Like \CC, D provides tuples through a library variadic-template structure.
    28612803Go does not have tuples but supports MRVF.
    2862 Java's variadic functions appear similar to C's but are type safe using homogeneous arrays, which are less useful than \CFA's heterogeneously typed variadic functions.
     2804Java's variadic functions appear similar to C's but are type-safe using homogeneous arrays, which are less useful than \CFA's heterogeneously-typed variadic functions.
    28632805Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML~\cite{sml}, Haskell, and Scala~\cite{Scala}, which decompose tuples using pattern matching.
    28642806
    28652807
    2866 \vspace*{-18pt}
    28672808\subsection{C Extensions}
    28682809
    2869 \vspace*{-5pt}
    2870 \CC is the best known C-based language and is similar to \CFA in that both are extensions to C with source and runtime backward compatibility.
    2871 Specific differences between \CFA and \CC have been identified in prior sections, with a final observation that \CFA has equal or fewer tokens to express the same notion in many cases.
     2810\CC is the best known C-based language, and is similar to \CFA in that both are extensions to C with source and runtime backwards compatibility.
     2811Specific difference between \CFA and \CC have been identified in prior sections, with a final observation that \CFA has equal or fewer tokens to express the same notion in many cases.
    28722812The key difference in design philosophies is that \CFA is easier for C programmers to understand by maintaining a procedural paradigm and avoiding complex interactions among extensions.
    28732813\CC, on the other hand, has multiple overlapping features (such as the three forms of polymorphism), many of which have complex interactions with its object-oriented design.
    2874 As a result, \CC has a steep learning curve for even experienced C programmers, especially when attempting to maintain performance equivalent to C legacy code.
    2875 
    2876 There are several other C extension languages with less usage and even more dramatic changes than \CC.
    2877 \mbox{Objective-C} and Cyclone are two other extensions to C with different design goals than \CFA, as discussed above.
     2814As a result, \CC has a steep learning curve for even experienced C programmers, especially when attempting to maintain performance equivalent to C legacy-code.
     2815
     2816There are several other C extension-languages with less usage and even more dramatic changes than \CC.
     2817Objective-C and Cyclone are two other extensions to C with different design goals than \CFA, as discussed above.
    28782818Other languages extend C with more focused features.
    28792819$\mu$\CC~\cite{uC++book}, CUDA~\cite{Nickolls08}, ispc~\cite{Pharr12}, and Sierra~\cite{Leissa14} add concurrent or data-parallel primitives to C or \CC;
    2880 data-parallel features have not yet been added to \CFA, but are easily incorporated within its design, whereas concurrency primitives similar to those in $\mu$\CC have already been added~\cite{Delisle18}.
    2881 Finally, CCured~\cite{Necula02} and Ironclad \CC~\cite{DeLozier13} attempt to provide a more memory-safe C by annotating pointer types with garbage collection information; type-checked polymorphism in \CFA covers several of C's memory-safety issues, but more aggressive approaches such as annotating all pointer types with their nullability or requiring runtime garbage collection are contradictory to \CFA's backward compatibility goals.
     2820data-parallel features have not yet been added to \CFA, but are easily incorporated within its design, while concurrency primitives similar to those in $\mu$\CC have already been added~\cite{Delisle18}.
     2821Finally, CCured~\cite{Necula02} and Ironclad \CC~\cite{DeLozier13} attempt to provide a more memory-safe C by annotating pointer types with garbage collection information; type-checked polymorphism in \CFA covers several of C's memory-safety issues, but more aggressive approaches such as annotating all pointer types with their nullability or requiring runtime garbage collection are contradictory to \CFA's backwards compatibility goals.
    28822822
    28832823
    28842824\section{Conclusion and Future Work}
    28852825
    2886 The goal of \CFA is to provide an evolutionary pathway for large C development environments to be more productive and safer, while respecting the talent and skill of C programmers.
    2887 While other programming languages purport to be a better C, they are, in fact, new and interesting languages in their own right, but not C extensions.
    2888 The purpose of this paper is to introduce \CFA, and showcase language features that illustrate the \CFA type system and approaches taken to achieve the goal of evolutionary C extension.
    2889 The contributions are a powerful type system using parametric polymorphism and overloading, generic types, tuples, advanced control structures, and extended declarations, which all have complex interactions.
     2826The goal of \CFA is to provide an evolutionary pathway for large C development-environments to be more productive and safer, while respecting the talent and skill of C programmers.
     2827While other programming languages purport to be a better C, they are in fact new and interesting languages in their own right, but not C extensions.
     2828The purpose of this paper is to introduce \CFA, and showcase language features that illustrate the \CFA type-system and approaches taken to achieve the goal of evolutionary C extension.
     2829The contributions are a powerful type-system using parametric polymorphism and overloading, generic types, tuples, advanced control structures, and extended declarations, which all have complex interactions.
    28902830The work is a challenging design, engineering, and implementation exercise.
    28912831On the surface, the project may appear as a rehash of similar mechanisms in \CC.
    28922832However, every \CFA feature is different than its \CC counterpart, often with extended functionality, better integration with C and its programmers, and always supporting separate compilation.
    2893 All of these new features are being used by the \CFA development team to build the \CFA runtime system.
     2833All of these new features are being used by the \CFA development-team to build the \CFA runtime-system.
    28942834Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable.
    28952835
    2896 While all examples in the paper compile and run, there are ongoing efforts to reduce compilation time, provide better debugging, and add more libraries;
    2897 when this work is complete in early 2019, a public beta release will be available at \url{https://github.com/cforall/cforall}.
    2898 There is also new work on a number of \CFA features, including arrays with size, runtime type information, virtual functions, user-defined conversions, and modules.
    2899 While \CFA polymorphic functions use dynamic virtual dispatch with low runtime overhead (see Section~\ref{sec:eval}), it is not as low as \CC template inlining.
    2900 Hence, it may be beneficial to provide a mechanism for performance-sensitive code.
    2901 Two promising approaches are an @inline@ annotation at polymorphic function call sites to create a template specialization of the function (provided the code is visible) or placing an @inline@ annotation on polymorphic function definitions to instantiate a specialized version for some set of types (\CC template specialization).
    2902  These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code bloat.
    2903 In general, we believe separate compilation, producing smaller code, works well with loaded hardware caches, which may offset the benefit of larger inlined code.
     2836While all examples in the paper compile and run, a public beta-release of \CFA will take 6--8 months to reduce compilation time, provide better debugging, and add a few more libraries.
     2837There is also new work on a number of \CFA features, including arrays with size, runtime type-information, virtual functions, user-defined conversions, and modules.
     2838While \CFA polymorphic functions use dynamic virtual-dispatch with low runtime overhead (see Section~\ref{sec:eval}), it is not as low as \CC template-inlining.
     2839Hence it may be beneficial to provide a mechanism for performance-sensitive code.
     2840Two promising approaches are an @inline@ annotation at polymorphic function call sites to create a template-specialization of the function (provided the code is visible) or placing an @inline@ annotation on polymorphic function-definitions to instantiate a specialized version for some set of types (\CC template specialization).
     2841These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code-bloat.
     2842In general, we believe separate compilation, producing smaller code, works well with loaded hardware-caches, which may offset the benefit of larger inlined-code.
    29042843
    29052844
    29062845\section{Acknowledgments}
    29072846
    2908 The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, Thierry Delisle, Andrew Beach, and Brice Dobry on the features described in this paper and thank Magnus Madsen for feedback on the writing.
    2909 Funding for this project was provided by Huawei Ltd (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr were partially funded by the Natural Sciences and Engineering Research Council of Canada.
     2847The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, Thierry Delisle, Andrew Beach and Brice Dobry on the features described in this paper, and thank Magnus Madsen for feedback on the writing.
     2848Funding for this project has been provided by Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada.
    29102849
    29112850{%
    29122851\fontsize{9bp}{12bp}\selectfont%
    2913 \vspace*{-3pt}
    29142852\bibliography{pl}
    29152853}%
     
    29902928
    29912929
    2992 \enlargethispage{1000pt}
    29932930\subsection{\CFA}
    29942931\label{s:CforallStack}
     
    30572994
    30582995
    3059 \newpage
    30602996\subsection{\CC}
    30612997
  • doc/proposals/ctordtor/Makefile

    rb067d9b r7951100  
    1 ## Define the configuration variables.
     1## Define the appropriate configuration variables.
    22
    3 Build = build
    4 Figures = figures
    5 Macros = ../../LaTeXmacros
    6 Bib = ../../bibliography
     3MACROS = ../../LaTeXmacros
     4BIB = ../../bibliography
    75
    8 TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
    9 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
     6TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
     7LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
    108BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
    11 
    12 MAKEFLAGS = --no-print-directory # --silent
    13 VPATH = ${Build} ${Figures}
    149
    1510## Define the text source files.
     
    3429
    3530DOCUMENT = ctor.pdf
    36 BASE = ${basename ${DOCUMENT}}
    3731
    3832# Directives #
    39 
    40 .PHONY : all clean                                      # not file names
    4133
    4234all : ${DOCUMENT}
    4335
    4436clean :
    45         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     37        rm -f *.bbl *.aux *.dvi *.idx *.ilg *.ind *.brf *.out *.log *.toc *.blg *.pstex_t *.cf \
     38                ${FIGURES} ${PICTURES} ${PROGRAMS} ${GRAPHS} ${basename ${DOCUMENT}}.ps ${DOCUMENT}
    4639
    4740# File Dependencies #
    4841
    49 ${DOCUMENT} : ${BASE}.ps
     42${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    5043        ps2pdf $<
    5144
    52 ${BASE}.ps : ${BASE}.dvi
    53         dvips ${Build}/$< -o $@
     45${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     46        dvips $< -o $@
    5447
    55 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
     48${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
     49                $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
    5750        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    58         #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     51        if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
    5952        # Must have *.aux file containing citations for bibtex
    6053        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    61         -${BibTeX} ${Build}/${basename $@}
    62         # Some citations reference others so run again to resolve these citations
     54        -${BibTeX} ${basename $@}
     55        # Some citations reference others so run steps again to resolve these citations
    6356        ${LaTeX} ${basename $@}.tex
    64         -${BibTeX} ${Build}/${basename $@}
     57        -${BibTeX} ${basename $@}
    6558        # Make index from *.aux entries and input index at end of document
    66         #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
    67         # Run again to finish citations
     59        makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
    6860        ${LaTeX} ${basename $@}.tex
    6961        # Run again to get index title into table of contents
     
    7567## Define the default recipes.
    7668
    77 ${Build}:
    78         mkdir -p ${Build}
     69%.tex : %.fig
     70        fig2dev -L eepic $< > $@
    7971
    80 %.tex : %.fig | ${Build}
    81         fig2dev -L eepic $< > ${Build}/$@
     72%.ps : %.fig
     73        fig2dev -L ps $< > $@
    8274
    83 %.ps : %.fig | ${Build}
    84         fig2dev -L ps $< > ${Build}/$@
    85 
    86 %.pstex : %.fig | ${Build}
    87         fig2dev -L pstex $< > ${Build}/$@
    88         fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
     75%.pstex : %.fig
     76        fig2dev -L pstex $< > $@
     77        fig2dev -L pstex_t -p $@ $< > $@_t
    8978
    9079# Local Variables: #
  • doc/proposals/ctordtor/ctor.tex

    rb067d9b r7951100  
     1% inline code ©...© (copyright symbol) emacs: C-q M-)
     2% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     3% blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
     4% green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
     5% LaTex escape §...§ (section symbol) emacs: C-q M-'
     6% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     7% math escape $...$ (dollar symbol)
     8
    19\documentclass[twoside,11pt]{article}
    210
     
    715\usepackage{textcomp}
    816\usepackage[latin1]{inputenc}
    9 
    1017\usepackage{fullpage,times,comment}
    1118\usepackage{epic,eepic}
    12 \usepackage{upquote}                                    % switch curled `'" to straight
     19\usepackage{upquote}                                                                    % switch curled `'" to straight
    1320\usepackage{calc}
    1421\usepackage{xspace}
    1522\usepackage{graphicx}
    16 \usepackage{varioref}                                   % extended references
    17 \usepackage{listings}                                   % format program code
    18 \usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
     23\usepackage{varioref}                                                                   % extended references
     24\usepackage{listings}                                                                   % format program code
     25\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    1926\usepackage{latexsym}                                   % \Box glyph
    2027\usepackage{mathptmx}                                   % better math font with "times"
     
    2734\renewcommand{\UrlFont}{\small\sf}
    2835
    29 \setlength{\topmargin}{-0.45in}                         % move running title into header
     36\setlength{\topmargin}{-0.45in}                                                 % move running title into header
    3037\setlength{\headsep}{0.25in}
    3138
     
    3643
    3744\interfootnotelinepenalty=10000
    38 
    39 \CFAStyle                                               % use default CFA format-style
    40 % inline code ©...© (copyright symbol) emacs: C-q M-)
    41 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    42 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    43 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    44 % LaTex escape §...§ (section symbol) emacs: C-q M-'
    45 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    46 % math escape $...$ (dollar symbol)
    47 
    4845
    4946\title{
     
    8683\thispagestyle{plain}
    8784\pagenumbering{arabic}
     85
    8886
    8987
  • doc/proposals/flags.md

    rb067d9b r7951100  
    6060        ```
    6161        FunFlags f = some_val();
    62         if ( f ) { sout | "f has some flag(s) set"; }
    63         if ( f & FOO ) { sout | "f has FOO set"; }
     62        if ( f ) { sout | "f has some flag(s) set" | endl; }
     63        if ( f & FOO ) { sout | "f has FOO set" | endl; }
    6464        f |= FOO; // set FOO
    6565        f -= FOO; // unset FOO
     
    8888        ```
    8989        FunFlags f = some_val();
    90         if ( f.FOO ) { sout | "f has FOO set"; }
     90        if ( f.FOO ) { sout | "f has FOO set" | endl; }
    9191        f.FOO = true;    // set FOO
    9292        f.FOO = false;   // unset FOO
  • doc/proposals/tuples/Makefile

    rb067d9b r7951100  
    1 ## Define the configuration variables.
     1## Define the appropriate configuration variables.
    22
    3 Build = build
    4 Figures = figures
    5 Macros = ../../LaTeXmacros
    6 Bib = ../../bibliography
     3MACROS = ../../LaTeXmacros
     4BIB = ../../bibliography
    75
    8 TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
    9 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
     6TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
     7LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
    108BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
    11 
    12 MAKEFLAGS = --no-print-directory --silent #
    13 VPATH = ${Build} ${Figures}
    149
    1510## Define the text source files.
     
    3429
    3530DOCUMENT = tuples.pdf
    36 BASE = ${basename ${DOCUMENT}}
    3731
    3832# Directives #
    39 
    40 .PHONY : all clean                                      # not file names
    4133
    4234all : ${DOCUMENT}
    4335
    4436clean :
    45         @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
     37        rm -f *.bbl *.aux *.dvi *.idx *.ilg *.ind *.brf *.out *.log *.toc *.blg *.pstex_t *.cf \
     38                ${FIGURES} ${PICTURES} ${PROGRAMS} ${GRAPHS} ${basename ${DOCUMENT}}.ps ${DOCUMENT}
    4639
    4740# File Dependencies #
    4841
    49 ${DOCUMENT} : ${BASE}.ps
     42${DOCUMENT} : ${basename ${DOCUMENT}}.ps
    5043        ps2pdf $<
    5144
    52 ${BASE}.ps : ${BASE}.dvi
    53         dvips ${Build}/$< -o $@
     45${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     46        dvips $< -o $@
    5447
    55 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
     48${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
     49                $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
    5750        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    58         #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     51        if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
    5952        # Must have *.aux file containing citations for bibtex
    6053        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    61         -${BibTeX} ${Build}/${basename $@}
    62         # Some citations reference others so run again to resolve these citations
     54        -${BibTeX} ${basename $@}
     55        # Some citations reference others so run steps again to resolve these citations
    6356        ${LaTeX} ${basename $@}.tex
    64         -${BibTeX} ${Build}/${basename $@}
     57        -${BibTeX} ${basename $@}
    6558        # Make index from *.aux entries and input index at end of document
    66         #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
    67         # Run again to finish citations
     59        makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
    6860        ${LaTeX} ${basename $@}.tex
    6961        # Run again to get index title into table of contents
     
    7567## Define the default recipes.
    7668
    77 ${Build}:
    78         mkdir -p ${Build}
     69%.tex : %.fig
     70        fig2dev -L eepic $< > $@
    7971
    80 %.tex : %.fig | ${Build}
    81         fig2dev -L eepic $< > ${Build}/$@
     72%.ps : %.fig
     73        fig2dev -L ps $< > $@
    8274
    83 %.ps : %.fig | ${Build}
    84         fig2dev -L ps $< > ${Build}/$@
    85 
    86 %.pstex : %.fig | ${Build}
    87         fig2dev -L pstex $< > ${Build}/$@
    88         fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
     75%.pstex : %.fig
     76        fig2dev -L pstex $< > $@
     77        fig2dev -L pstex_t -p $@ $< > $@_t
    8978
    9079# Local Variables: #
  • doc/proposals/tuples/tuples.tex

    rb067d9b r7951100  
     1% inline code ©...© (copyright symbol) emacs: C-q M-)
     2% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     3% blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
     4% green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
     5% LaTex escape §...§ (section symbol) emacs: C-q M-'
     6% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     7% math escape $...$ (dollar symbol)
     8
    19\documentclass[twoside,11pt]{article}
    210
     
    715\usepackage{textcomp}
    816\usepackage[latin1]{inputenc}
    9 
    1017\usepackage{fullpage,times,comment}
    1118\usepackage{epic,eepic}
    12 \usepackage{upquote}                                    % switch curled `'" to straight
     19\usepackage{upquote}                                                                    % switch curled `'" to straight
    1320\usepackage{calc}
    1421\usepackage{xspace}
    1522\usepackage{graphicx}
    16 \usepackage{varioref}                                   % extended references
    17 \usepackage{listings}                                   % format program code
    18 \usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
     23\usepackage{varioref}                                                                   % extended references
     24\usepackage{listings}                                                                   % format program code
     25\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    1926\usepackage{latexsym}                                   % \Box glyph
    2027\usepackage{mathptmx}                                   % better math font with "times"
     
    2734\renewcommand{\UrlFont}{\small\sf}
    2835
    29 \setlength{\topmargin}{-0.45in}                         % move running title into header
     36\setlength{\topmargin}{-0.45in}                                                 % move running title into header
    3037\setlength{\headsep}{0.25in}
    3138
     
    3542
    3643\interfootnotelinepenalty=10000
    37 
    38 \CFAStyle                                               % use default CFA format-style
    39 % inline code ©...© (copyright symbol) emacs: C-q M-)
    40 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    41 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    42 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    43 % LaTex escape §...§ (section symbol) emacs: C-q M-'
    44 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    45 % math escape $...$ (dollar symbol)
    46 
    4744
    4845\title{
  • doc/proposals/user_conversions.md

    rb067d9b r7951100  
    55There is also a set of _explicit_ conversions that are only allowed through a
    66cast expression.
    7 I propose that safe, unsafe, and explicit (cast) conversions be expressed as
    8 constructor variants.
     7Based on Glen's notes on conversions [1], I propose that safe and unsafe
     8conversions be expressed as constructor variants, though I make explicit
     9(cast) conversions a constructor variant as well rather than a dedicated
     10operator.
    911Throughout this article, I will use the following operator names for
    1012constructors and conversion functions from `From` to `To`:
    1113
    12         void ?{} ( To&, To );            // copy constructor
    13         void ?{} ( To&, From );          // explicit constructor
    14         void ?{explicit} ( To&, From );  // explicit cast conversion
    15         void ?{safe} ( To&, From );      // implicit safe conversion
    16         void ?{unsafe} ( To&, From );    // implicit unsafe conversion
    17 
    18 It has been suggested that all constructors would define unsafe implicit
     14        void ?{} ( To*, To );            // copy constructor
     15        void ?{} ( To*, From );          // explicit constructor
     16        void ?{explicit} ( To*, From );  // explicit cast conversion
     17        void ?{safe} ( To*, From );      // implicit safe conversion
     18        void ?{unsafe} ( To*, From );    // implicit unsafe conversion
     19
     20[1] http://plg.uwaterloo.ca/~cforall/Conversions/index.html
     21
     22Glen's design made no distinction between constructors and unsafe implicit
    1923conversions; this is elegant, but interacts poorly with tuples.
    2024Essentially, without making this distinction, a constructor like the following
     
    2226multiplying the space of possible interpretations of all functions:
    2327
    24         void ?{}( Coord& this, int x, int y );
     28        void ?{}( Coord *this, int x, int y );
    2529
    2630That said, it would certainly be possible to make a multiple-argument implicit
     
    2832used infrequently:
    2933
    30         void ?{unsafe}( Coord& this, int x, int y );
     34        void ?{unsafe}( Coord *this, int x, int y );
    3135
    3236An alternate possibility would be to only count two-arg constructors
    33 `void ?{} ( To&, From )` as unsafe conversions; under this semantics, safe and
     37`void ?{} ( To*, From )` as unsafe conversions; under this semantics, safe and
    3438explicit conversions should also have a compiler-enforced restriction to
    3539ensure that they are two-arg functions (this restriction may be valuable
     
    3943is convertable to `To`.
    4044If user-defined conversions are not added to the language,
    41 `void ?{} ( To&, From )` may be a suitable representation, relying on
     45`void ?{} ( To*, From )` may be a suitable representation, relying on
    4246conversions on the argument types to account for transitivity.
    43 Since `To&` should be an exact match on `To`, this should put all the implicit
    44 conversions on the RHS.
    45 On the other hand, under some models (like [1]), implicit conversions are not
    46 allowed in assertion parameters, so another assertion syntax specific to
    47 conversions may be required, e.g. `From -> To`.
    48 It has also been suggested that, for programmer control, no implicit
    49 conversions (except, possibly, for polymorphic specialization) should be
    50 allowed in resolution of cast operators.
    51 
    52 [1] ../working/assertion_resolution.md
     47On the other hand, `To*` should perhaps match its target type exactly, so
     48another assertion syntax specific to conversions may be required, e.g.
     49`From -> To`.
    5350
    5451### Constructor Idiom ###
     
    5653that we can use the full range of Cforall features for conversions, including
    5754polymorphism.
    58 In an earlier version of this proposal, Glen Ditchfield defines a
    59 _constructor idiom_ that can be used to create chains of safe conversions
    60 without duplicating code; given a type `Safe` which members of another type
    61 `From` can be directly converted to, the constructor idiom allows us to write
    62 a conversion for any type `To` which `Safe` converts to:
    63 
    64         forall(otype To | { void ?{safe}( To&, Safe ) })
    65         void ?{safe}( To& this, From that ) {
     55Glen [1] defines a _constructor idiom_ that can be used to create chains of
     56safe conversions without duplicating code; given a type `Safe` which members
     57of another type `From` can be directly converted to, the constructor idiom
     58allows us to write a conversion for any type `To` which `Safe` converts to:
     59
     60        forall(otype To | { void ?{safe}( To*, Safe ) })
     61        void ?{safe}( To *this, From that ) {
    6662                Safe tmp = /* some expression involving that */;
    67                 this{ tmp }; // initialize from assertion parameter
     63                *this = tmp; // uses assertion parameter
    6864        }
    6965
     
    7167unsafe conversions.
    7268
    73 Glen's original suggestion said the copy constructor for `To` should also be
    74 accepted as a resolution for `void ?{safe}( To&, Safe )` (`Safe` == `To`),
    75 allowing this same code to be used for the single-step conversion as well.
    76 This proposal does come at the cost of an extra copy initialization of the
    77 target value, though.
    78 
    79 Contrariwise, if a monomorphic conversion from `From` to `Safe` is written,
    80 e.g:
    81 
    82         void ?{safe}( Safe& this, From that ) {
    83                 this{ /* some parameters involving that */ };
    84         }
    85 
    86 Then the code for a transitive conversion from `From` to any `To` type
    87 convertable from `Safe` is written:
    88 
    89         forall(otype To | { void ?{safe}( To&, Safe ) })
    90         void ?{safe}( To& this, From that ) {
    91                 Safe tmp = that;  // uses monomorphic conversion
    92                 this{ tmp };      // initialize from assertion parameter
    93         }
    94 
    95 Given the entirely-boilerplate nature of this code, but negative performance
    96 implications of the unmodified constructor idiom, it might be fruitful to have
    97 transitive and single step conversion operators, and let CFA build the
    98 transitive conversions; some possible names:
    99 
    100         void ?{safe}  (To&, From);    void ?{final safe} (To&, From);  // single-step
    101         void ?{safe*} (To&, From);    void ?{safe}       (To&, From);  // transitive
    102 
    10369What selective non-use of the constructor idiom gives us is the ability to
    10470define a conversion that may only be the *last* conversion in a chain of such.
    105 One use for this is to solve the problem that `explicit` conversions were
    106 added to C++ for, that of conversions to `bool` chaining to become conversions
    107 to any arithmetic type.
    108 Another use is to unambiguously represent the full hierarchy of implicit
    109 conversions in C by making sign conversions non-transitive, allowing the
    110 compiler to resolve e.g. `int -> unsigned long` as
    111 `int -> long -> unsigned long` over `int -> unsigned int -> unsigned long`.
    112 See [2] for more details.
    113 
    114 [2] ../working/glen_conversions/index.html#usual
     71Constructing a conversion graph able to unambiguously represent the full
     72hierarchy of implicit conversions in C is provably impossible using only
     73single-step conversions with no additional information (see Appendix A), but
     74this mechanism is sufficiently powerful (see [1], though the design there has
     75some minor bugs; the general idea is to use the constructor idiom to define
     76two chains of conversions, one among the signed integral types, another among
     77the unsigned, and to use monomorphic conversions to allow conversions between
     78signed and unsigned integer types).
    11579
    11680### Appendix A: Partial and Total Orders ###
     
    189153convert from `int` to `unsigned long`, so we just put in a direct conversion
    190154and make the compiler smart enough to figure out the costs" - this is the
    191 approach taken by the existing compiler, but given that in a user-defined
     155approach taken by the existing compipler, but given that in a user-defined
    192156conversion proposal the users can build an arbitrary graph of conversions,
    193157this case still needs to be handled.
     
    196160exists a chain of conversions from `a` to `b` (see Appendix A for description
    197161of preorders and related constructs).
    198 This preorder roughly corresponds to a more usual type-theoretic concept of
     162This preorder corresponds roughly to a more usual type-theoretic concept of
    199163subtyping ("if I can convert `a` to `b`, `a` is a more specific type than
    200164`b`"); however, since this graph is arbitrary, it may contain cycles, so if
     
    228192and so is considered to be the nearer type.
    229193By transitivity, then, the conversion from `X` to `Y2` should be cheaper than
    230 the conversion from `X` to `W`, but in this case the `Y2` and `W` are
     194the conversion from `X` to `W`, but in this case the `X` and `W` are
    231195incomparable by the conversion preorder, so the tie is broken by the shorter
    232196path from `X` to `W` in favour of `W`, contradicting the transitivity property
  • doc/refrat/Makefile

    rb067d9b r7951100  
    5353        dvips ${Build}/$< -o $@
    5454
    55 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib | ${Build}
     55${BASE}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib
    5757        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    5858        if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     
    7878        mkdir -p ${Build}
    7979
    80 %.tex : %.fig | ${Build}
     80%.tex : %.fig ${Build}
    8181        fig2dev -L eepic $< > ${Build}/$@
    8282
    83 %.ps : %.fig | ${Build}
     83%.ps : %.fig ${Build}
    8484        fig2dev -L ps $< > ${Build}/$@
    8585
    86 %.pstex : %.fig | ${Build}
     86%.pstex : %.fig ${Build}
    8787        fig2dev -L pstex $< > ${Build}/$@
    8888        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/user/Makefile

    rb067d9b r7951100  
    44Figures = figures
    55Macros = ../LaTeXmacros
    6 TeXLIB = .:${Macros}:${Build}:
     6TeXLIB = .:${Macros}:${Build}:../bibliography:
    77LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    8 BibTeX = BIBINPUTS=../bibliography: && export BIBINPUTS && bibtex
     8BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
    99
    1010MAKEFLAGS = --no-print-directory --silent #
     
    5151# File Dependencies #
    5252
    53 build/version: ../../configure | ${Build}
    54         ../../configure --version | grep "cfa-cc configure" | grep -oEe "([0-9]+\.)+[0-9]+" > $@
    55 
    5653${DOCUMENT} : ${BASE}.ps
    5754        ps2pdf $<
     
    6057        dvips ${Build}/$< -o $@
    6158
    62 ${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    63                 ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib build/version | ${Build}
     59${BASE}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     60                ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib
    6461        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    6562        if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
     
    7976## Define the default recipes.
    8077
    81 ${Build} :
     78${Build}:
    8279        mkdir -p ${Build}
    8380
    84 %.tex : %.fig | ${Build}
     81%.tex : %.fig ${Build}
    8582        fig2dev -L eepic $< > ${Build}/$@
    8683
    87 %.ps : %.fig | ${Build}
     84%.ps : %.fig ${Build}
    8885        fig2dev -L ps $< > ${Build}/$@
    8986
    90 %.pstex : %.fig | ${Build}
     87%.pstex : %.fig ${Build}
    9188        fig2dev -L pstex $< > ${Build}/$@
    9289        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/user/user.tex

    rb067d9b r7951100  
    11%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2 %%
     2%% 
    33%% Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    44%%
    55%% The contents of this file are covered under the licence agreement in the
    66%% file "LICENCE" distributed with Cforall.
    7 %%
    8 %% user.tex --
    9 %%
     7%% 
     8%% user.tex -- 
     9%% 
    1010%% Author           : Peter A. Buhr
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sat Jul 13 18:36:18 2019
    14 %% Update Count     : 3876
     13%% Last Modified On : Sun May  6 10:33:53 2018
     14%% Update Count     : 3319
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    7272
    7373% Names used in the document.
    74 \newcommand{\Version}{\input{build/version}}
     74\newcommand{\Version}{\input{../../version}}
    7575\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    7676\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
     
    146146\CFA adds many modern programming-language features that directly lead to increased \emph{\Index{safety}} and \emph{\Index{productivity}}, while maintaining interoperability with existing C programs and achieving similar performance.
    147147Like C, \CFA is a statically typed, procedural (non-\Index{object-oriented}) language with a low-overhead runtime, meaning there is no global \Index{garbage-collection}, but \Index{regional garbage-collection}\index{garbage-collection!regional} is possible.
    148 The primary new features include polymorphic routines and types, exceptions, concurrency, and modules.
     148The primary new features include parametric-polymorphic routines and types, exceptions, concurrency, and modules.
    149149
    150150One of the main design philosophies of \CFA is to ``\Index{describe not prescribe}'', which means \CFA tries to provide a pathway from low-level C programming to high-level \CFA programming, but it does not force programmers to ``do the right thing''.
     
    155155As well, new programs can be written in \CFA using a combination of C and \CFA features.
    156156
    157 \Index*[C++]{\CC{}}~\cite{c++:v1} had a similar goal 30 years ago, allowing object-oriented programming to be incrementally added to C.
    158 However, \CC currently has the disadvantages of a strong object-oriented bias, multiple legacy design-choices that cannot be updated, and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project.
     157\Index*[C++]{\CC{}} had a similar goal 30 years ago, allowing object-oriented programming to be incrementally added to C.
     158However, \CC currently has the disadvantages of a strong object-oriented bias, multiple legacy design-choices that cannot be updated, and active divergence of the language model from C, all of which requires significant effort and training to incrementally add \CC to a C-based project.
    159159In contrast, \CFA has 30 years of hindsight and a clean starting point.
    160160
    161161Like \Index*[C++]{\CC{}}, there may be both an old and new ways to achieve the same effect.
    162 For example, the following programs compare the C, \CFA, and \CC I/O mechanisms, where the programs output the same result.
    163 \begin{center}
     162For example, the following programs compare the \CFA, C, and \CC I/O mechanisms, where the programs output the same result.
     163\begin{cquote}
    164164\begin{tabular}{@{}l@{\hspace{1.5em}}l@{\hspace{1.5em}}l@{}}
    165165\multicolumn{1}{c@{\hspace{1.5em}}}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{\CC}}      \\
     
    178178int main( void ) {
    179179        int x = 0, y = 1, z = 2;
    180         ®sout | x | y | z;®§\indexc{sout}§
     180        ®sout | x | y | z | endl;®§\indexc{sout}§
    181181}
    182182\end{cfa}
     
    191191\end{cfa}
    192192\end{tabular}
    193 \end{center}
     193\end{cquote}
    194194While the \CFA I/O looks similar to the \Index*[C++]{\CC{}} output style, there are important differences, such as automatic spacing between variables as in \Index*{Python} (see~\VRef{s:IOLibrary}).
    195195
    196 
    197196\subsection{Background}
    198197
    199198This document is a programmer reference-manual for the \CFA programming language.
    200 The manual covers the core features of the language and runtime-system, with simple examples illustrating syntax and semantics of features.
     199The manual covers the core features of the language and runtime-system, with simple examples illustrating syntax and semantics of each feature.
    201200The manual does not teach programming, \ie how to combine the new constructs to build complex programs.
    202 The reader must have an intermediate knowledge of control flow, data structures, and concurrency issues to understand the ideas presented, as well as some experience programming in C/\CC.
     201A reader should already have an intermediate knowledge of control flow, data structures, and concurrency issues to understand the ideas presented, as well as some experience programming in C/\CC.
    203202Implementers should refer to the \CFA Programming Language Specification for details about the language syntax and semantics.
    204203Changes to the syntax and additional features are expected to be included in later revisions.
     
    207206\section{Why fix C?}
    208207
    209 The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from hobby projects to commercial operating-systems.
     208The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems (especially UNIX systems) to hobby projects.
    210209This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    211210Even with all its problems, C continues to be popular because it allows writing software at virtually any level in a computer system without restriction.
    212211For system programming, where direct access to hardware, storage management, and real-time issues are a requirement, C is usually the only language of choice.
    213 The TIOBE index~\cite{TIOBE} for July 2018 ranks the top five most \emph{popular} programming languages as \Index*{Java} 16\%, C 14\%, \Index*[C++]{\CC{}} 7.5\%, Python 6\%, Visual Basic 4\% = 47.5\%, where the next 50 languages are less than 4\% each, with a long tail.
    214 The top 3 rankings over the past 30 years are:
     212The TIOBE index~\cite{TIOBE} for March 2016 showed the following programming-language popularity: \Index*{Java} 20.5\%, C 14.5\%, \Index*[C++]{\CC{}} 6.7\%, \Csharp 4.3\%, \Index*{Python} 4.3\%, where the next 50 languages are less than 3\% each with a long tail.
     213As well, for 30 years, C has been the number 1 and 2 most popular programming language:
    215214\begin{center}
    216 \setlength{\tabcolsep}{10pt}
    217 \begin{tabular}{@{}rccccccc@{}}
    218                 & 2018  & 2013  & 2008  & 2003  & 1998  & 1993  & 1988  \\ \hline
    219 Java    & 1             & 2             & 1             & 1             & 16    & -             & -             \\
    220 \R{C}   & \R{2} & \R{1} & \R{2} & \R{2} & \R{1} & \R{1} & \R{1} \\
    221 \CC             & 3             & 4             & 3             & 3             & 2             & 2             & 5             \\
     215\setlength{\tabcolsep}{1.5ex}
     216\begin{tabular}{@{}r|c|c|c|c|c|c|c@{}}
     217Ranking & 2016  & 2011  & 2006  & 2001  & 1996  & 1991  & 1986          \\
     218\hline
     219Java    & 1             & 1             & 1             & 3             & 29    & -             & -                     \\
     220\hline
     221\R{C}   & \R{2} & \R{2} & \R{2} & \R{1} & \R{1} & \R{1} & \R{1}         \\
     222\hline
     223\CC             & 3             & 3             & 3             & 2             & 2             & 2             & 7                     \\
    222224\end{tabular}
    223225\end{center}
    224226Hence, C is still an extremely important programming language, with double the usage of \Index*[C++]{\CC{}}; in many cases, \CC is often used solely as a better C.
    225227Love it or hate it, C has been an important and influential part of computer science for 40 years and its appeal is not diminishing.
    226 Nevertheless, C has many problems and omissions that make it an unacceptable programming language for modern needs.
     228Unfortunately, C has many problems and omissions that make it an unacceptable programming language for modern needs.
    227229
    228230As stated, the goal of the \CFA project is to engineer modern language-features into C in an evolutionary rather than revolutionary way.
     
    234236These languages have different syntax and semantics from C, do not interoperate directly with C, and are not systems languages because of restrictive memory-management or garbage collection.
    235237As a result, there is a significant learning curve to move to these languages, and C legacy-code must be rewritten.
    236 These costs can be prohibitive for many companies with a large software-base in C/\CC, and a significant number of programmers require retraining in the new programming language.
    237 
    238 The result of this project is a language that is largely backwards compatible with \Index*[C11]{\Celeven{}}~\cite{C11}, but fixes many of the well known C problems while adding modern language-features.
    239 To achieve these goals required a significant engineering exercise, where we had to ``think inside the existing C box''.
    240 Without these significant extension to C, it is unable to cope with the needs of modern programming problems and programmers;
     238These costs can be prohibitive for many companies with a large software-base in C/\CC, and a significant number of programmers require retraining to the new programming language.
     239
     240The result of this project is a language that is largely backwards compatible with \Index*[C11]{\Celeven{}}~\cite{C11}, but fixes many of the well known C problems while containing modern language-features.
     241Without significant extension to the C programming language, it is becoming unable to cope with the needs of modern programming problems and programmers;
    241242as a result, it will fade into disuse.
    242243Considering the large body of existing C code and programmers, there is significant impetus to ensure C is transformed into a modern programming language.
     
    254255\begin{lstlisting}
    255256®forall( otype T )® T identity( T val ) { return val; }
    256 int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
     257int forty_two = identity( 42 );                 §\C{// T is bound to int, forty\_two == 42}§
    257258\end{lstlisting}
    258259% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
     
    282283
    283284double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    284 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
     285double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp );      §\C{// search sorted array}§
    285286\end{lstlisting}
    286287which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
     
    291292
    292293forall( otype T | { int ?<?( T, T ); } ) unsigned int bsearch( T key, const T * arr, size_t size ) {
    293         T * result = bsearch( key, arr, size ); §\C{// call first version}§
    294         return result ? result - arr : size; } §\C{// pointer subtraction includes sizeof(T)}§
    295 
    296 double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
     294        T * result = bsearch( key, arr, size ); §\C{// call first version}§
     295        return result ? result - arr : size; }  §\C{// pointer subtraction includes sizeof(T)}§
     296
     297double * val = bsearch( 5.0, vals, 10 );        §\C{// selection based on return type}§
    297298int posn = bsearch( 5.0, vals, 10 );
    298299\end{lstlisting}
     
    306307\begin{lstlisting}
    307308forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    308 int * ip = malloc(); §\C{// select type and size from left-hand side}§
     309int * ip = malloc();                                    §\C{// select type and size from left-hand side}§
    309310double * dp = malloc();
    310311struct S {...} * sp = malloc();
     
    317318Whereas, \CFA wraps each of these routines into ones with the overloaded name ©abs©:
    318319\begin{cfa}
    319 char ®abs®( char );
    320 extern "C" { int ®abs®( int ); } §\C{// use default C routine for int}§
    321 long int ®abs®( long int );
    322 long long int ®abs®( long long int );
    323 float ®abs®( float );
    324 double ®abs®( double );
    325 long double ®abs®( long double );
    326 float _Complex ®abs®( float _Complex );
    327 double _Complex ®abs®( double _Complex );
    328 long double _Complex ®abs®( long double _Complex );
     320char abs( char );
     321®extern "C" {® int abs( int ); ®}®              §\C{// use default C routine for int}§
     322long int abs( long int );
     323long long int abs( long long int );
     324float abs( float );
     325double abs( double );
     326long double abs( long double );
     327float _Complex abs( float _Complex );
     328double _Complex abs( double _Complex );
     329long double _Complex abs( long double _Complex );
    329330\end{cfa}
    330331The problem is the name clash between the library routine ©abs© and the \CFA names ©abs©.
    331332Hence, names appearing in an ©extern "C"© block have \newterm*{C linkage}.
    332333Then overloading polymorphism uses a mechanism called \newterm{name mangling}\index{mangling!name} to create unique names that are different from C names, which are not mangled.
    333 Hence, there is the same need, as in \CC, to know if a name is a C or \CFA name, so it can be correctly formed.
    334 There is no way around this problem, other than C's approach of creating unique names for each pairing of operation and types.
     334Hence, there is the same need as in \CC, to know if a name is a C or \CFA name, so it can be correctly formed.
     335There is no way around this problem, other than C's approach of creating unique names for each pairing of operation and type.
    335336
    336337This example strongly illustrates a core idea in \CFA: \emph{the \Index{power of a name}}.
     
    349350\begin{description}
    350351\item
    351 \Indexc{-std=gnu11}\index{compilation option!-std=gnu11@{©-std=gnu11©}}
    352 The 2011 C standard plus GNU extensions.
    353 \item
    354 \Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline]$-fgnu89-inline$}}
    355 Use the traditional GNU semantics for inline routines in C11 mode, which allows inline routines in header files.
     352\Indexc{-std=gnu99}\index{compilation option!-std=gnu99@{©-std=gnu99©}}
     353The 1999 C standard plus GNU extensions.
     354\item
     355\Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline]@-fgnu89-inline@}}
     356Use the traditional GNU semantics for inline routines in C99 mode, which allows inline routines in header files.
    356357\end{description}
    357358The following new \CFA options are available:
     
    426427\begin{cfa}
    427428#ifndef __CFORALL__
    428 #include <stdio.h>§\indexc{stdio.h}§ §\C{// C header file}§
     429#include <stdio.h>§\indexc{stdio.h}§    §\C{// C header file}§
    429430#else
    430 #include <fstream>§\indexc{fstream}§ §\C{// \CFA header file}§
     431#include <fstream>§\indexc{fstream}§    §\C{// \CFA header file}§
    431432#endif
    432433\end{cfa}
    433 which conditionally includes the correct header file, if the program is compiled using \Indexc{gcc} or \Indexc{cfa}.
    434 
    435 The \CFA translator has multiple steps.
    436 The following flags control how the tranlator works, the stages run, and printing within a stage.
    437 The majority of these flags are used by \CFA developers, but some are occasionally useful to programmers.
    438 \begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt]
    439 \item
    440 \Indexc{-h}\index{translator option!-h@{©-h©}}, \Indexc{--help}\index{translator option!--help@{©--help©}} \, print help message
    441 \item
    442 \Indexc{-l}\index{translator option!-l@{©-l©}}, \Indexc{--libcfa}\index{translator option!--libcfa@{©--libcfa©}} \, generate libcfa.c
    443 \item
    444 \Indexc{-L}\index{translator option!-L@{©-L©}}, \Indexc{--linemarks}\index{translator option!--linemarks@{©--linemarks©}} \, generate line marks
    445 \item
    446 \Indexc{-m}\index{translator option!-m@{©-m©}}, \Indexc{--no-main}\index{translator option!--no-main@{©--no-main©}} \, do not replace main
    447 \item
    448 \Indexc{-N}\index{translator option!-N@{©-N©}}, \Indexc{--no-linemarks}\index{translator option!--no-linemarks@{©--no-linemarks©}} \, do not generate line marks
    449 \item
    450 \Indexc{-n}\index{translator option!-n@{©-n©}}, \Indexc{--no-prelude}\index{translator option!--no-prelude@{©--no-prelude©}} \, do not read prelude
    451 \item
    452 \Indexc{-p}\index{translator option!-p@{©-p©}}, \Indexc{--prototypes}\index{translator option!--prototypes@{©--prototypes©}} \, generate prototypes for prelude functions
    453 \item
    454 \Indexc{-P}\index{translator option!-P@{©-P©}}, \Indexc{--print}\index{translator option!--print@{©--print©}} \, one of:
    455 \begin{description}[topsep=0pt,itemsep=0pt,parsep=0pt]
    456 \item
    457 \Indexc{altexpr}\index{translator option!-P@{©-P©}!©altexpr©}\index{translator option!--print@{©-print©}!©altexpr©} \, alternatives for expressions
    458 \item
    459 \Indexc{ascodegen}\index{translator option!-P@{©-P©}!©ascodegen©}\index{translator option!--print@{©-print©}!©ascodegen©} \, as codegen rather than AST
    460 \item
    461 \Indexc{ast}\index{translator option!-P@{©-P©}!©ast©}\index{translator option!--print@{©-print©}!©ast©} \, AST after parsing
    462 \item
    463 \Indexc{astdecl}\index{translator option!-P@{©-P©}!©astdecl©}\index{translator option!--print@{©-print©}!©astdecl©} \, AST after declaration validation pass
    464 \item
    465 \Indexc{asterr}\index{translator option!-P@{©-P©}!©asterr©}\index{translator option!--print@{©-print©}!©asterr©} \, AST on error
    466 \item
    467 \Indexc{astexpr}\index{translator option!-P@{©-P©}!©astexpr©}\index{translator option!--print@{©-print©}!©altexpr©} \, AST after expression analysis
    468 \item
    469 \Indexc{astgen}\index{translator option!-P@{©-P©}!©astgen©}\index{translator option!--print@{©-print©}!©astgen©} \, AST after instantiate generics
    470 \item
    471 \Indexc{box}\index{translator option!-P@{©-P©}!©box©}\index{translator option!--print@{©-print©}!©box©} \, before box step
    472 \item
    473 \Indexc{ctordtor}\index{translator option!-P@{©-P©}!©ctordtor©}\index{translator option!--print@{©-print©}!©ctordtor©} \, after ctor/dtor are replaced
    474 \item
    475 \Indexc{codegen}\index{translator option!-P@{©-P©}!©codegen©}\index{translator option!--print@{©-print©}!©codegen©} \, before code generation
    476 \item
    477 \Indexc{declstats}\index{translator option!-P@{©-P©}!©declstats©}\index{translator option!--print@{©-print©}!©declstats©} \, code property statistics
    478 \item
    479 \Indexc{parse}\index{translator option!-P@{©-P©}!©parse©}\index{translator option!--print@{©-print©}!©parse©} \, yacc (parsing) debug information
    480 \item
    481 \Indexc{pretty}\index{translator option!-P@{©-P©}!©pretty©}\index{translator option!--print@{©-print©}!©pretty©} \, prettyprint for ascodegen flag
    482 \item
    483 \Indexc{resolver}\index{translator option!-P@{©-P©}!©resolver©}\index{translator option!--print@{©-print©}!©resolver©} \, before resolver step
    484 \item
    485 \Indexc{rproto}\index{translator option!-P@{©-P©}!©rproto©}\index{translator option!--print@{©-print©}!©rproto©} \, resolver-proto instance
    486 \item
    487 \Indexc{rsteps}\index{translator option!-P@{©-P©}!©rsteps©}\index{translator option!--print@{©-print©}!©rsteps©} \, resolver steps
    488 \item
    489 \Indexc{symevt}\index{translator option!-P@{©-P©}!©symevt©}\index{translator option!--print@{©-print©}!©symevt©} \, symbol table events
    490 \item
    491 \Indexc{tree}\index{translator option!-P@{©-P©}!©tree©}\index{translator option!--print@{©-print©}!©tree©} \, parse tree
    492 \item
    493 \Indexc{tuple}\index{translator option!-P@{©-P©}!©tuple©}\index{translator option!--print@{©-print©}!©tuple©} \, after tuple expansion
    494 \end{description}
    495 \item
    496 \Indexc{--prelude-dir} <directory> \, prelude directory for debug/nodebug
    497 \item
    498 \Indexc{-S}\index{translator option!-S@{©-S©}!©counters,heap,time,all,none©}, \Indexc{--statistics}\index{translator option!--statistics@{©--statistics©}!©counters,heap,time,all,none©} <option-list> \, enable profiling information:
    499 \begin{description}[topsep=0pt,itemsep=0pt,parsep=0pt]
    500 \item
    501 \Indexc{counters,heap,time,all,none}
    502 \end{description}
    503 \item
    504 \Indexc{-t}\index{translator option!-t@{©-t©}}, \Indexc{--tree}\index{translator option!--tree@{©--tree©}} build in tree
    505 \end{description}
    506 
    507 
    508 \section{Backquote Identifiers}
    509 \label{s:BackquoteIdentifiers}
    510 
    511 \CFA introduces several new keywords (see \VRef{s:CFAKeywords}) that can clash with existing C variable-names in legacy code.
    512 Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism:
    513 \begin{cfa}
    514 int ®`®otype®`® = 3; §\C{// make keyword an identifier}§
    515 double ®`®forall®`® = 3.5;
    516 \end{cfa}
    517 
    518 Existing C programs with keyword clashes can be converted by enclosing keyword identifiers in backquotes, and eventually the identifier name can be changed to a non-keyword name.
    519 \VRef[Figure]{f:HeaderFileInterposition} shows how clashes in existing C header-files (see~\VRef{s:StandardHeaders}) can be handled using preprocessor \newterm{interposition}: ©#include_next© and ©-I filename©.
    520 Several common C header-files with keyword clashes are fixed in the standard \CFA header-library, so there is a seamless programming-experience.
    521 
    522 \begin{figure}
    523 \begin{cfa}
    524 // include file uses the CFA keyword "with".
    525 #if ! defined( with ) §\C{// nesting ?}§
    526 #define with ®`®with®`® §\C{// make keyword an identifier}§
    527 #define __CFA_BFD_H__
    528 #endif
    529 
    530 ®#include_next <bfdlink.h> §\C{// must have internal check for multiple expansion}§
    531 ®
    532 #if defined( with ) && defined( __CFA_BFD_H__ ) §\C{// reset only if set}§
    533 #undef with
    534 #undef __CFA_BFD_H__
    535 #endif
    536 \end{cfa}
    537 \caption{Header-File Interposition}
    538 \label{f:HeaderFileInterposition}
    539 \end{figure}
     434which conditionally includes the correct header file, if the program is compiled using \Indexc{gcc} or \Indexc{cfa}.
    540435
    541436
     
    544439Numeric constants are extended to allow \Index{underscore}s\index{constant!underscore}, \eg:
    545440\begin{cfa}
    546 2®_®147®_®483®_®648; §\C{// decimal constant}§
    547 56®_®ul; §\C{// decimal unsigned long constant}§
    548 0®_®377; §\C{// octal constant}§
    549 0x®_®ff®_®ff; §\C{// hexadecimal constant}§
    550 0x®_®ef3d®_®aa5c; §\C{// hexadecimal constant}§
    551 3.141®_®592®_®654; §\C{// floating constant}§
    552 10®_®e®_®+1®_®00; §\C{// floating constant}§
    553 0x®_®ff®_®ff®_®p®_®3; §\C{// hexadecimal floating}§
    554 0x®_®1.ffff®_®ffff®_®p®_®128®_®l; §\C{// hexadecimal floating long constant}§
    555 L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§; §\C{// wide character constant}§
     4412®_®147®_®483®_®648;                                    §\C{// decimal constant}§
     44256®_®ul;                                                                §\C{// decimal unsigned long constant}§
     4430®_®377;                                                                §\C{// octal constant}§
     4440x®_®ff®_®ff;                                                   §\C{// hexadecimal constant}§
     4450x®_®ef3d®_®aa5c;                                               §\C{// hexadecimal constant}§
     4463.141®_®592®_®654;                                              §\C{// floating constant}§
     44710®_®e®_®+1®_®00;                                               §\C{// floating constant}§
     4480x®_®ff®_®ff®_®p®_®3;                                   §\C{// hexadecimal floating}§
     4490x®_®1.ffff®_®ffff®_®p®_®128®_®l;               §\C{// hexadecimal floating long constant}§
     450L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§;     §\C{// wide character constant}§
    556451\end{cfa}
    557452The rules for placement of underscores are:
     
    574469
    575470
     471\section{Backquote Identifiers}
     472\label{s:BackquoteIdentifiers}
     473
     474\CFA introduces several new keywords (see \VRef{s:CFAKeywords}) that can clash with existing C variable-names in legacy code.
     475Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism:
     476\begin{cfa}
     477int ®`®otype®`® = 3;                    §\C{// make keyword an identifier}§
     478double ®`®forall®`® = 3.5;
     479\end{cfa}
     480
     481Existing C programs with keyword clashes can be converted by enclosing keyword identifiers in backquotes, and eventually the identifier name can be changed to a non-keyword name.
     482\VRef[Figure]{f:HeaderFileInterposition} shows how clashes in existing C header-files (see~\VRef{s:StandardHeaders}) can be handled using preprocessor \newterm{interposition}: ©#include_next© and ©-I filename©.
     483Several common C header-files with keyword clashes are fixed in the standard \CFA header-library, so there is a seamless programming-experience.
     484
     485\begin{figure}
     486\begin{cfa}
     487// include file uses the CFA keyword "with".
     488#if ! defined( with )                   §\C{// nesting ?}§
     489#define with ®`®with®`®                 §\C{// make keyword an identifier}§
     490#define __CFA_BFD_H__
     491#endif
     492
     493®#include_next <bfdlink.h>              §\C{// must have internal check for multiple expansion}§
     494®
     495#if defined( with ) && defined( __CFA_BFD_H__ ) §\C{// reset only if set}§
     496#undef with
     497#undef __CFA_BFD_H__
     498#endif
     499\end{cfa}
     500\caption{Header-File Interposition}
     501\label{f:HeaderFileInterposition}
     502\end{figure}
     503
     504
    576505\section{Exponentiation Operator}
    577506
    578507C, \CC, and Java (and many other programming languages) have no exponentiation operator\index{exponentiation!operator}\index{operator!exponentiation}, \ie $x^y$, and instead use a routine, like \Indexc{pow}, to perform the exponentiation operation.
    579 \CFA extends the basic operators with the exponentiation operator ©?\?©\index{?\\?@©?\?©} and ©?\=?©\index{?\\=?@©\=?©}, as in, ©x \ y© and ©x \= y©, which means $x^y$ and $x \leftarrow x^y$.
     508\CFA extends the basic operators with the exponentiation operator ©?\?©\index{?\\?@\lstinline@?\?@} and ©?\=?©\index{?\\=?@\lstinline@?\=?@}, as in, ©x \ y© and ©x \= y©, which means $x^y$ and $x \leftarrow x^y$.
    580509The priority of the exponentiation operator is between the cast and multiplicative operators, so that ©w * (int)x \ (int)y * z© is parenthesized as ©((w * (((int)x) \ ((int)y))) * z)©.
    581510
    582511As for \Index{division}, there are exponentiation operators for integral and floating types, including the builtin \Index{complex} types.
    583 Integral exponentiation\index{exponentiation!unsigned integral} is performed with repeated multiplication\footnote{The multiplication computation is $O(\log y)$.} (or shifting if the exponent is 2).
    584 Overflow from large exponents or negative exponents return zero.
    585 Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the exponent cannot be negative.
    586 \begin{cfa}
    587 sout | 1 ®\® 0 | 1 ®\® 1 | 2 ®\® 8 | -4 ®\® 3 | 5 ®\® 3 | 5 ®\® 32 | 5L ®\® 32 | 5L ®\® 64 | -4 ®\® -3 | -4.0 ®\® -3 | 4.0 ®\® 2.1
    588            | (1.0f+2.0fi) ®\® (3.0f+2.0fi);
    589 1 1 256 -64 125 ®0® 3273344365508751233 ®0® ®0® -0.015625 18.3791736799526 0.264715-1.1922i
    590 \end{cfa}
    591 Note, ©5 ®\® 32© and ©5L ®\® 64© overflow, and ©-4 ®\® -3© is a fraction but stored in an integer so all three computations generate an integral zero.
    592 Parenthesis are necessary for complex constants or the expression is parsed as ©1.0f+®(®2.0fi \ 3.0f®)®+2.0fi©.
    593 The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation version is available.
    594 \begin{cfa}
    595 forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } )
    596 OT ?®\®?( OT ep, unsigned int y );
    597 forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } )
    598 OT ?®\®?( OT ep, unsigned long int y );
    599 \end{cfa}
    600 The user type ©T© must define multiplication, one, ©1©, and, ©*©.
    601 
    602 
    603 \section{Control Structures}
    604 
    605 \CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds control structures to increase functionality and safety.
    606 
    607 
    608 %\subsection{\texorpdfstring{\protect\lstinline@if@/\protect\lstinline@while@ Statement}{if Statement}}
    609 \subsection{\texorpdfstring{\LstKeywordStyle{if}/\LstKeywordStyle{while} Statement}{if/while Statement}}
    610 
    611 The ©if©/©while© expression allows declarations, similar to ©for© declaration expression.
    612 (Does not make sense for ©do©-©while©.)
    613 \begin{cfa}
    614 if ( ®int x = f()® ) ... §\C{// x != 0}§
    615 if ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§
    616 if ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§
    617 if ( ®struct S { int i; } x = { f() }; x.i < 4® ) §\C{// relational expression}§
    618 
    619 while ( ®int x = f()® ) ... §\C{// x != 0}§
    620 while ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§
    621 while ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§
    622 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... §\C{// relational expression}§
    623 \end{cfa}
    624 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical ©&&© operator.\footnote{\CC only provides a single declaration always compared not equal to 0.}
    625 The scope of the declaration(s) is local to the @if@ statement but exist within both the ``then'' and ``else'' clauses.
    626 
    627 
    628 \subsection{Loop Control}
    629 
    630 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
    631 \begin{itemize}
    632 \item
    633 An empty conditional implies ©1©.
    634 \item
    635 The up-to range ©~©\index{~@©~©} means exclusive range [M,N).
    636 \item
    637 The up-to range ©~=©\index{~=@©~=©} means inclusive range [M,N].
    638 \item
    639 The down-to range ©-~©\index{-~@©-~©} means exclusive range [N,M).
    640 \item
    641 The down-to range ©-~=©\index{-~=@©-~=©} means inclusive range [N,M].
    642 \item
    643 ©@© means put nothing in this field.
    644 \item
    645 ©0© is the implicit start value;
    646 \item
    647 ©1© is the implicit increment value.
    648 \item
    649 The up-to range uses ©+=© for increment;
    650 \item
    651 The down-to range uses ©-=© for decrement.
    652 \item
    653 The loop index is polymorphic in the type of the start value or comparison value when start is implicitly ©0©.
    654 \end{itemize}
    655 
    656 \begin{figure}
    657 \begin{cquote}
    658 \begin{tabular}{@{}l|l@{}}
    659 \multicolumn{1}{c|}{loop control} & \multicolumn{1}{c}{output} \\
    660 \hline
    661 \begin{cfa}
    662 sout | nlOff;
    663 while ®()® { sout | "empty"; break; } sout | nl;
    664 do { sout | "empty"; break; } while ®()®; sout | nl;
    665 for ®()® { sout | "empty"; break; } sout | nl;
    666 for ( ®0® ) { sout | "A"; } sout | "zero" | nl;
    667 for ( ®1® ) { sout | "A"; } sout | nl;
    668 for ( ®10® ) { sout | "A"; } sout | nl;
    669 for ( ®1 ~= 10 ~ 2® ) { sout | "B"; } sout | nl;
    670 for ( ®10 -~= 1 ~ 2® ) { sout | "C"; } sout | nl;
    671 for ( ®0.5 ~ 5.5® ) { sout | "D"; } sout | nl;
    672 for ( ®5.5 -~ 0.5® ) { sout | "E"; } sout | nl;
    673 for ( ®i; 10® ) { sout | i; } sout | nl;
    674 for ( ®i; 1 ~= 10 ~ 2® ) { sout | i; } sout | nl;
    675 for ( ®i; 10 -~= 1 ~ 2® ) { sout | i; } sout | nl;
    676 for ( ®i; 0.5 ~ 5.5® ) { sout | i; } sout | nl;
    677 for ( ®i; 5.5 -~ 0.5® ) { sout | i; } sout | nl;
    678 for ( ®ui; 2u ~= 10u ~ 2u® ) { sout | ui; } sout | nl;
    679 for ( ®ui; 10u -~= 2u ~ 2u® ) { sout | ui; } sout | nl;
    680 enum { N = 10 };
    681 for ( ®N® ) { sout | "N"; } sout | nl;
    682 for ( ®i; N® ) { sout | i; } sout | nl;
    683 for ( ®i; N -~ 0® ) { sout | i; } sout | nl;
    684 const int start = 3, comp = 10, inc = 2;
    685 for ( ®i; start ~ comp ~ inc + 1® ) { sout | i; } sout | nl;
    686 for ( ®i; 1 ~ @® ) { if ( i > 10 ) break;
    687         sout | i; } sout | nl;
    688 for ( ®i; 10 -~ @® ) { if ( i < 0 ) break;
    689         sout | i; } sout | nl;
    690 for ( ®i; 2 ~ @ ~ 2® ) { if ( i > 10 ) break;
    691         sout | i; } sout | nl;
    692 for ( ®i; 2.1 ~ @ ~ @® ) { if ( i > 10.5 ) break;
    693         sout | i; i += 1.7; } sout | nl;
    694 for ( ®i; 10 -~ @ ~ 2® ) { if ( i < 0 ) break;
    695         sout | i; } sout | nl;
    696 for ( ®i; 12.1 ~ @ ~ @® ) { if ( i < 2.5 ) break;
    697         sout | i; i -= 1.7; } sout | nl;
    698 for ( ®i; 5 : j; -5 ~ @® ) { sout | i | j; } sout | nl;
    699 for ( ®i; 5 : j; -5 -~ @® ) { sout | i | j; } sout | nl;
    700 for ( ®i; 5 : j; -5 ~ @ ~ 2® ) { sout | i | j; } sout | nl;
    701 for ( ®i; 5 : j; -5 -~ @ ~ 2® ) { sout | i | j; } sout | nl;
    702 for ( ®j; -5 ~ @ : i; 5® ) { sout | i | j; } sout | nl;
    703 for ( ®j; -5 -~ @ : i; 5® ) { sout | i | j; } sout | nl;
    704 for ( ®j; -5 ~ @ ~ 2 : i; 5® ) { sout | i | j; } sout | nl;
    705 for ( ®j; -5 -~ @ ~ 2 : i; 5® ) { sout | i | j; } sout | nl;
    706 for ( ®j; -5 -~ @ ~ 2 : i; 5 : k; 1.5 ~ @® ) {
    707         sout | i | j | k; } sout | nl;
    708 for ( ®j; -5 -~ @ ~ 2 : k; 1.5 ~ @ : i; 5® ) {
    709         sout | i | j | k; } sout | nl;
    710 for ( ®k; 1.5 ~ @ : j; -5 -~ @ ~ 2 : i; 5® ) {
    711         sout | i | j | k; } sout | nl;
    712 \end{cfa}
    713 &
    714 \begin{cfa}
    715 
    716 empty
    717 empty
    718 empty
    719 zero
    720 A
    721 A A A A A A A A A A
    722 B B B B B
    723 C C C C C
    724 D D D D D
    725 E E E E E
    726 0 1 2 3 4 5 6 7 8 9
    727 1 3 5 7 9
    728 10 8 6 4 2
    729 0.5 1.5 2.5 3.5 4.5
    730 5.5 4.5 3.5 2.5 1.5
    731 2 4 6 8 10
    732 10 8 6 4 2
    733 
    734 N N N N N N N N N N
    735 0 1 2 3 4 5 6 7 8 9
    736 10 9 8 7 6 5 4 3 2 1
    737 
    738 3 6 9
    739 
    740 1 2 3 4 5 6 7 8 9 10
    741 
    742 10 9 8 7 6 5 4 3 2 1 0
    743 
    744 2 4 6 8 10
    745 
    746 2.1 3.8 5.5 7.2 8.9
    747 
    748 10 8 6 4 2 0
    749 
    750 12.1 10.4 8.7 7 5.3 3.6
    751 0 -5 1 -4 2 -3 3 -2 4 -1
    752 0 -5 1 -6 2 -7 3 -8 4 -9
    753 0 -5 1 -3 2 -1 3 1 4 3
    754 0 -5 1 -7 2 -9 3 -11 4 -13
    755 0 -5 1 -4 2 -3 3 -2 4 -1
    756 0 -5 1 -6 2 -7 3 -8 4 -9
    757 0 -5 1 -3 2 -1 3 1 4 3
    758 0 -5 1 -7 2 -9 3 -11 4 -13
    759 
    760 0 -5 1.5 1 -7 2.5 2 -9 3.5 3 -11 4.5 4 -13 5.5
    761 
    762 0 -5 1.5 1 -7 2.5 2 -9 3.5 3 -11 4.5 4 -13 5.5
    763 
    764 0 -5 1.5 1 -7 2.5 2 -9 3.5 3 -11 4.5 4 -13 5.5
    765 \end{cfa}
    766 \end{tabular}
    767 \end{cquote}
    768 \caption{Loop Control Examples}
    769 \label{f:LoopControlExamples}
    770 \end{figure}
    771 
    772 
    773 %\section{\texorpdfstring{\protect\lstinline@switch@ Statement}{switch Statement}}
    774 \subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}}
    775 
    776 C allows a number of questionable forms for the ©switch© statement:
    777 \begin{enumerate}
    778 \item
    779 By default, the end of a ©case© clause\footnote{
    780 In this section, the term \emph{case clause} refers to either a ©case© or ©default© clause.}
    781 \emph{falls through} to the next ©case© clause in the ©switch© statement;
    782 to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©:
    783 \begin{cfa}
    784 switch ( i ) {
    785   case 1:
    786         ...
    787         // fall-through
    788   case 2:
    789         ...
    790         break;  // exit switch statement
    791 }
    792 \end{cfa}
    793 The ability to fall-through to the next clause \emph{is} a useful form of control flow, specifically when a sequence of case actions compound:
    794 \begin{cquote}
    795 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    796 \begin{cfa}
    797 switch ( argc ) {
    798   case 3:
    799         // open output file
    800         // fall-through
    801   case 2:
    802         // open input file
    803         break;  // exit switch statement
    804   default:
    805         // usage message
    806 }
    807 \end{cfa}
    808 &
    809 \begin{cfa}
    810 
    811 if ( argc == 3 ) {
    812         // open output file
    813         ®// open input file
    814 ®} else if ( argc == 2 ) {
    815         ®// open input file (duplicate)
    816 
    817 ®} else {
    818         // usage message
    819 }
    820 \end{cfa}
    821 \end{tabular}
    822 \end{cquote}
    823 In this example, case 2 is always done if case 3 is done.
    824 This control flow is difficult to simulate with if statements or a ©switch© statement without fall-through as code must be duplicated or placed in a separate routine.
    825 C also uses fall-through to handle multiple case-values resulting in the same action:
    826 \begin{cfa}
    827 switch ( i ) {
    828   ®case 1: case 3: case 5:®     // odd values
    829         // odd action
    830         break;
    831   ®case 2: case 4: case 6:®     // even values
    832         // even action
    833         break;
    834 }
    835 \end{cfa}
    836 However, this situation is handled in other languages without fall-through by allowing a list of case values.
    837 While fall-through itself is not a problem, the problem occurs when fall-through is the default, as this semantics is unintuitive to many programmers and is different from virtually all other programming languages with a ©switch© statement.
    838 Hence, default fall-through semantics results in a large number of programming errors as programmers often \emph{forget} the ©break© statement at the end of a ©case© clause, resulting in inadvertent fall-through.
    839 
    840 \item
    841 It is possible to place ©case© clauses on statements nested \emph{within} the body of the ©switch© statement:
    842 \begin{cfa}
    843 switch ( i ) {
    844   case 0:
    845         if ( j < k ) {
    846                 ...
    847           ®case 1:®             // transfer into "if" statement
    848                 ...
    849         } // if
    850   case 2:
    851         while ( j < 5 ) {
    852                 ...
    853           ®case 3:®             // transfer into "while" statement
    854                 ...
    855         } // while
    856 } // switch
    857 \end{cfa}
    858 The problem with this usage is branching into control structures, which is known to cause both comprehension and technical difficulties.
    859 The comprehension problem occurs from the inability to determine how control reaches a particular point due to the number of branches leading to it.
    860 The technical problem results from the inability to ensure declaration and initialization of variables when blocks are not entered at the beginning.
    861 There are no positive arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it.
    862 Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}:
    863 \begin{cfa}
    864 register int n = (count + 7) / 8;
    865 switch ( count % 8 ) {
    866 case 0: do{ *to = *from++;
    867 case 7:         *to = *from++;
    868 case 6:         *to = *from++;
    869 case 5:         *to = *from++;
    870 case 4:         *to = *from++;
    871 case 3:         *to = *from++;
    872 case 2:         *to = *from++;
    873 case 1:         *to = *from++;
    874                 } while ( --n > 0 );
    875 }
    876 \end{cfa}
    877 which unrolls a loop N times (N = 8 above) and uses the ©switch© statement to deal with any iterations not a multiple of N.
    878 While efficient, this sort of special purpose usage is questionable:
    879 \begin{quote}
    880 Disgusting, no? But it compiles and runs just fine. I feel a combination of pride and revulsion at this
    881 discovery.~\cite{Duff83}
    882 \end{quote}
    883 \item
    884 It is possible to place the ©default© clause anywhere in the list of labelled clauses for a ©switch© statement, rather than only at the end.
    885 Virtually all programming languages with a ©switch© statement require the ©default© clause to appear last in the case-clause list.
    886 The logic for this semantics is that after checking all the ©case© clauses without success, the ©default© clause is selected;
    887 hence, physically placing the ©default© clause at the end of the ©case© clause list matches with this semantics.
    888 This physical placement can be compared to the physical placement of an ©else© clause at the end of a series of connected ©if©/©else© statements.
    889 
    890 \item
    891 It is possible to place unreachable code at the start of a ©switch© statement, as in:
    892 \begin{cfa}
    893 switch ( x ) {
    894         ®int y = 1;® §\C{// unreachable initialization}§
    895         ®x = 7;® §\C{// unreachable code without label/branch}§
    896   case 0: ...
    897         ...
    898         ®int z = 0;® §\C{// unreachable initialization, cannot appear after case}§
    899         z = 2;
    900   case 1:
    901         ®x = z;® §\C{// without fall through, z is uninitialized}§
    902 }
    903 \end{cfa}
    904 While the declaration of the local variable ©y© is useful with a scope across all ©case© clauses, the initialization for such a variable is defined to never be executed because control always transfers over it.
    905 Furthermore, any statements before the first ©case© clause can only be executed if labelled and transferred to using a ©goto©, either from outside or inside of the ©switch©, both of which are problematic.
    906 As well, the declaration of ©z© cannot occur after the ©case© because a label can only be attached to a statement, and without a fall through to case 3, ©z© is uninitialized.
    907 The key observation is that the ©switch© statement branches into control structure, \ie there are multiple entry points into its statement body.
    908 \end{enumerate}
    909 
    910 Before discussing potential language changes to deal with these problems, it is worth observing that in a typical C program:
    911 \begin{itemize}
    912 \item
    913 the number of ©switch© statements is small,
    914 \item
    915 most ©switch© statements are well formed (\ie no \Index*{Duff's device}),
    916 \item
    917 the ©default© clause is usually written as the last case-clause,
    918 \item
    919 and there is only a medium amount of fall-through from one ©case© clause to the next, and most of these result from a list of case values executing common code, rather than a sequence of case actions that compound.
    920 \end{itemize}
    921 These observations put into perspective the \CFA changes to the ©switch©.
    922 \begin{enumerate}
    923 \item
    924 Eliminating default fall-through has the greatest potential for affecting existing code.
    925 However, even if fall-through is removed, most ©switch© statements would continue to work because of the explicit transfers already present at the end of each ©case© clause, the common placement of the ©default© clause at the end of the case list, and the most common use of fall-through, \ie a list of ©case© clauses executing common code, \eg:
    926 \begin{cfa}
    927 case 1:  case 2:  case 3: ...
    928 \end{cfa}
    929 still works.
    930 Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments.
    931 Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, \eg:
    932 \begin{cfa}
    933 ®choose® ( i ) {
    934   case 1:  case 2:  case 3:
    935         ...
    936         ®// implicit end of switch (break)
    937   ®case 5:
    938         ...
    939         ®fallthru®; §\C{// explicit fall through}§
    940   case 7:
    941         ...
    942         ®break® §\C{// explicit end of switch (redundant)}§
    943   default:
    944         j = 3;
    945 }
    946 \end{cfa}
    947 Like the ©switch© statement, the ©choose© statement retains the fall-through semantics for a list of ©case© clauses;
    948 An implicit ©break© is applied only at the end of the \emph{statements} following a ©case© clause.
    949 An explicit ©fallthru© is retained because it is a C-idiom most C programmers expect, and its absence might discourage programmers from using the ©choose© statement.
    950 As well, allowing an explicit ©break© from the ©choose© is a carry over from the ©switch© statement, and expected by C programmers.
    951 \item
    952 \Index*{Duff's device} is eliminated from both ©switch© and ©choose© statements, and only invalidates a small amount of very questionable code.
    953 Hence, the ©case© clause must appear at the same nesting level as the ©switch©/©choose© body, as is done in most other programming languages with ©switch© statements.
    954 \item
    955 The issue of ©default© at locations other than at the end of the cause clause can be solved by using good programming style, and there are a few reasonable situations involving fall-through where the ©default© clause needs to appear is locations other than at the end.
    956 Therefore, no change is made for this issue.
    957 \item
    958 Dealing with unreachable code in a ©switch©/©choose© body is solved by restricting declarations and associated initialization to the start of statement body, which is executed \emph{before} the transfer to the appropriate ©case© clause\footnote{
    959 Essentially, these declarations are hoisted before the ©switch©/©choose© statement and both declarations and statement are surrounded by a compound statement.} and precluding statements before the first ©case© clause.
    960 Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound.
    961 \begin{cfa}
    962 switch ( x ) {
    963         ®int i = 0;® §\C{// allowed only at start}§
    964   case 0:
    965         ...
    966         ®int j = 0;® §\C{// disallowed}§
    967   case 1:
    968         {
    969                 ®int k = 0;® §\C{// allowed at different nesting levels}§
    970                 ...
    971           ®case 2:® §\C{// disallow case in nested statements}§
    972         }
    973   ...
    974 }
    975 \end{cfa}
    976 \end{enumerate}
    977 
    978 
    979 %\section{\texorpdfstring{\protect\lstinline@case@ Clause}{case Clause}}
    980 \subsection{\texorpdfstring{\LstKeywordStyle{case} Statement}{case Statement}}
    981 
    982 C restricts the ©case© clause of a ©switch© statement to a single value.
    983 For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values.
    984 Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C.
    985 Therefore, the ©case© clause is extended with a list of values, as in:
    986 \begin{cquote}
    987 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    988 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    989 \begin{cfa}
    990 switch ( i ) {
    991   case ®1, 3, 5®:
    992         ...
    993   case ®2, 4, 6®:
    994         ...
    995 }
    996 \end{cfa}
    997 &
    998 \begin{cfa}
    999 switch ( i ) {
    1000   case 1: case 3 : case 5:
    1001         ...
    1002   case 2: case 4 : case 6:
    1003         ...
    1004 }
    1005 \end{cfa}
    1006 &
    1007 \begin{cfa}
    1008 
    1009 // odd values
    1010 
    1011 // even values
    1012 
    1013 
    1014 \end{cfa}
    1015 \end{tabular}
    1016 \end{cquote}
    1017 In addition, subranges are allowed to specify case values.\footnote{
    1018 gcc has the same mechanism but awkward syntax, \lstinline@2 ...42@, because a space is required after a number, otherwise the period is a decimal point.}
    1019 \begin{cfa}
    1020 switch ( i ) {
    1021   case ®1~5:® §\C{// 1, 2, 3, 4, 5}§
    1022         ...
    1023   case ®10~15:® §\C{// 10, 11, 12, 13, 14, 15}§
    1024         ...
    1025 }
    1026 \end{cfa}
    1027 Lists of subranges are also allowed.
    1028 \begin{cfa}
    1029 case ®1~5, 12~21, 35~42®:
    1030 \end{cfa}
    1031 
    1032 
    1033 % for ()  => for ( ;; )
    1034 % for ( 10 - t ) => for ( typeof(10 - t) ? = 0 ; ? < 10 - t; ? += 1 ) // using 0 and 1
    1035 % for ( i ; 10 - t ) => for ( typeof(10 - t) i = 0 ; i < 10 - t; i += 1 ) // using 0 and 1
    1036 % for ( T i ; 10 - t ) => for ( T i = 0 ; i < 10 - t; i += 1 ) // using 0 and 1
    1037 % for ( 3~9 ) => for ( int ? = 3 ; ? < 9; ? += 1 ) // using 1
    1038 % for ( i ; 3~9 ) => for ( int i = 3 ; i < 9; i += 1 ) // using 1
    1039 % for ( T i ; 3~9 ) => for ( T i = 3 ; i < 9; i += 1 ) // using 1
    1040 
    1041 
    1042 %\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}}
    1043 \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}}
     512Unsigned integral exponentiation\index{exponentiation!unsigned integral} is performed with repeated multiplication\footnote{The multiplication computation is $O(\log y)$.} (or shifting if the base is 2).
     513Signed integral exponentiation\index{exponentiation!signed integral} is performed with repeated multiplication (or shifting if the base is 2), but yields a floating result because $x^{-y}=1/x^y$.
     514Hence, it is important to designate exponent integral-constants as unsigned or signed: ©3 \ 3u© return an integral result, while ©3 \ 3© returns a floating result.
     515Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative.
     516\begin{cfa}
     517sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi) | endl;
     518256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
     519\end{cfa}
     520Parenthesis are necessary for the complex constants or the expresion is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©.
     521The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available.
     522For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©;
     523for returning a floating value, an additional divide of type ©T© into a ©double© returning a ©double© (©double ?/?( double, T )©) is necessary for negative exponents.
     524
     525
     526\section{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}}
    1044527
    1045528While C provides ©continue© and ©break© statements for altering control flow, both are restricted to one level of nesting for a particular control structure.
    1046529Unfortunately, this restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting.
    1047 To prevent having to switch to the ©goto©, \CFA extends the \Indexc{continue}\index{continue@©continue©!labelled}\index{labelled!continue@©continue©} and \Indexc{break}\index{break@©break©!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85}, as in Java.
     530To prevent having to switch to the ©goto©, \CFA extends the \Indexc{continue}\index{continue@\lstinline@continue@!labelled}\index{labelled!continue@©continue©} and \Indexc{break}\index{break@\lstinline@break@!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85}, as in Java.
    1048531For both ©continue© and ©break©, the target label must be directly associated with a ©for©, ©while© or ©do© statement;
    1049532for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
     
    1130613\end{figure}
    1131614
    1132 Both labelled ©continue© and ©break© are a ©goto©\index{goto@©goto©!restricted} restricted in the following ways:
     615Both labelled ©continue© and ©break© are a ©goto©\index{goto@\lstinline@goto@!restricted} restricted in the following ways:
    1133616\begin{itemize}
    1134617\item
     
    1143626With ©goto©, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader.
    1144627Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs.
    1145 Otherwise, the implicit targets of the current ©continue© and ©break©, \ie the closest enclosing loop or ©switch©, change as certain constructs are added or removed.
    1146 
    1147 
    1148 %\section{\texorpdfstring{\protect\lstinline@with@ Statement}{with Statement}}
    1149 \section{\texorpdfstring{\LstKeywordStyle{with} Statement}{with Statement}}
     628The implicit targets of the current ©continue© and ©break©, \ie the closest enclosing loop or ©switch©, change as certain constructs are added or removed.
     629
     630
     631\section{\texorpdfstring{\protect\lstinline@switch@ Statement}{switch Statement}}
     632
     633C allows a number of questionable forms for the ©switch© statement:
     634\begin{enumerate}
     635\item
     636By default, the end of a ©case© clause\footnote{
     637In this section, the term \emph{case clause} refers to either a ©case© or ©default© clause.}
     638\emph{falls through} to the next ©case© clause in the ©switch© statement;
     639to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©:
     640\begin{cfa}
     641switch ( i ) {
     642  case 1:
     643        ...
     644        // fall-through
     645  case 2:
     646        ...
     647        break;  // exit switch statement
     648}
     649\end{cfa}
     650The ability to fall-through to the next clause \emph{is} a useful form of control flow, specifically when a sequence of case actions compound:
     651\begin{cquote}
     652\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     653\begin{cfa}
     654switch ( argc ) {
     655  case 3:
     656        // open output file
     657        // fall-through
     658  case 2:
     659        // open input file
     660        break;  // exit switch statement
     661  default:
     662        // usage message
     663}
     664\end{cfa}
     665&
     666\begin{cfa}
     667
     668if ( argc == 3 ) {
     669        // open output file
     670        ®// open input file
     671®} else if ( argc == 2 ) {
     672        ®// open input file (duplicate)
     673
     674®} else {
     675        // usage message
     676}
     677\end{cfa}
     678\end{tabular}
     679\end{cquote}
     680In this example, case 2 is always done if case 3 is done.
     681This control flow is difficult to simulate with if statements or a ©switch© statement without fall-through as code must be duplicated or placed in a separate routine.
     682C also uses fall-through to handle multiple case-values resulting in the same action:
     683\begin{cfa}
     684switch ( i ) {
     685  ®case 1: case 3: case 5:®     // odd values
     686        // odd action
     687        break;
     688  ®case 2: case 4: case 6:®     // even values
     689        // even action
     690        break;
     691}
     692\end{cfa}
     693However, this situation is handled in other languages without fall-through by allowing a list of case values.
     694While fall-through itself is not a problem, the problem occurs when fall-through is the default, as this semantics is unintuitive to many programmers and is different from virtually all other programming languages with a ©switch© statement.
     695Hence, default fall-through semantics results in a large number of programming errors as programmers often \emph{forget} the ©break© statement at the end of a ©case© clause, resulting in inadvertent fall-through.
     696
     697\item
     698It is possible to place ©case© clauses on statements nested \emph{within} the body of the ©switch© statement:
     699\begin{cfa}
     700switch ( i ) {
     701  case 0:
     702        if ( j < k ) {
     703                ...
     704          ®case 1:®             // transfer into "if" statement
     705                ...
     706        } // if
     707  case 2:
     708        while ( j < 5 ) {
     709                ...
     710          ®case 3:®             // transfer into "while" statement
     711                ...
     712        } // while
     713} // switch
     714\end{cfa}
     715The problem with this usage is branching into control structures, which is known to cause both comprehension and technical difficulties.
     716The comprehension problem occurs from the inability to determine how control reaches a particular point due to the number of branches leading to it.
     717The technical problem results from the inability to ensure declaration and initialization of variables when blocks are not entered at the beginning.
     718There are no positive arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it.
     719Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}:
     720\begin{cfa}
     721register int n = (count + 7) / 8;
     722switch ( count % 8 ) {
     723case 0: do{ *to = *from++;
     724case 7:         *to = *from++;
     725case 6:         *to = *from++;
     726case 5:         *to = *from++;
     727case 4:         *to = *from++;
     728case 3:         *to = *from++;
     729case 2:         *to = *from++;
     730case 1:         *to = *from++;
     731                } while ( --n > 0 );
     732}
     733\end{cfa}
     734which unrolls a loop N times (N = 8 above) and uses the ©switch© statement to deal with any iterations not a multiple of N.
     735While efficient, this sort of special purpose usage is questionable:
     736\begin{quote}
     737Disgusting, no? But it compiles and runs just fine. I feel a combination of pride and revulsion at this
     738discovery.~\cite{Duff83}
     739\end{quote}
     740\item
     741It is possible to place the ©default© clause anywhere in the list of labelled clauses for a ©switch© statement, rather than only at the end.
     742Virtually all programming languages with a ©switch© statement require the ©default© clause to appear last in the case-clause list.
     743The logic for this semantics is that after checking all the ©case© clauses without success, the ©default© clause is selected;
     744hence, physically placing the ©default© clause at the end of the ©case© clause list matches with this semantics.
     745This physical placement can be compared to the physical placement of an ©else© clause at the end of a series of connected ©if©/©else© statements.
     746
     747\item
     748It is possible to place unreachable code at the start of a ©switch© statement, as in:
     749\begin{cfa}
     750switch ( x ) {
     751        ®int y = 1;®                            §\C{// unreachable initialization}§
     752        ®x = 7;®                                        §\C{// unreachable code without label/branch}§
     753  case 0: ...
     754        ...
     755        ®int z = 0;®                            §\C{// unreachable initialization, cannot appear after case}§
     756        z = 2;
     757  case 1:
     758        ®x = z;®                                        §\C{// without fall through, z is uninitialized}§
     759}
     760\end{cfa}
     761While the declaration of the local variable ©y© is useful with a scope across all ©case© clauses, the initialization for such a variable is defined to never be executed because control always transfers over it.
     762Furthermore, any statements before the first ©case© clause can only be executed if labelled and transferred to using a ©goto©, either from outside or inside of the ©switch©, both of which are problematic.
     763As well, the declaration of ©z© cannot occur after the ©case© because a label can only be attached to a statement, and without a fall through to case 3, ©z© is uninitialized.
     764The key observation is that the ©switch© statement branches into control structure, \ie there are multiple entry points into its statement body.
     765\end{enumerate}
     766
     767Before discussing potential language changes to deal with these problems, it is worth observing that in a typical C program:
     768\begin{itemize}
     769\item
     770the number of ©switch© statements is small,
     771\item
     772most ©switch© statements are well formed (\ie no \Index*{Duff's device}),
     773\item
     774the ©default© clause is usually written as the last case-clause,
     775\item
     776and there is only a medium amount of fall-through from one ©case© clause to the next, and most of these result from a list of case values executing common code, rather than a sequence of case actions that compound.
     777\end{itemize}
     778These observations put into perspective the \CFA changes to the ©switch©.
     779\begin{enumerate}
     780\item
     781Eliminating default fall-through has the greatest potential for affecting existing code.
     782However, even if fall-through is removed, most ©switch© statements would continue to work because of the explicit transfers already present at the end of each ©case© clause, the common placement of the ©default© clause at the end of the case list, and the most common use of fall-through, \ie a list of ©case© clauses executing common code, \eg:
     783\begin{cfa}
     784case 1:  case 2:  case 3: ...
     785\end{cfa}
     786still works.
     787Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments.
     788Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, \eg:
     789\begin{cfa}
     790®choose® ( i ) {
     791  case 1:  case 2:  case 3:
     792        ...
     793        ®// implicit end of switch (break)
     794  ®case 5:
     795        ...
     796        ®fallthru®;                                     §\C{// explicit fall through}§
     797  case 7:
     798        ...
     799        ®break®                                         §\C{// explicit end of switch (redundant)}§
     800  default:
     801        j = 3;
     802}
     803\end{cfa}
     804Like the ©switch© statement, the ©choose© statement retains the fall-through semantics for a list of ©case© clauses;
     805An implicit ©break© is applied only at the end of the \emph{statements} following a ©case© clause.
     806An explicit ©fallthru© is retained because it is a C-idiom most C programmers expect, and its absence might discourage programmers from using the ©choose© statement.
     807As well, allowing an explicit ©break© from the ©choose© is a carry over from the ©switch© statement, and expected by C programmers.
     808\item
     809\Index*{Duff's device} is eliminated from both ©switch© and ©choose© statements, and only invalidates a small amount of very questionable code.
     810Hence, the ©case© clause must appear at the same nesting level as the ©switch©/©choose© body, as is done in most other programming languages with ©switch© statements.
     811\item
     812The issue of ©default© at locations other than at the end of the cause clause can be solved by using good programming style, and there are a few reasonable situations involving fall-through where the ©default© clause needs to appear is locations other than at the end.
     813Therefore, no change is made for this issue.
     814\item
     815Dealing with unreachable code in a ©switch©/©choose© body is solved by restricting declarations and associated initialization to the start of statement body, which is executed \emph{before} the transfer to the appropriate ©case© clause\footnote{
     816Essentially, these declarations are hoisted before the ©switch©/©choose© statement and both declarations and statement are surrounded by a compound statement.} and precluding statements before the first ©case© clause.
     817Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound.
     818\begin{cfa}
     819switch ( x ) {
     820        ®int i = 0;®                            §\C{// allowed only at start}§
     821  case 0:
     822        ...
     823        ®int j = 0;®                            §\C{// disallowed}§
     824  case 1:
     825        {
     826                ®int k = 0;®                    §\C{// allowed at different nesting levels}§
     827                ...
     828          ®case 2:®                                     §\C{// disallow case in nested statements}§
     829        }
     830  ...
     831}
     832\end{cfa}
     833\end{enumerate}
     834
     835
     836\section{\texorpdfstring{\protect\lstinline@case@ Clause}{case Clause}}
     837
     838C restricts the ©case© clause of a ©switch© statement to a single value.
     839For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values.
     840Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C.
     841Therefore, the ©case© clause is extended with a list of values, as in:
     842\begin{cquote}
     843\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
     844\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
     845\begin{cfa}
     846switch ( i ) {
     847  case ®1, 3, 5®:
     848        ...
     849  case ®2, 4, 6®:
     850        ...
     851}
     852\end{cfa}
     853&
     854\begin{cfa}
     855switch ( i ) {
     856  case 1: case 3 : case 5:
     857        ...
     858  case 2: case 4 : case 6:
     859        ...
     860}
     861\end{cfa}
     862&
     863\begin{cfa}
     864
     865// odd values
     866
     867// even values
     868
     869
     870\end{cfa}
     871\end{tabular}
     872\end{cquote}
     873In addition, subranges are allowed to specify case values.\footnote{
     874gcc has the same mechanism but awkward syntax, \lstinline@2 ...42@, because a space is required after a number, otherwise the period is a decimal point.}
     875\begin{cfa}
     876switch ( i ) {
     877  case ®1~5:®                                   §\C{// 1, 2, 3, 4, 5}§
     878        ...
     879  case ®10~15:®                                 §\C{// 10, 11, 12, 13, 14, 15}§
     880        ...
     881}
     882\end{cfa}
     883Lists of subranges are also allowed.
     884\begin{cfa}
     885case ®1~5, 12~21, 35~42®:
     886\end{cfa}
     887
     888
     889\section{\texorpdfstring{\protect\lstinline@with@ Statement}{with Statement}}
    1150890\label{s:WithStatement}
    1151891
    1152892Grouping heterogeneous data into \newterm{aggregate}s (structure/union) is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers:
    1153893\begin{cfa}
    1154 struct S { §\C{// aggregate}§
    1155         char c; §\C{// fields}§
     894struct S {                                                                      §\C{// aggregate}§
     895        char c;                                                                 §\C{// fields}§
    1156896        int i;
    1157897        double d;
     
    1162902\begin{cfa}
    1163903void f( S s ) {
    1164         ®s.®c; ®s.®i; ®s.®d; §\C{// access containing fields}§
     904        `s.`c; `s.`i; `s.`d;                                    §\C{// access containing fields}§
    1165905}
    1166906\end{cfa}
     
    1169909\begin{C++}
    1170910struct S {
    1171         char c; §\C{// fields}§
     911        char c;                                                                 §\C{// fields}§
    1172912        int i;
    1173913        double d;
    1174         void f() { §\C{// implicit ``this'' aggregate}§
    1175                 ®this->®c; ®this->®i; ®this->®d; §\C{// access containing fields}§
     914        void f() {                                                              §\C{// implicit ``this'' aggregate}§
     915                `this->`c; `this->`i; `this->`d;        §\C{// access containing fields}§
    1176916        }
    1177917}
    1178918\end{C++}
    1179 Object-oriented nesting of member functions in a \lstinline[language=C++]@class/struct@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.
     919Object-oriented nesting of member functions in a \lstinline[language=C++]@class/struct@ allows eliding \lstinline[language=C++]$this->$ because of lexical scoping.
    1180920However, for other aggregate parameters, qualification is necessary:
    1181921\begin{cfa}
    1182922struct T { double m, n; };
    1183 int S::f( T & t ) { §\C{// multiple aggregate parameters}§
    1184         c; i; d; §\C{\color{red}// this--{\textgreater}.c, this--{\textgreater}.i, this--{\textgreater}.d}§
    1185         ®t.®m; ®t.®n; §\C{// must qualify}§
    1186 }
    1187 \end{cfa}
    1188 
    1189 To simplify the programmer experience, \CFA provides a ©with© statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing the field identifiers.
     923int S::f( T & t ) {                                                     §\C{// multiple aggregate parameters}§
     924        c; i; d;                                                                §\C{\color{red}// this--{\textgreater}.c, this--{\textgreater}.i, this--{\textgreater}.d}§
     925        `t.`m; `t.`n;                                                   §\C{// must qualify}§
     926}
     927\end{cfa}
     928
     929To simplify the programmer experience, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing the field identifiers.
    1190930Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block.
    1191931\begin{cfa}
    1192 void f( S & this ) ®with ( this )® { §\C{// with statement}§
    1193         c; i; d; §\C{\color{red}// this.c, this.i, this.d}§
     932void f( S & this ) `with ( this )` {            §\C{// with statement}§
     933        c; i; d;                                                                §\C{\color{red}// this.c, this.i, this.d}§
    1194934}
    1195935\end{cfa}
    1196936with the generality of opening multiple aggregate-parameters:
    1197937\begin{cfa}
    1198 void f( S & s, T & t ) ®with ( s, t )® { §\C{// multiple aggregate parameters}§
    1199         c; i; d; §\C{\color{red}// s.c, s.i, s.d}§
    1200         m; n; §\C{\color{red}// t.m, t.n}§
    1201 }
    1202 \end{cfa}
    1203 
    1204 In detail, the ©with© statement has the form:
     938void f( S & s, T & t ) `with ( s, t )` {                §\C{// multiple aggregate parameters}§
     939        c; i; d;                                                                §\C{\color{red}// s.c, s.i, s.d}§
     940        m; n;                                                                   §\C{\color{red}// t.m, t.n}§
     941}
     942\end{cfa}
     943
     944In detail, the @with@ statement has the form:
    1205945\begin{cfa}
    1206946§\emph{with-statement}§:
     
    1217957The difference between parallel and nesting occurs for fields with the same name and type:
    1218958\begin{cfa}
    1219 struct S { int ®i®; int j; double m; } s, w;
    1220 struct T { int ®i®; int k; int m; } t, w;
     959struct S { int `i`; int j; double m; } s, w;
     960struct T { int `i`; int k; int m; } t, w;
    1221961with ( s, t ) {
    1222         j + k; §\C{// unambiguous, s.j + t.k}§
    1223         m = 5.0; §\C{// unambiguous, t.m = 5.0}§
    1224         m = 1; §\C{// unambiguous, s.m = 1}§
    1225         int a = m; §\C{// unambiguous, a = s.i }§
    1226         double b = m; §\C{// unambiguous, b = t.m}§
    1227         int c = s.i + t.i; §\C{// unambiguous, qualification}§
    1228         (double)m; §\C{// unambiguous, cast}§
    1229 }
    1230 \end{cfa}
    1231 For parallel semantics, both ©s.i© and ©t.i© are visible, so ©i© is ambiguous without qualification;
    1232 for nested semantics, ©t.i© hides ©s.i©, so ©i© implies ©t.i©.
     962        j + k;                                                                  §\C{// unambiguous, s.j + t.k}§
     963        m = 5.0;                                                                §\C{// unambiguous, t.m = 5.0}§
     964        m = 1;                                                                  §\C{// unambiguous, s.m = 1}§
     965        int a = m;                                                              §\C{// unambiguous, a = s.i }§
     966        double b = m;                                                   §\C{// unambiguous, b = t.m}§
     967        int c = s.i + t.i;                                              §\C{// unambiguous, qualification}§
     968        (double)m;                                                              §\C{// unambiguous, cast}§
     969}
     970\end{cfa}
     971For parallel semantics, both @s.i@ and @t.i@ are visible, so @i@ is ambiguous without qualification;
     972for nested semantics, @t.i@ hides @s.i@, so @i@ implies @t.i@.
    1233973\CFA's ability to overload variables means fields with the same name but different types are automatically disambiguated, eliminating most qualification when opening multiple aggregates.
    1234974Qualification or a cast is used to disambiguate.
    1235975
    1236 There is an interesting problem between parameters and the function-body ©with©, \eg:
    1237 \begin{cfa}
    1238 void ?{}( S & s, int i ) with ( s ) { §\C{// constructor}§
    1239         ®s.i = i;®  j = 3;  m = 5.5; §\C{// initialize fields}§
    1240 }
    1241 \end{cfa}
    1242 Here, the assignment ©s.i = i© means ©s.i = s.i©, which is meaningless, and there is no mechanism to qualify the parameter ©i©, making the assignment impossible using the function-body ©with©.
     976There is an interesting problem between parameters and the function-body @with@, \eg:
     977\begin{cfa}
     978void ?{}( S & s, int i ) with ( s ) {           §\C{// constructor}§
     979        `s.i = i;`  j = 3;  m = 5.5;                    §\C{// initialize fields}§
     980}
     981\end{cfa}
     982Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function-body @with@.
    1243983To solve this problem, parameters are treated like an initialized aggregate:
    1244984\begin{cfa}
     
    1250990and implicitly opened \emph{after} a function-body open, to give them higher priority:
    1251991\begin{cfa}
    1252 void ?{}( S & s, int ®i® ) with ( s ) ®with( §\emph{\color{red}params}§ )® {
    1253         s.i = ®i®; j = 3; m = 5.5;
    1254 }
    1255 \end{cfa}
    1256 Finally, a cast may be used to disambiguate among overload variables in a ©with© expression:
    1257 \begin{cfa}
    1258 with ( w ) { ... } §\C{// ambiguous, same name and no context}§
    1259 with ( (S)w ) { ... } §\C{// unambiguous, cast}§
    1260 \end{cfa}
    1261 and ©with© expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate:
     992void ?{}( S & s, int `i` ) with ( s ) `with( §\emph{\color{red}params}§ )` {
     993        s.i = `i`; j = 3; m = 5.5;
     994}
     995\end{cfa}
     996Finally, a cast may be used to disambiguate among overload variables in a @with@ expression:
     997\begin{cfa}
     998with ( w ) { ... }                                                      §\C{// ambiguous, same name and no context}§
     999with ( (S)w ) { ... }                                           §\C{// unambiguous, cast}§
     1000\end{cfa}
     1001and @with@ expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate:
    12621002% \begin{cfa}
    12631003% struct S { int i, j; } sv;
    1264 % with ( sv ) { §\C{// implicit reference}§
     1004% with ( sv ) {                                                         §\C{// implicit reference}§
    12651005%       S & sr = sv;
    1266 %       with ( sr ) { §\C{// explicit reference}§
     1006%       with ( sr ) {                                                   §\C{// explicit reference}§
    12671007%               S * sp = &sv;
    1268 %               with ( *sp ) { §\C{// computed reference}§
    1269 %                       i = 3; j = 4; §\C{\color{red}// sp--{\textgreater}i, sp--{\textgreater}j}§
     1008%               with ( *sp ) {                                          §\C{// computed reference}§
     1009%                       i = 3; j = 4;                                   §\C{\color{red}// sp--{\textgreater}i, sp--{\textgreater}j}§
    12701010%               }
    1271 %               i = 2; j = 3; §\C{\color{red}// sr.i, sr.j}§
     1011%               i = 2; j = 3;                                           §\C{\color{red}// sr.i, sr.j}§
    12721012%       }
    1273 %       i = 1; j = 2; §\C{\color{red}// sv.i, sv.j}§
     1013%       i = 1; j = 2;                                                   §\C{\color{red}// sv.i, sv.j}§
    12741014% }
    12751015% \end{cfa}
     
    12791019class C {
    12801020        int i, j;
    1281         int mem() { §\C{\color{red}// implicit "this" parameter}§
    1282                 i = 1; §\C{\color{red}// this->i}§
    1283                 j = 2; §\C{\color{red}// this->j}§
     1021        int mem() {                                     §\C{\color{red}// implicit "this" parameter}§
     1022                i = 1;                                  §\C{\color{red}// this->i}§
     1023                j = 2;                                  §\C{\color{red}// this->j}§
    12841024        }
    12851025}
     
    12881028\begin{cfa}
    12891029struct S { int i, j; };
    1290 int mem( S & ®this® ) { §\C{// explicit "this" parameter}§
    1291         ®this.®i = 1; §\C{// "this" is not elided}§
     1030int mem( S & ®this® ) {                 §\C{// explicit "this" parameter}§
     1031        ®this.®i = 1;                           §\C{// "this" is not elided}§
    12921032        ®this.®j = 2;
    12931033}
     
    12981038\begin{cfa}
    12991039int mem( S & this ) ®with( this )® { §\C{// with clause}§
    1300         i = 1; §\C{\color{red}// this.i}§
    1301         j = 2; §\C{\color{red}// this.j}§
     1040        i = 1;                                          §\C{\color{red}// this.i}§
     1041        j = 2;                                          §\C{\color{red}// this.j}§
    13021042}
    13031043\end{cfa}
     
    13161056        struct S1 { ... } s1;
    13171057        struct S2 { ... } s2;
    1318         ®with( s1 )® { §\C{// with statement}§
     1058        ®with( s1 )® {                          §\C{// with statement}§
    13191059                // access fields of s1 without qualification
    1320                 ®with s2® { §\C{// nesting}§
     1060                ®with s2® {                             §\C{// nesting}§
    13211061                        // access fields of s1 and s2 without qualification
    13221062                }
     
    13731113Non-local transfer can cause stack unwinding, \ie non-local routine termination, depending on the kind of raise.
    13741114\begin{cfa}
    1375 exception_t E {}; §\C{// exception type}§
     1115exception_t E {};                               §\C{// exception type}§
    13761116void f(...) {
    1377         ... throw E{}; ... §\C{// termination}§
    1378         ... throwResume E{}; ... §\C{// resumption}§
     1117        ... throw E{}; ...                      §\C{// termination}§
     1118        ... throwResume E{}; ...        §\C{// resumption}§
    13791119}
    13801120try {
    13811121        f(...);
    1382 } catch( E e ; §boolean-predicate§ ) {          §\C[8cm]{// termination handler}§
     1122} catch( E e ; §boolean-predicate§ ) {                  §\C[8cm]{// termination handler}§
    13831123        // recover and continue
    1384 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§
     1124} catchResume( E e ; §boolean-predicate§ ) {    §\C{// resumption handler}\CRT§
    13851125        // repair and return
    13861126} finally {
     
    14421182For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
    14431183\begin{cfa}
    1444 int ®(*®f®())[®5®]® {...}; §\C{// definition}§
    1445  ... ®(*®f®())[®3®]® += 1; §\C{// usage}§
     1184int ®(*®f®())[®5®]® {...};                              §\C{// definition}§
     1185 ... ®(*®f®())[®3®]® += 1;                              §\C{// usage}§
    14461186\end{cfa}
    14471187Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
    1448 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice, even though Dennis Richie believed otherwise:
    1449 \begin{quote}
    1450 In spite of its difficulties, I believe that the C's approach to declarations remains plausible, and am comfortable with it; it is a useful unifying principle.~\cite[p.~12]{Ritchie93}
    1451 \end{quote}
     1188While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
    14521189
    14531190\CFA provides its own type, variable and routine declarations, using a different syntax.
     
    16351372*x = 3;                 // implicit dereference
    16361373int * ®const® y = (int *)104;
    1637 *y = *x;                        // implicit dereference
     1374*y = *x;                // implicit dereference
    16381375\end{cfa}
    16391376\end{tabular}
     
    16491386\hline
    16501387\begin{cfa}
    1651 lda             r1,100   // load address of x
    1652 ld               r2,(r1)   // load value of x
    1653 lda             r3,104   // load address of y
    1654 st               r2,(r3)   // store x into y
     1388lda             r1,100  // load address of x
     1389ld               r2,(r1)          // load value of x
     1390lda             r3,104  // load address of y
     1391st               r2,(r3)          // store x into y
    16551392\end{cfa}
    16561393&
    16571394\begin{cfa}
    16581395
    1659 ld              r2,(100)   // load value of x
    1660 
    1661 st              r2,(104)   // store x into y
     1396ld              r2,(100)        // load value of x
     1397
     1398st              r2,(104)        // store x into y
    16621399\end{cfa}
    16631400\end{tabular}
     
    16731410\begin{cfa}
    16741411int x, y, ®*® p1, ®*® p2, ®**® p3;
    1675 p1 = ®&®x;    // p1 points to x
    1676 p2 = p1;    // p2 points to x
    1677 p1 = ®&®y;    // p1 points to y
    1678 p3 = &p2;  // p3 points to p2
     1412p1 = ®&®x;              // p1 points to x
     1413p2 = p1;                // p2 points to x
     1414p1 = ®&®y;              // p1 points to y
     1415p3 = &p2;               // p3 points to p2
    16791416\end{cfa}
    16801417&
     
    16871424For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage
    16881425\begin{cfa}
    1689 p2 = p1 + x; §\C{// compiler infers *p2 = *p1 + x;}§
     1426p2 = p1 + x;                                    §\C{// compiler infers *p2 = *p1 + x;}§
    16901427\end{cfa}
    16911428Algol68 infers the following dereferencing ©*p2 = *p1 + x©, because adding the arbitrary integer value in ©x© to the address of ©p1© and storing the resulting address into ©p2© is an unlikely operation.
    1692 Unfortunately, automatic dereferencing does not work in all cases, and so some mechanism is necessary to fix incorrect choices.
     1429Unfortunately, automatic dereferencing does not work in all cases, and so some mechanism is necessary to fix incorrect choices. 
    16931430
    16941431Rather than inferring dereference, most programming languages pick one implicit dereferencing semantics, and the programmer explicitly indicates the other to resolve address-duality.
    16951432In C, objects of pointer type always manipulate the pointer object's address:
    16961433\begin{cfa}
    1697 p1 = p2; §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§
    1698 p2 = p1 + x; §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§
     1434p1 = p2;                                                §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§
     1435p2 = p1 + x;                                    §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§
    16991436\end{cfa}
    17001437even though the assignment to ©p2© is likely incorrect, and the programmer probably meant:
    17011438\begin{cfa}
    1702 p1 = p2; §\C{// pointer address assignment}§
    1703 ®*®p2 = ®*®p1 + x; §\C{// pointed-to value assignment / operation}§
     1439p1 = p2;                                                §\C{// pointer address assignment}§
     1440®*®p2 = ®*®p1 + x;                              §\C{// pointed-to value assignment / operation}§
    17041441\end{cfa}
    17051442The C semantics work well for situations where manipulation of addresses is the primary meaning and data is rarely accessed, such as storage management (©malloc©/©free©).
     
    17181455\begin{cfa}
    17191456int x, y, ®&® r1, ®&® r2, ®&&® r3;
    1720 ®&®r1 = &x; §\C{// r1 points to x}§
    1721 ®&®r2 = &r1; §\C{// r2 points to x}§
    1722 ®&®r1 = &y; §\C{// r1 points to y}§
    1723 ®&&®r3 = ®&®&r2; §\C{// r3 points to r2}§
     1457®&®r1 = &x;                                             §\C{// r1 points to x}§
     1458®&®r2 = &r1;                                    §\C{// r2 points to x}§
     1459®&®r1 = &y;                                             §\C{// r1 points to y}§
     1460®&&®r3 = ®&®&r2;                                §\C{// r3 points to r2}§
    17241461r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§
    17251462\end{cfa}
     
    17371474For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}):
    17381475\begin{cfa}
    1739 (&®*®)r1 = &x; §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§
     1476(&®*®)r1 = &x;                                  §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§
    17401477\end{cfa}
    17411478Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}):
    17421479\begin{cfa}
    1743 (&(&®*®)®*®)r3 = &(&®*®)r2; §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§
     1480(&(&®*®)®*®)r3 = &(&®*®)r2;             §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§
    17441481\end{cfa}
    17451482Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth.
     
    17491486int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    17501487                 &r1 = x,    &&r2 = r1,   &&&r3 = r2;
    1751 ***p3 = 3; §\C{// change x}§
    1752 r3 = 3; §\C{// change x, ***r3}§
    1753 **p3 = ...; §\C{// change p1}§
    1754 &r3 = ...; §\C{// change r1, (\&*)**r3, 1 cancellation}§
    1755 *p3 = ...; §\C{// change p2}§
    1756 &&r3 = ...; §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§
    1757 &&&r3 = p3; §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§
     1488***p3 = 3;                                              §\C{// change x}§
     1489r3 = 3;                                                 §\C{// change x, ***r3}§
     1490**p3 = ...;                                             §\C{// change p1}§
     1491&r3 = ...;                                              §\C{// change r1, (\&*)**r3, 1 cancellation}§
     1492*p3 = ...;                                              §\C{// change p2}§
     1493&&r3 = ...;                                             §\C{// change r2, (\&(\&*)*)*r3, 2 cancellations}§
     1494&&&r3 = p3;                                             §\C{// change r3 to p3, (\&(\&(\&*)*)*)r3, 3 cancellations}§
    17581495\end{cfa}
    17591496Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types.
     
    17621499As for a pointer type, a reference type may have qualifiers:
    17631500\begin{cfa}
    1764 const int cx = 5; §\C{// cannot change cx;}§
    1765 const int & cr = cx; §\C{// cannot change what cr points to}§
    1766 ®&®cr = &cx; §\C{// can change cr}§
    1767 cr = 7; §\C{// error, cannot change cx}§
    1768 int & const rc = x; §\C{// must be initialized}§
    1769 ®&®rc = &x; §\C{// error, cannot change rc}§
    1770 const int & const crc = cx; §\C{// must be initialized}§
    1771 crc = 7; §\C{// error, cannot change cx}§
    1772 ®&®crc = &cx; §\C{// error, cannot change crc}§
     1501const int cx = 5;                                       §\C{// cannot change cx;}§
     1502const int & cr = cx;                            §\C{// cannot change what cr points to}§
     1503®&®cr = &cx;                                            §\C{// can change cr}§
     1504cr = 7;                                                         §\C{// error, cannot change cx}§
     1505int & const rc = x;                                     §\C{// must be initialized}§
     1506®&®rc = &x;                                                     §\C{// error, cannot change rc}§
     1507const int & const crc = cx;                     §\C{// must be initialized}§
     1508crc = 7;                                                        §\C{// error, cannot change cx}§
     1509®&®crc = &cx;                                           §\C{// error, cannot change crc}§
    17731510\end{cfa}
    17741511Hence, for type ©& const©, there is no pointer assignment, so ©&rc = &x© is disallowed, and \emph{the address value cannot be the null pointer unless an arbitrary pointer is coerced\index{coercion} into the reference}:
    17751512\begin{cfa}
    1776 int & const cr = *0; §\C{// where 0 is the int * zero}§
     1513int & const cr = *0;                            §\C{// where 0 is the int * zero}§
    17771514\end{cfa}
    17781515Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management:
     
    17811518cr = 5;
    17821519free( &cr );
    1783 cr = 7; §\C{// unsound pointer dereference}§
     1520cr = 7;                                                         §\C{// unsound pointer dereference}§
    17841521\end{cfa}
    17851522
     
    18061543\begin{cfa}
    18071544int w, x, y, z, & ar[3] = { x, y, z }; §\C{// initialize array of references}§
    1808 &ar[1] = &w; §\C{// change reference array element}§
    1809 typeof( ar[1] ) p; §\C{// (gcc) is int, \ie the type of referenced object}§
    1810 typeof( &ar[1] ) q; §\C{// (gcc) is int \&, \ie the type of reference}§
    1811 sizeof( ar[1] ) == sizeof( int ); §\C{// is true, \ie the size of referenced object}§
    1812 sizeof( &ar[1] ) == sizeof( int *) §\C{// is true, \ie the size of a reference}§
     1545&ar[1] = &w;                                            §\C{// change reference array element}§
     1546typeof( ar[1] ) p;                                      §\C{// (gcc) is int, \ie the type of referenced object}§
     1547typeof( &ar[1] ) q;                                     §\C{// (gcc) is int \&, \ie the type of reference}§
     1548sizeof( ar[1] ) == sizeof( int );       §\C{// is true, \ie the size of referenced object}§
     1549sizeof( &ar[1] ) == sizeof( int *)      §\C{// is true, \ie the size of a reference}§
    18131550\end{cfa}
    18141551
     
    18271564Therefore, for pointer/reference initialization, the initializing value must be an address not a value.
    18281565\begin{cfa}
    1829 int * p = &x; §\C{// assign address of x}§
    1830 ®int * p = x;® §\C{// assign value of x}§
    1831 int & r = x; §\C{// must have address of x}§
     1566int * p = &x;                                           §\C{// assign address of x}§
     1567®int * p = x;®                                          §\C{// assign value of x}§
     1568int & r = x;                                            §\C{// must have address of x}§
    18321569\end{cfa}
    18331570Like the previous example with C pointer-arithmetic, it is unlikely assigning the value of ©x© into a pointer is meaningful (again, a warning is usually given).
     
    18381575Similarly, when a reference type is used for a parameter/return type, the call-site argument does not require a reference operator for the same reason.
    18391576\begin{cfa}
    1840 int & f( int & r ); §\C{// reference parameter and return}§
    1841 z = f( x ) + f( y ); §\C{// reference operator added, temporaries needed for call results}§
     1577int & f( int & r );                                     §\C{// reference parameter and return}§
     1578z = f( x ) + f( y );                            §\C{// reference operator added, temporaries needed for call results}§
    18421579\end{cfa}
    18431580Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©.
     
    18661603void f( int & r );
    18671604void g( int * p );
    1868 f( 3 );                   g( ®&®3 ); §\C{// compiler implicit generates temporaries}§
    1869 f( x + y );             g( ®&®(x + y) ); §\C{// compiler implicit generates temporaries}§
     1605f( 3 );                   g( ®&®3 );            §\C{// compiler implicit generates temporaries}§
     1606f( x + y );             g( ®&®(x + y) );        §\C{// compiler implicit generates temporaries}§
    18701607\end{cfa}
    18711608Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{
     
    18781615\begin{cfa}
    18791616void f( int i );
    1880 void (* fp)( int ); §\C{// routine pointer}§
    1881 fp = f; §\C{// reference initialization}§
    1882 fp = &f; §\C{// pointer initialization}§
    1883 fp = *f; §\C{// reference initialization}§
    1884 fp(3); §\C{// reference invocation}§
    1885 (*fp)(3); §\C{// pointer invocation}§
     1617void (* fp)( int );                                     §\C{// routine pointer}§
     1618fp = f;                                                         §\C{// reference initialization}§
     1619fp = &f;                                                        §\C{// pointer initialization}§
     1620fp = *f;                                                        §\C{// reference initialization}§
     1621fp(3);                                                          §\C{// reference invocation}§
     1622(*fp)(3);                                                       §\C{// pointer invocation}§
    18861623\end{cfa}
    18871624While C's treatment of routine objects has similarity to inferring a reference type in initialization contexts, the examples are assignment not initialization, and all possible forms of assignment are possible (©f©, ©&f©, ©*f©) without regard for type.
    18881625Instead, a routine object should be referenced by a ©const© reference:
    18891626\begin{cfa}
    1890 ®const® void (®&® fr)( int ) = f; §\C{// routine reference}§
    1891 fr = ... §\C{// error, cannot change code}§
    1892 &fr = ...; §\C{// changing routine reference}§
    1893 fr( 3 ); §\C{// reference call to f}§
    1894 (*fr)(3); §\C{// error, incorrect type}§
     1627®const® void (®&® fr)( int ) = f;       §\C{// routine reference}§
     1628fr = ...                                                        §\C{// error, cannot change code}§
     1629&fr = ...;                                                      §\C{// changing routine reference}§
     1630fr( 3 );                                                        §\C{// reference call to f}§
     1631(*fr)(3);                                                       §\C{// error, incorrect type}§
    18951632\end{cfa}
    18961633because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{
     
    19051642\begin{itemize}
    19061643\item
    1907 if ©R© is an \Index{rvalue} of type ©T &©$_1\cdots$ ©&©$_r$, where $r \ge 1$ references (©&© symbols), than ©&R© has type ©T ®*®&©$_{\color{red}2}\cdots$ ©&©$_{\color{red}r}$, \ie ©T© pointer with $r-1$ references (©&© symbols).
    1908 
    1909 \item
    1910 if ©L© is an \Index{lvalue} of type ©T &©$_1\cdots$ ©&©$_l$, where $l \ge 0$ references (©&© symbols), than ©&L© has type ©T ®*®&©$_{\color{red}1}\cdots$ ©&©$_{\color{red}l}$, \ie ©T© pointer with $l$ references (©&© symbols).
     1644if ©R© is an \Index{rvalue} of type ©T &$_1$...&$_r$© where $r \ge 1$ references (©&© symbols) then ©&R© has type ©T ®*®&$_{\color{red}2}$...&$_{\color{red}r}$©, \ie ©T© pointer with $r-1$ references (©&© symbols).
     1645
     1646\item
     1647if ©L© is an \Index{lvalue} of type ©T &$_1$...&$_l$© where $l \ge 0$ references (©&© symbols) then ©&L© has type ©T ®*®&$_{\color{red}1}$...&$_{\color{red}l}$©, \ie ©T© pointer with $l$ references (©&© symbols).
    19111648\end{itemize}
    19121649The following example shows the first rule applied to different \Index{rvalue} contexts:
     
    19141651int x, * px, ** ppx, *** pppx, **** ppppx;
    19151652int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    1916 x = rrrx; §\C[2.0in]{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§
    1917 px = &rrrx; §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}§
    1918 ppx = &&rrrx; §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}§
    1919 pppx = &&&rrrx; §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}§
    1920 ppppx = &&&&rrrx; §\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}§
     1653x = rrrx;               // rrrx is an lvalue with type int &&& (equivalent to x)
     1654px = &rrrx;             // starting from rrrx, &rrrx is an rvalue with type int *&&& (&x)
     1655ppx = &&rrrx;   // starting from &rrrx, &&rrrx is an rvalue with type int **&& (&rx)
     1656pppx = &&&rrrx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (&rrx)
     1657ppppx = &&&&rrrx; // starting from &&&rrrx, &&&&rrrx is an rvalue with type int **** (&rrrx)
    19211658\end{cfa}
    19221659The following example shows the second rule applied to different \Index{lvalue} contexts:
     
    19241661int x, * px, ** ppx, *** pppx;
    19251662int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    1926 rrrx = 2; §\C{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§
    1927 &rrrx = px; §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (rx)}§
    1928 &&rrrx = ppx; §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (rrx)}§
    1929 &&&rrrx = pppx; §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (rrrx)}\CRT§
     1663rrrx = 2;               // rrrx is an lvalue with type int &&& (equivalent to x)
     1664&rrrx = px;             // starting from rrrx, &rrrx is an rvalue with type int *&&& (rx)
     1665&&rrrx = ppx;   // starting from &rrrx, &&rrrx is an rvalue with type int **&& (rrx)
     1666&&&rrrx = pppx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (rrrx)
    19301667\end{cfa}
    19311668
     
    19401677\begin{cfa}
    19411678int x;
    1942 x + 1; §\C[2.0in]{// lvalue variable (int) converts to rvalue for expression}§
     1679x + 1;                  // lvalue variable (int) converts to rvalue for expression
    19431680\end{cfa}
    19441681An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped.
     
    19501687\begin{cfa}
    19511688int x, &r = x, f( int p );
    1952 x = ®r® + f( ®r® ); §\C{// lvalue reference converts to rvalue}§
     1689x = ®r® + f( ®r® );  // lvalue reference converts to rvalue
    19531690\end{cfa}
    19541691An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped.
     
    19571694lvalue to reference conversion: \lstinline[deletekeywords=lvalue]@lvalue-type cv1 T@ converts to ©cv2 T &©, which allows implicitly converting variables to references.
    19581695\begin{cfa}
    1959 int x, &r = ®x®, f( int & p ); §\C{// lvalue variable (int) convert to reference (int \&)}§
    1960 f( ®x® ); §\C{// lvalue variable (int) convert to reference (int \&)}§
     1696int x, &r = ®x®, f( int & p ); // lvalue variable (int) convert to reference (int &)
     1697f( ®x® );               // lvalue variable (int) convert to reference (int &)
    19611698\end{cfa}
    19621699Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost.
     
    19681705\begin{cfa}
    19691706int x, & f( int & p );
    1970 f( ®x + 3® );   §\C[1.5in]{// rvalue parameter (int) implicitly converts to lvalue temporary reference (int \&)}§
    1971 ®&f®(...) = &x; §\C{// rvalue result (int \&) implicitly converts to lvalue temporary reference (int \&)}\CRT§
     1707f( ®x + 3® );   // rvalue parameter (int) implicitly converts to lvalue temporary reference (int &)
     1708®&f®(...) = &x; // rvalue result (int &) implicitly converts to lvalue temporary reference (int &)
    19721709\end{cfa}
    19731710In both case, modifications to the temporary are inaccessible (\Index{warning}).
     
    21581895in both cases the type is assumed to be void as opposed to old style C defaults of int return type and unknown parameter types, respectively, as in:
    21591896\begin{cfa}
    2160 [§\,§] g(); §\C{// no input or output parameters}§
    2161 [ void ] g( void ); §\C{// no input or output parameters}§
     1897[§\,§] g();                                                     §\C{// no input or output parameters}§
     1898[ void ] g( void );                                     §\C{// no input or output parameters}§
    21621899\end{cfa}
    21631900
     
    21771914\begin{cfa}
    21781915typedef int foo;
    2179 int f( int (* foo) ); §\C{// foo is redefined as a parameter name}§
     1916int f( int (* foo) );                           §\C{// foo is redefined as a parameter name}§
    21801917\end{cfa}
    21811918The string ``©int (* foo)©'' declares a C-style named-parameter of type pointer to an integer (the parenthesis are superfluous), while the same string declares a \CFA style unnamed parameter of type routine returning integer with unnamed parameter of type pointer to foo.
     
    21851922C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg:
    21861923\begin{cfa}
    2187 [ int ] f( * int, int * ); §\C{// returns an integer, accepts 2 pointers to integers}§
    2188 [ * int, int * ] f( int ); §\C{// returns 2 pointers to integers, accepts an integer}§
     1924[ int ] f( * int, int * );                      §\C{// returns an integer, accepts 2 pointers to integers}§
     1925[ * int, int * ] f( int );                      §\C{// returns 2 pointers to integers, accepts an integer}§
    21891926\end{cfa}
    21901927The reason for allowing both declaration styles in the new context is for backwards compatibility with existing preprocessor macros that generate C-style declaration-syntax, as in:
    21911928\begin{cfa}
    21921929#define ptoa( n, d ) int (*n)[ d ]
    2193 int f( ptoa( p, 5 ) ) ... §\C{// expands to int f( int (*p)[ 5 ] )}§
    2194 [ int ] f( ptoa( p, 5 ) ) ... §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§
     1930int f( ptoa( p, 5 ) ) ...                       §\C{// expands to int f( int (*p)[ 5 ] )}§
     1931[ int ] f( ptoa( p, 5 ) ) ...           §\C{// expands to [ int ] f( int (*p)[ 5 ] )}§
    21951932\end{cfa}
    21961933Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms.
     
    22141951        int z;
    22151952        ... x = 0; ... y = z; ...
    2216         ®return;® §\C{// implicitly return x, y}§
     1953        ®return;®                                                       §\C{// implicitly return x, y}§
    22171954}
    22181955\end{cfa}
     
    22241961[ int x, int y ] f() {
    22251962        ...
    2226 } §\C{// implicitly return x, y}§
     1963}                                                                               §\C{// implicitly return x, y}§
    22271964\end{cfa}
    22281965In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered.
     
    22331970[ int x, int y ] f( int, x, int y ) {
    22341971        ...
    2235 } §\C{// implicitly return x, y}§
     1972}                                                                               §\C{// implicitly return x, y}§
    22361973\end{cfa}
    22371974This notation allows the compiler to eliminate temporary variables in nested routine calls.
    22381975\begin{cfa}
    2239 [ int x, int y ] f( int, x, int y ); §\C{// prototype declaration}§
     1976[ int x, int y ] f( int, x, int y );    §\C{// prototype declaration}§
    22401977int a, b;
    22411978[a, b] = f( f( f( a, b ) ) );
     
    22511988as well, parameter names are optional, \eg:
    22521989\begin{cfa}
    2253 [ int x ] f (); §\C{// returning int with no parameters}§
    2254 [ * int ] g (int y); §\C{// returning pointer to int with int parameter}§
    2255 [ ] h ( int, char ); §\C{// returning no result with int and char parameters}§
    2256 [ * int, int ] j ( int ); §\C{// returning pointer to int and int, with int parameter}§
     1990[ int x ] f ();                                                 §\C{// returning int with no parameters}§
     1991[ * int ] g (int y);                                    §\C{// returning pointer to int with int parameter}§
     1992[ ] h ( int, char );                                    §\C{// returning no result with int and char parameters}§
     1993[ * int, int ] j ( int );                               §\C{// returning pointer to int and int, with int parameter}§
    22571994\end{cfa}
    22581995This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
     
    22752012The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
    22762013\begin{cfa}
    2277 * [ int x ] () fp; §\C{// pointer to routine returning int with no parameters}§
    2278 * [ * int ] (int y) gp; §\C{// pointer to routine returning pointer to int with int parameter}§
    2279 * [ ] (int,char) hp; §\C{// pointer to routine returning no result with int and char parameters}§
    2280 * [ * int,int ] ( int ) jp; §\C{// pointer to routine returning pointer to int and int, with int parameter}§
     2014* [ int x ] () fp;                                              §\C{// pointer to routine returning int with no parameters}§
     2015* [ * int ] (int y) gp;                                 §\C{// pointer to routine returning pointer to int with int parameter}§
     2016* [ ] (int,char) hp;                                    §\C{// pointer to routine returning no result with int and char parameters}§
     2017* [ * int,int ] ( int ) jp;                             §\C{// pointer to routine returning pointer to int and int, with int parameter}§
    22812018\end{cfa}
    22822019While parameter names are optional, \emph{a routine name cannot be specified};
    22832020for example, the following is incorrect:
    22842021\begin{cfa}
    2285 * [ int x ] f () fp; §\C{// routine name "f" is not allowed}§
     2022* [ int x ] f () fp;                                    §\C{// routine name "f" is not allowed}§
    22862023\end{cfa}
    22872024
     
    23062043whereas a named (keyword) call may be:
    23072044\begin{cfa}
    2308 p( z : 3, x : 4, y : 7 );  §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§
     2045p( z : 3, x : 4, y : 7 );       §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§
    23092046\end{cfa}
    23102047Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters.
     
    23232060For example, the following routine prototypes and definition are all valid.
    23242061\begin{cfa}
    2325 void p( int, int, int ); §\C{// equivalent prototypes}§
     2062void p( int, int, int );                        §\C{// equivalent prototypes}§
    23262063void p( int x, int y, int z );
    23272064void p( int y, int x, int z );
    23282065void p( int z, int y, int x );
    2329 void p( int q, int r, int s ) {} §\C{// match with this definition}§
     2066void p( int q, int r, int s ) {}        §\C{// match with this definition}§
    23302067\end{cfa}
    23312068Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming.
     
    23392076int f( int x, double y );
    23402077
    2341 f( j : 3, i : 4 ); §\C{// 1st f}§
    2342 f( x : 7, y : 8.1 ); §\C{// 2nd f}§
    2343 f( 4, 5 );  §\C{// ambiguous call}§
     2078f( j : 3, i : 4 );                              §\C{// 1st f}§
     2079f( x : 7, y : 8.1 );                    §\C{// 2nd f}§
     2080f( 4, 5 );                                              §\C{// ambiguous call}§
    23442081\end{cfa}
    23452082However, named arguments compound routine resolution in conjunction with conversions:
    23462083\begin{cfa}
    2347 f( i : 3, 5.7 ); §\C{// ambiguous call ?}§
     2084f( i : 3, 5.7 );                                §\C{// ambiguous call ?}§
    23482085\end{cfa}
    23492086Depending on the cost associated with named arguments, this call could be resolvable or ambiguous.
     
    23592096the allowable positional calls are:
    23602097\begin{cfa}
    2361 p(); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
    2362 p( 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
    2363 p( 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
    2364 p( 4, 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§
     2098p();                                                    §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
     2099p( 4 );                                                 §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
     2100p( 4, 4 );                                              §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
     2101p( 4, 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§
    23652102// empty arguments
    2366 p(  , 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§
    2367 p( 4,  , 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§
    2368 p( 4, 4,   ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
    2369 p( 4,  ,   ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
    2370 p(  , 4,   ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§
    2371 p(  ,  , 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§
    2372 p(  ,  ,   ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
     2103p(  , 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§
     2104p( 4,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§
     2105p( 4, 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
     2106p( 4,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
     2107p(  , 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§
     2108p(  ,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§
     2109p(  ,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
    23732110\end{cfa}
    23742111Here the missing arguments are inserted from the default values in the parameter list.
     
    23942131Default values may only appear in a prototype versus definition context:
    23952132\begin{cfa}
    2396 void p( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§
    2397 void p( int, int = 2, int = 3 ); §\C{// prototype: allowed}§
    2398 void p( int x, int y = 2, int z = 3 ) {} §\C{// definition: not allowed}§
     2133void p( int x, int y = 2, int z = 3 );          §\C{// prototype: allowed}§
     2134void p( int, int = 2, int = 3 );                        §\C{// prototype: allowed}§
     2135void p( int x, int y = 2, int z = 3 ) {}        §\C{// definition: not allowed}§
    23992136\end{cfa}
    24002137The reason for this restriction is to allow separate compilation.
     
    24212158\begin{cfa}
    24222159void p( int x, int y = 2, int z = 3... );
    2423 p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§
    2424 p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§
     2160p( 1, 4, 5, 6, z : 3 );         §\C{// assume p( /* positional */, ... , /* named */ );}§
     2161p( 1, z : 3, 4, 5, 6 );         §\C{// assume p( /* positional */, /* named */, ... );}§
    24252162\end{cfa}
    24262163The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments;
     
    24522189Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as:
    24532190\begin{cfa}
    2454 p( 1, /* default */, 5 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§
     2191p( 1, /* default */, 5 );               §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§
    24552192\end{cfa}
    24562193
     
    24652202\begin{cfa}
    24662203struct {
    2467         int f1; §\C{// named field}§
    2468         int f2 : 4; §\C{// named field with bit field size}§
    2469         int : 3; §\C{// unnamed field for basic type with bit field size}§
    2470         int ; §\C{// disallowed, unnamed field}§
    2471         int *; §\C{// disallowed, unnamed field}§
    2472         int (*)( int ); §\C{// disallowed, unnamed field}§
     2204        int f1;                                 §\C{// named field}§
     2205        int f2 : 4;                             §\C{// named field with bit field size}§
     2206        int : 3;                                §\C{// unnamed field for basic type with bit field size}§
     2207        int ;                                   §\C{// disallowed, unnamed field}§
     2208        int *;                                  §\C{// disallowed, unnamed field}§
     2209        int (*)( int );                 §\C{// disallowed, unnamed field}§
    24732210};
    24742211\end{cfa}
     
    24782215\begin{cfa}
    24792216struct {
    2480         int , , ; §\C{// 3 unnamed fields}§
     2217        int , , ;                               §\C{// 3 unnamed fields}§
    24812218}
    24822219\end{cfa}
     
    25252262        struct T t;
    25262263} s;
    2527 
     2264       
    25282265
    25292266
     
    25722309const unsigned int size = 5;
    25732310int ia[size];
    2574 ... §\C{// assign values to array ia}§
    2575 qsort( ia, size ); §\C{// sort ascending order using builtin ?<?}§
     2311...                                             §\C{// assign values to array ia}§
     2312qsort( ia, size );              §\C{// sort ascending order using builtin ?<?}§
    25762313{
    25772314        ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§
    2578         qsort( ia, size ); §\C{// sort descending order by local redefinition}§
     2315        qsort( ia, size );      §\C{// sort descending order by local redefinition}§
    25792316}
    25802317\end{cfa}
     
    25842321The following program in undefined in \CFA (and Indexc{gcc})
    25852322\begin{cfa}
    2586 [* [int]( int )] foo() { §\C{// int (* foo())( int )}§
     2323[* [int]( int )] foo() {                §\C{// int (* foo())( int )}§
    25872324        int ®i® = 7;
    25882325        int bar( int p ) {
    2589                 ®i® += 1; §\C{// dependent on local variable}§
    2590                 sout | ®i®;
     2326                ®i® += 1;                               §\C{// dependent on local variable}§
     2327                sout | ®i® | endl;
    25912328        }
    2592         return bar; §\C{// undefined because of local dependence}§
     2329        return bar;                                     §\C{// undefined because of local dependence}§
    25932330}
    25942331int main() {
    2595         * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§
    2596         sout | fp( 3 );
    2597 }
    2598 \end{cfa}
    2599 because
     2332        * [int]( int ) fp = foo();      §\C{// int (* fp)( int )}§
     2333        sout | fp( 3 ) | endl;
     2334}
     2335\end{cfa}
     2336because 
    26002337
    26012338Currently, there are no \Index{lambda} expressions, \ie unnamed routines because routine names are very important to properly select the correct routine.
     
    26062343In C and \CFA, lists of elements appear in several contexts, such as the parameter list of a routine call.
    26072344\begin{cfa}
    2608 f( ®2, x, 3 + i® ); §\C{// element list}§
     2345f( ®2, x, 3 + i® );                             §\C{// element list}§
    26092346\end{cfa}
    26102347A list of elements is called a \newterm{tuple}, and is different from a \Index{comma expression}.
     
    26232360typedef struct { int quot, rem; } div_t;        §\C[7cm]{// from include stdlib.h}§
    26242361div_t div( int num, int den );
    2625 div_t qr = div( 13, 5 ); §\C{// return quotient/remainder aggregate}§
    2626 printf( "%d %d\n", qr.quot, qr.rem ); §\C{// print quotient/remainder}§
     2362div_t qr = div( 13, 5 );                                        §\C{// return quotient/remainder aggregate}§
     2363printf( "%d %d\n", qr.quot, qr.rem );           §\C{// print quotient/remainder}§
    26272364\end{cfa}
    26282365This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue.
     
    26342371For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value.
    26352372\begin{cfa}
    2636 double modf( double x, double * i ); §\C{// from include math.h}§
    2637 double intp, frac = modf( 13.5, &intp ); §\C{// return integral and fractional components}§
    2638 printf( "%g %g\n", intp, frac ); §\C{// print integral/fractional components}§
     2373double modf( double x, double * i );            §\C{// from include math.h}§
     2374double intp, frac = modf( 13.5, &intp );        §\C{// return integral and fractional components}§
     2375printf( "%g %g\n", intp, frac );                        §\C{// print integral/fractional components}§
    26392376\end{cfa}
    26402377This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call.
     
    26632400When a function call is passed as an argument to another call, the best match of actual arguments to formal parameters is evaluated given all possible expression interpretations in the current scope.
    26642401\begin{cfa}
    2665 void g( int, int ); §\C{// 1}§
    2666 void g( double, double ); §\C{// 2}§
    2667 g( div( 13, 5 ) ); §\C{// select 1}§
    2668 g( modf( 13.5 ) ); §\C{// select 2}§
     2402void g( int, int );                                                     §\C{// 1}§
     2403void g( double, double );                                       §\C{// 2}§
     2404g( div( 13, 5 ) );                                                      §\C{// select 1}§
     2405g( modf( 13.5 ) );                                                      §\C{// select 2}§
    26692406\end{cfa}
    26702407In this case, there are two overloaded ©g© routines.
     
    26752412The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call.
    26762413\begin{cfa}
    2677 [ int, int ] div( int x, int y ); §\C{// from include stdlib}§
    2678 printf( "%d %d\n", div( 13, 5 ) ); §\C{// print quotient/remainder}§
    2679 
    2680 [ double, double ] modf( double x ); §\C{// from include math}§
    2681 printf( "%g %g\n", modf( 13.5 ) ); §\C{// print integral/fractional components}§
     2414[ int, int ] div( int x, int y );                       §\C{// from include stdlib}§
     2415printf( "%d %d\n", div( 13, 5 ) );                      §\C{// print quotient/remainder}§
     2416
     2417[ double, double ] modf( double x );            §\C{// from include math}§
     2418printf( "%g %g\n", modf( 13.5 ) );                      §\C{// print integral/fractional components}§
    26822419\end{cfa}
    26832420This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type.
     
    26892426\begin{cfa}
    26902427int quot, rem;
    2691 [ quot, rem ] = div( 13, 5 ); §\C{// assign multiple variables}§
    2692 printf( "%d %d\n", quot, rem ); §\C{// print quotient/remainder}\CRT§
     2428[ quot, rem ] = div( 13, 5 );                           §\C{// assign multiple variables}§
     2429printf( "%d %d\n", quot, rem );                         §\C{// print quotient/remainder}\CRT§
    26932430\end{cfa}
    26942431Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call.
     
    26962433
    26972434\subsection{Expressions}
    2698 
    2699 % Change order of expression evaluation.
    2700 % http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0145r2.pdf
    27012435
    27022436Multiple-return-value functions provide \CFA with a new syntax for expressing a combination of expressions in the return statement and a combination of types in a function signature.
     
    27192453In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}.
    27202454\begin{cfa}
    2721 [int, int] ®qr® = div( 13, 5 ); §\C{// initialize tuple variable}§
    2722 printf( "%d %d\n", ®qr® ); §\C{// print quotient/remainder}§
     2455[int, int] ®qr® = div( 13, 5 );                 §\C{// initialize tuple variable}§
     2456printf( "%d %d\n", ®qr® );                              §\C{// print quotient/remainder}§
    27232457\end{cfa}
    27242458It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}.
     
    27262460One way to access the individual components of a tuple variable is with assignment.
    27272461\begin{cfa}
    2728 [ quot, rem ] = qr; §\C{// assign multiple variables}§
     2462[ quot, rem ] = qr;                                             §\C{// assign multiple variables}§
    27292463\end{cfa}
    27302464
     
    27492483[int, double] * p;
    27502484
    2751 int y = x.0; §\C{// access int component of x}§
    2752 y = f().1; §\C{// access int component of f}§
    2753 p->0 = 5; §\C{// access int component of tuple pointed-to by p}§
    2754 g( x.1, x.0 ); §\C{// rearrange x to pass to g}§
    2755 double z = [ x, f() ].0.1; §\C{// access second component of first component of tuple expression}§
     2485int y = x.0;                                                    §\C{// access int component of x}§
     2486y = f().1;                                                              §\C{// access int component of f}§
     2487p->0 = 5;                                                               §\C{// access int component of tuple pointed-to by p}§
     2488g( x.1, x.0 );                                                  §\C{// rearrange x to pass to g}§
     2489double z = [ x, f() ].0.1;                              §\C{// access second component of first component of tuple expression}§
    27562490\end{cfa}
    27572491Tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple.
     
    28202554double y;
    28212555[int, double] z;
    2822 [y, x] = 3.14; §\C{// mass assignment}§
     2556[y, x] = 3.14;                                                  §\C{// mass assignment}§
    28232557[x, y] = z;                                                         §\C{// multiple assignment}§
    28242558z = 10;                                                         §\C{// mass assignment}§
    2825 z = [x, y]; §\C{// multiple assignment}§
     2559z = [x, y];                                                             §\C{// multiple assignment}§
    28262560\end{cfa}
    28272561Let $L_i$ for $i$ in $[0, n)$ represent each component of the flattened left side, $R_i$ represent each component of the flattened right side of a multiple assignment, and $R$ represent the right side of a mass assignment.
     
    28672601        double c, d;
    28682602        [ void ] f( [ int, int ] );
    2869         f( [ c, a ] = [ b, d ] = 1.5 ); §\C{// assignments in parameter list}§
     2603        f( [ c, a ] = [ b, d ] = 1.5 );  // assignments in parameter list
    28702604\end{cfa}
    28712605The tuple expression begins with a mass assignment of ©1.5© into ©[b, d]©, which assigns ©1.5© into ©b©, which is truncated to ©1©, and ©1.5© into ©d©, producing the tuple ©[1, 1.5]© as a result.
     
    28802614\begin{cfa}
    28812615struct S;
    2882 void ?{}(S *); §\C{// (1)}§
    2883 void ?{}(S *, int); §\C{// (2)}§
    2884 void ?{}(S * double); §\C{// (3)}§
    2885 void ?{}(S *, S); §\C{// (4)}§
    2886 
    2887 [S, S] x = [3, 6.28]; §\C{// uses (2), (3), specialized constructors}§
    2888 [S, S] y; §\C{// uses (1), (1), default constructor}§
    2889 [S, S] z = x.0; §\C{// uses (4), (4), copy constructor}§
     2616void ?{}(S *);         // (1)
     2617void ?{}(S *, int);    // (2)
     2618void ?{}(S * double);  // (3)
     2619void ?{}(S *, S);      // (4)
     2620
     2621[S, S] x = [3, 6.28];  // uses (2), (3), specialized constructors
     2622[S, S] y;              // uses (1), (1), default constructor
     2623[S, S] z = x.0;        // uses (4), (4), copy constructor
    28902624\end{cfa}
    28912625In this example, ©x© is initialized by the multiple constructor calls ©?{}(&x.0, 3)© and ©?{}(&x.1, 6.28)©, while ©y© is initialized by two default constructor calls ©?{}(&y.0)© and ©?{}(&y.1)©.
     
    29282662A member-access tuple may be used anywhere a tuple can be used, \eg:
    29292663\begin{cfa}
    2930 s.[ y, z, x ] = [ 3, 3.2, 'x' ]; §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§
    2931 f( s.[ y, z ] ); §\C{// equivalent to f( s.y, s.z )}§
     2664s.[ y, z, x ] = [ 3, 3.2, 'x' ];                §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§
     2665f( s.[ y, z ] );                                                §\C{// equivalent to f( s.y, s.z )}§
    29322666\end{cfa}
    29332667Note, the fields appearing in a record-field tuple may be specified in any order;
     
    29392673void f( double, long );
    29402674
    2941 f( x.[ 0, 3 ] ); §\C{// f( x.0, x.3 )}§
    2942 x.[ 0, 1 ] = x.[ 1, 0 ]; §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§
     2675f( x.[ 0, 3 ] );                                                §\C{// f( x.0, x.3 )}§
     2676x.[ 0, 1 ] = x.[ 1, 0 ];                                §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§
    29432677[ long, int, long ] y = x.[ 2, 0, 2 ];
    29442678\end{cfa}
     
    29572691\begin{cfa}
    29582692[ int, float, double ] f();
    2959 [ double, float ] x = f().[ 2, 1 ]; §\C{// f() called once}§
     2693[ double, float ] x = f().[ 2, 1 ];             §\C{// f() called once}§
    29602694\end{cfa}
    29612695
     
    29702704That is, a cast can be used to select the type of an expression when it is ambiguous, as in the call to an overloaded function.
    29712705\begin{cfa}
    2972 int f(); §\C{// (1)}§
    2973 double f(); §\C{// (2)}§
    2974 
    2975 f(); §\C{// ambiguous - (1),(2) both equally viable}§
    2976 (int)f(); §\C{// choose (2)}§
     2706int f();     // (1)
     2707double f();  // (2)
     2708
     2709f();       // ambiguous - (1),(2) both equally viable
     2710(int)f();  // choose (2)
    29772711\end{cfa}
    29782712Since casting is a fundamental operation in \CFA, casts need to be given a meaningful interpretation in the context of tuples.
     
    29822716void g();
    29832717
    2984 (void)f(); §\C{// valid, ignore results}§
    2985 (int)g(); §\C{// invalid, void cannot be converted to int}§
     2718(void)f();  // valid, ignore results
     2719(int)g();   // invalid, void cannot be converted to int
    29862720
    29872721struct A { int x; };
    2988 (struct A)f(); §\C{// invalid, int cannot be converted to A}§
     2722(struct A)f();  // invalid, int cannot be converted to A
    29892723\end{cfa}
    29902724In C, line 4 is a valid cast, which calls ©f© and discards its result.
     
    30022736        [int, [int, int], int] g();
    30032737
    3004         ([int, double])f(); §\C{// (1) valid}§
    3005         ([int, int, int])g(); §\C{// (2) valid}§
    3006         ([void, [int, int]])g(); §\C{// (3) valid}§
    3007         ([int, int, int, int])g(); §\C{// (4) invalid}§
    3008         ([int, [int, int, int]])g(); §\C{// (5) invalid}§
     2738        ([int, double])f();           // (1) valid
     2739        ([int, int, int])g();         // (2) valid
     2740        ([void, [int, int]])g();      // (3) valid
     2741        ([int, int, int, int])g();    // (4) invalid
     2742        ([int, [int, int, int]])g();  // (5) invalid
    30092743\end{cfa}
    30102744
     
    30662800void f([int, int], int, int);
    30672801
    3068 f([0, 0], 0, 0); §\C{// no cost}§
    3069 f(0, 0, 0, 0); §\C{// cost for structuring}§
    3070 f([0, 0,], [0, 0]); §\C{// cost for flattening}§
    3071 f([0, 0, 0], 0); §\C{// cost for flattening and structuring}§
     2802f([0, 0], 0, 0);    // no cost
     2803f(0, 0, 0, 0);      // cost for structuring
     2804f([0, 0,], [0, 0]); // cost for flattening
     2805f([0, 0, 0], 0);    // cost for flattening and structuring
    30722806\end{cfa}
    30732807
     
    31322866[ unsigned int, char ]
    31332867[ double, double, double ]
    3134 [ * int, int * ] §\C{// mix of CFA and ANSI}§
     2868[ * int, int * ]                §\C{// mix of CFA and ANSI}§
    31352869[ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ]
    31362870\end{cfa}
     
    31392873Examples of declarations using tuple types are:
    31402874\begin{cfa}
    3141 [ int, int ] x; §\C{// 2 element tuple, each element of type int}§
    3142 * [ char, char ] y; §\C{// pointer to a 2 element tuple}§
     2875[ int, int ] x;                 §\C{// 2 element tuple, each element of type int}§
     2876* [ char, char ] y;             §\C{// pointer to a 2 element tuple}§
    31432877[ [ int, int ] ] z ([ int, int ]);
    31442878\end{cfa}
     
    31572891[ int, int ] w1;
    31582892[ int, int, int ] w2;
    3159 [ void ] f (int, int, int); §\C{// three input parameters of type int}§
    3160 [ void ] g ([ int, int, int ]); §\C{3 element tuple as input}§
     2893[ void ] f (int, int, int); /* three input parameters of type int */
     2894[ void ] g ([ int, int, int ]); /* 3 element tuple as input */
    31612895f( [ 1, 2, 3 ] );
    31622896f( w1, 3 );
     
    32382972[ int, int, int, int ] w = [ 1, 2, 3, 4 ];
    32392973int x = 5;
    3240 [ x, w ] = [ w, x ]; §\C{// all four tuple coercions}§
     2974[ x, w ] = [ w, x ];            §\C{// all four tuple coercions}§
    32412975\end{cfa}
    32422976Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values;
     
    33263060both these examples produce indeterminate results:
    33273061\begin{cfa}
    3328 f( x++, x++ ); §\C{// C routine call with side effects in arguments}§
    3329 [ v1, v2 ] = [ x++, x++ ]; §\C{// side effects in righthand side of multiple assignment}§
     3062f( x++, x++ );                          §\C{// C routine call with side effects in arguments}§
     3063[ v1, v2 ] = [ x++, x++ ];      §\C{// side effects in righthand side of multiple assignment}§
    33303064\end{cfa}
    33313065
     
    33493083
    33503084
    3351 \section{Stream I/O Library}
    3352 \label{s:StreamIOLibrary}
    3353 \index{input/output stream library}
    3354 \index{stream library}
    3355 
    3356 The goal of \CFA stream input/output (I/O) is to simplify the common cases\index{I/O!common case}, while fully supporting polymorphism and user defined types in a consistent way.
    3357 Stream I/O can be implicitly or explicitly formatted.
    3358 Implicit formatting means \CFA selects the output or input format for values that match with the type of a variable.
    3359 Explicit formatting means additional information is specified to augment how an output or input of value is interpreted.
    3360 \CFA formatting is a cross between C ©printf© and \CC ©cout© manipulators, and Python implicit spacing and newline.
    3361 Specifically:
    3362 \begin{itemize}
    3363 \item
    3364 ©printf©/Python format codes are dense, making them difficult to read and remember.
    3365 \CFA/\CC format manipulators are named, making them easier to read and remember.
    3366 \item
    3367 ©printf©/Python separates format codes from associated variables, making it difficult to match codes with variables.
    3368 \CFA/\CC co-locate codes with associated variables, where \CFA has the tighter binding.
    3369 \item
    3370 Format manipulators in \CFA have local effect, whereas \CC have global effect, except ©setw©.
    3371 Hence, it is common programming practice to toggle manipulators on and then back to the default to prevent downstream side-effects.
    3372 Without this programming style, errors occur when moving prints, as manipulator effects incorrectly flow into the new location.
    3373 (To guarantee no side-effects, manipulator values must be saved and restored across function calls.)
    3374 \item
    3375 \CFA has more sophisticated implicit spacing between values than Python, plus implicit newline at the end of a print.
    3376 \end{itemize}
    3377 The \CFA header file for the I/O library is \Indexc{fstream.hfa}.
    3378 
    3379 For implicit formatted output, the common case is printing a series of variables separated by whitespace.
     3085\section{I/O Library}
     3086\label{s:IOLibrary}
     3087\index{input/output library}
     3088
     3089The goal of \CFA I/O is to simplify the common cases\index{I/O!common case}, while fully supporting polymorphism and user defined types in a consistent way.
     3090The approach combines ideas from \CC and Python.
     3091The \CFA header file for the I/O library is \Indexc{fstream}.
     3092
     3093The common case is printing out a sequence of variables separated by whitespace.
    33803094\begin{cquote}
    3381 \begin{tabular}{@{}l@{\hspace{2em}}l@{\hspace{2em}}l@{}}
    3382 \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}}       & \multicolumn{1}{c}{\textbf{Python}}   \\
     3095\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     3096\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{\CC}}      \\
    33833097\begin{cfa}
    33843098int x = 1, y = 2, z = 3;
    3385 sout | x ®|® y ®|® z;
     3099sout | x ®|® y ®|® z | endl;
    33863100\end{cfa}
    33873101&
     
    33893103
    33903104cout << x ®<< " "® << y ®<< " "® << z << endl;
    3391 \end{cfa}
    3392 &
    3393 \begin{cfa}
    3394 x = 1;  y = 2;  z = 3
    3395 print( x, y, z )
    33963105\end{cfa}
    33973106\\
     
    34013110&
    34023111\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3403 1® ®2® ®3
    3404 \end{cfa}
    3405 &
    3406 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3407 1® ®2® ®3
     31121 2 3
    34083113\end{cfa}
    34093114\end{tabular}
    34103115\end{cquote}
    3411 The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators and newline.
    3412 Similar simplification occurs for \Index{tuple} I/O, which flattens the tuple and prints each value separated by ``\lstinline[showspaces=true]@, @''.
     3116The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators.
     3117Similar simplification occurs for \Index{tuple} I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
    34133118\begin{cfa}
    34143119[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];
    3415 sout | t1 | t2; §\C{// print tuples}§
     3120sout | t1 | t2 | endl;                                  §\C{// print tuples}§
    34163121\end{cfa}
    34173122\begin{cfa}[showspaces=true,aboveskip=0pt]
    341831231®, ®2®, ®3 4®, ®5®, ®6
    34193124\end{cfa}
    3420 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority \emph{overloadable} operator, other than assignment.
     3125Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment.
    34213126Therefore, fewer output expressions require parenthesis.
    34223127\begin{cquote}
     
    34253130&
    34263131\begin{cfa}
    3427 sout | x * 3 | y + 1 | z << 2 | x == y | ®(®x | y®)® | ®(®x || y®)® | ®(®x > z ? 1 : 2®)®;
     3132sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl;
    34283133\end{cfa}
    34293134\\
     
    34313136&
    34323137\begin{cfa}
    3433 cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << ®(®x | y®)® << ®(®x || y®)® << ®(®x > z ? 1 : 2®)® << endl;
     3138cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << (x | y) << (x || y) << (x > z ? 1 : 2) << endl;
    34343139\end{cfa}
    34353140\\
     
    34403145\end{tabular}
    34413146\end{cquote}
    3442 Input and output use a uniform operator, ©|©, rather than separate operators, as in ©>>© and ©<<© for \CC.
    3443 There is a weak similarity between the \CFA logical-or operator and the \Index{Shell pipe-operator} for moving data, where data flows in the correct direction for input but the opposite direction for output.
    3444 
    3445 For implicit formatted input, the common case is reading a sequence of values separated by whitespace, where the type of an input constant must match with the type of the input variable.
    3446 \begin{cquote}
    3447 \begin{lrbox}{\LstBox}
    3448 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    3449 int x;   double y   char z;
    3450 \end{cfa}
    3451 \end{lrbox}
    3452 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}}
    3453 \multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\
    3454 \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}}       & \multicolumn{1}{c}{\textbf{Python}}   \\
    3455 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    3456 sin | x | y | z;
    3457 \end{cfa}
    3458 &
    3459 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    3460 cin >> x >> y >> z;
    3461 \end{cfa}
    3462 &
    3463 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    3464 x = int(input());  y = float(input());  z = input();
    3465 \end{cfa}
    3466 \\
    3467 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3468 ®1® ®2.5® ®A®
    3469 
    3470 
    3471 \end{cfa}
    3472 &
    3473 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3474 ®1® ®2.5® ®A®
    3475 
    3476 
    3477 \end{cfa}
    3478 &
    3479 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3480 ®1®
    3481 ®2.5®
    3482 ®A®
    3483 \end{cfa}
    3484 \end{tabular}
    3485 \end{cquote}
    3486 
     3147There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
    34873148
    34883149
    34893150\subsection{Implicit Separator}
    34903151
    3491 The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator for output.
     3152The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator.
    34923153The rules for implicitly adding the separator are:
    34933154\begin{enumerate}
     
    34953156A separator does not appear at the start or end of a line.
    34963157\begin{cfa}[belowskip=0pt]
    3497 sout | 1 | 2 | 3;
     3158sout | 1 | 2 | 3 | endl;
    34983159\end{cfa}
    34993160\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    35043165A separator does not appear before or after a character literal or variable.
    35053166\begin{cfa}
    3506 sout | '1' | '2' | '3';
     3167sout | '1' | '2' | '3' | endl;
    35073168123
    35083169\end{cfa}
    35093170
    35103171\item
    3511 A separator does not appear before or after a null (empty) C string, which is a local mechanism to disable insertion of the separator character.
    3512 \begin{cfa}
    3513 sout | 1 | "" | 2 | "" | 3;
     3172A separator does not appear before or after a null (empty) C string.
     3173\begin{cfa}
     3174sout | 1 | "" | 2 | "" | 3 | endl;
    35143175123
    35153176\end{cfa}
     3177which is a local mechanism to disable insertion of the separator character.
     3178
     3179\item
     3180A separator does not appear before a C string starting with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$£¥¡¿«@
     3181%$
     3182\begin{cfa}[mathescape=off]
     3183sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥"
     3184                | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10 | endl;
     3185\end{cfa}
     3186%$
     3187\begin{cfa}[mathescape=off,basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt]
     3188x ®(®1 x ®[®2 x ®{®3 x ®=®4 x ®$®5 x ®£®6 x ®¥®7 x ®¡®8 x ®¿®9 x ®«®10
     3189\end{cfa}
     3190%$
     3191where \lstinline[basicstyle=\tt]@¡¿@ are inverted opening exclamation and question marks, and \lstinline[basicstyle=\tt]@«@ is an opening citation mark.
    35163192
    35173193\item
    35183194{\lstset{language=CFA,deletedelim=**[is][]{¢}{¢}}
    3519 A separator does not appear before a C string starting with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[basicstyle=\tt]@,.;!?)]}%¢»@, where \lstinline[basicstyle=\tt]@»@ is a closing citation mark.
     3195A seperator does not appear after a C string ending with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[basicstyle=\tt]@,.;!?)]}%¢»@
    35203196\begin{cfa}[belowskip=0pt]
    35213197sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x"
    3522                 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";
     3198                | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x" | endl;
    35233199\end{cfa}
    35243200\begin{cfa}[basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt]
    352532011®,® x 2®.® x 3®;® x 4®!® x 5®?® x 6®%® x 7§\color{red}\textcent§ x 8®»® x 9®)® x 10®]® x 11®}® x
    35263202\end{cfa}}%
    3527 
    3528 \item
    3529 A separator does not appear after a C string ending with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$£¥¡¿«@, where \lstinline[basicstyle=\tt]@¡¿@ are inverted opening exclamation and question marks, and \lstinline[basicstyle=\tt]@«@ is an opening citation mark.
    3530 %$
    3531 \begin{cfa}[mathescape=off]
    3532 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥"
    3533                 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;
    3534 \end{cfa}
    3535 %$
    3536 \begin{cfa}[mathescape=off,basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt]
    3537 x ®(®1 x ®[®2 x ®{®3 x ®=®4 x ®$®5 x ®£®6 x ®¥®7 x ®¡®8 x ®¿®9 x ®«®10
    3538 \end{cfa}
    3539 %$
    3540 
    3541 \item
    3542 A seperator does not appear before/after a C string starting/ending with the \Index*{ASCII} quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]@`'": \t\v\f\r\n@
     3203where \lstinline[basicstyle=\tt]@»@ is a closing citation mark.
     3204
     3205\item
     3206A seperator does not appear before or after a C string begining/ending with the \Index*{ASCII} quote or whitespace characters: \lstinline[basicstyle=\tt,showspaces=true]@`'": \t\v\f\r\n@
    35433207\begin{cfa}[belowskip=0pt]
    3544 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx";
     3208sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx" | endl;
    35453209\end{cfa}
    35463210\begin{cfa}[basicstyle=\tt,showspaces=true,showtabs=true,aboveskip=0pt,belowskip=0pt]
     
    35513215If a space is desired before or after one of the special string start/end characters, simply insert a space.
    35523216\begin{cfa}[belowskip=0pt]
    3553 sout | "x (§\color{red}\texttt{\textvisiblespace}§" | 1 | "§\color{red}\texttt{\textvisiblespace}§) x" | 2 | "§\color{red}\texttt{\textvisiblespace}§, x" | 3 | "§\color{red}\texttt{\textvisiblespace}§:x:§\color{red}\texttt{\textvisiblespace}§" | 4;
     3217sout | "x (§\color{red}\texttt{\textvisiblespace}§" | 1 | "§\color{red}\texttt{\textvisiblespace}§) x" | 2 | "§\color{red}\texttt{\textvisiblespace}§, x" | 3 | "§\color{red}\texttt{\textvisiblespace}§:x:§\color{red}\texttt{\textvisiblespace}§" | 4 | endl;
    35543218\end{cfa}
    35553219\begin{cfa}[basicstyle=\tt,showspaces=true,showtabs=true,aboveskip=0pt,belowskip=0pt]
     
    35593223
    35603224
    3561 \subsection{Separation Manipulators}
    3562 
    3563 The following \Index{manipulator}s control \Index{implicit output separation}.
    3564 The effect of these manipulators is global for an output stream (except ©sepOn© and ©sepOff©).
     3225\subsection{Manipulator}
     3226
     3227The following \CC-style \Index{manipulator}s and routines control implicit seperation.
    35653228\begin{enumerate}
    35663229\item
    3567 \Indexc{sepSet}\index{manipulator!sepSet@©sepSet©} and \Indexc{sep}\index{manipulator!sep@©sep©}/\Indexc{sepGet}\index{manipulator!sepGet@©sepGet©} set and get the separator string.
     3230Routines \Indexc{sepSet}\index{manipulator!sepSet@©sepSet©} and \Indexc{sep}\index{manipulator!sep@©sep©}/\Indexc{sepGet}\index{manipulator!sepGet@©sepGet©} set and get the separator string.
    35683231The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    35693232\begin{cfa}[mathescape=off,belowskip=0pt]
    3570 sepSet( sout, ", $" ); §\C{// set separator from " " to ", \$"}§
    3571 sout | 1 | 2 | 3 | " \"" | ®sep® | "\"";
     3233sepSet( sout, ", $" );                                          §\C{// set separator from " " to ", \$"}§
     3234sout | 1 | 2 | 3 | " \"" | ®sep® | "\"" | endl;
    35723235\end{cfa}
    35733236%$
     
    35773240%$
    35783241\begin{cfa}[belowskip=0pt]
    3579 sepSet( sout, " " ); §\C{// reset separator to " "}§
    3580 sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\"";
     3242sepSet( sout, " " );                                            §\C{// reset separator to " "}§
     3243sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\"" | endl;
    35813244\end{cfa}
    35823245\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    35853248©sepGet© can be used to store a separator and then restore it:
    35863249\begin{cfa}[belowskip=0pt]
    3587 char store[®sepSize®]; §\C{// sepSize is the maximum separator size}§
    3588 strcpy( store, sepGet( sout ) ); §\C{// copy current separator}§
    3589 sepSet( sout, "_" ); §\C{// change separator to underscore}§
    3590 sout | 1 | 2 | 3;
     3250char store[®sepSize®];                                          §\C{// sepSize is the maximum separator size}§
     3251strcpy( store, sepGet( sout ) );                          §\C{// copy current separator}§
     3252sepSet( sout, "_" );                                            §\C{// change separator to underscore}§
     3253sout | 1 | 2 | 3 | endl;
    35913254\end{cfa}
    35923255\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    35943257\end{cfa}
    35953258\begin{cfa}[belowskip=0pt]
    3596 sepSet( sout, store ); §\C{// change separator back to original}§
    3597 sout | 1 | 2 | 3;
     3259sepSet( sout, store );                                          §\C{// change separator back to original}§
     3260sout | 1 | 2 | 3 | endl;
    35983261\end{cfa}
    35993262\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    36023265
    36033266\item
    3604 \Indexc{sepSetTuple}\index{manipulator!sepSetTuple@©sepSetTuple©} and \Indexc{sepTuple}\index{manipulator!sepTuple@©sepTuple©}/\Indexc{sepGetTuple}\index{manipulator!sepGetTuple@©sepGetTuple©} get and set the tuple separator-string.
     3267Routine \Indexc{sepSetTuple}\index{manipulator!sepSetTuple@©sepSetTuple©} and \Indexc{sepTuple}\index{manipulator!sepTuple@©sepTuple©}/\Indexc{sepGetTuple}\index{manipulator!sepGetTuple@©sepGetTuple©} get and set the tuple separator-string.
    36053268The tuple separator-string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    36063269\begin{cfa}[belowskip=0pt]
    3607 sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§
    3608 sout | t1 | t2 | " \"" | ®sepTuple® | "\"";
     3270sepSetTuple( sout, " " );                                       §\C{// set tuple separator from ", " to " "}§
     3271sout | t1 | t2 | " \"" | ®sepTuple® | "\"" | endl;
    36093272\end{cfa}
    36103273\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    36123275\end{cfa}
    36133276\begin{cfa}[belowskip=0pt]
    3614 sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§
    3615 sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\"";
     3277sepSetTuple( sout, ", " );                                      §\C{// reset tuple separator to ", "}§
     3278sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\"" | endl;
    36163279\end{cfa}
    36173280\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    36213284
    36223285\item
    3623 \Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} toggle printing the separator.
     3286Manipulators \Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} \emph{globally} toggle printing the separator, \ie the seperator is adjusted with respect to all subsequent printed items.
    36243287\begin{cfa}[belowskip=0pt]
    3625 sout | sepDisable | 1 | 2 | 3; §\C{// turn off implicit separator}§
     3288sout | sepDisable | 1 | 2 | 3 | endl;           §\C{// globally turn off implicit separator}§
    36263289\end{cfa}
    36273290\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    36293292\end{cfa}
    36303293\begin{cfa}[belowskip=0pt]
    3631 sout | sepEnable | 1 | 2 | 3; §\C{// turn on implicit separator}§
     3294sout | sepEnable | 1 | 2 | 3 | endl;            §\C{// globally turn on implicit separator}§
    36323295\end{cfa}
    36333296\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    36363299
    36373300\item
    3638 \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} and \Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} toggle printing the separator with respect to the next printed item, and then return to the global seperator setting.
     3301Manipulators \Indexc{sepOn}\index{manipulator!sepOn@©sepOn©} and \Indexc{sepOff}\index{manipulator!sepOff@©sepOff©} \emph{locally} toggle printing the separator, \ie the seperator is adjusted only with respect to the next printed item.
    36393302\begin{cfa}[belowskip=0pt]
    3640 sout | 1 | sepOff | 2 | 3; §\C{// turn off implicit separator for the next item
     3303sout | 1 | sepOff | 2 | 3 | endl;                       §\C{// locally turn off implicit separator
    36413304\end{cfa}
    36423305\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    36443307\end{cfa}
    36453308\begin{cfa}[belowskip=0pt]
    3646 sout | sepDisable | 1 | sepOn | 2 | 3; §\C{// turn on implicit separator for the next item
     3309sout | sepDisable | 1 | sepOn | 2 | 3 | endl; §\C{// locally turn on implicit separator
    36473310\end{cfa}
    36483311\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    36513314The tuple separator also responses to being turned on and off.
    36523315\begin{cfa}[belowskip=0pt]
    3653 sout | t1 | sepOff | t2; §\C{// turn off implicit separator for the next item
     3316sout | t1 | sepOff | t2 | endl;                         §\C{// locally turn on/off implicit separator
    36543317\end{cfa}
    36553318\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    36593322use ©sep© to accomplish this functionality.
    36603323\begin{cfa}[belowskip=0pt]
    3661 sout | sepOn | 1 | 2 | 3 | sepOn; §\C{// sepOn does nothing at start/end of line}§
     3324sout | sepOn | 1 | 2 | 3 | sepOn | endl ;       §\C{// sepOn does nothing at start/end of line}§
    36623325\end{cfa}
    36633326\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    36653328\end{cfa}
    36663329\begin{cfa}[belowskip=0pt]
    3667 sout | sep | 1 | 2 | 3 | sep ; §\C{// use sep to print separator at start/end of line}§
     3330sout | sep | 1 | 2 | 3 | sep | endl ;           §\C{// use sep to print separator at start/end of line}§
    36683331\end{cfa}
    36693332\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    36703333® ®1 2 3® ®
    3671 \end{cfa}
    3672 \end{enumerate}
    3673 
    3674 
    3675 \subsection{Newline Manipulators}
    3676 
    3677 The following \Index{manipulators} control \Index{newline separation} for input and output.
    3678 
    3679 For input:
    3680 \begin{enumerate}[parsep=0pt]
    3681 \item
    3682 \Indexc{nl}\index{manipulator!nl@©nl©} scans characters until the next newline character, i.e., ignore the remaining characters in the line.
    3683 \item
    3684 \Indexc{nlOn}\index{manipulator!nlOn@©nlOn©} reads the newline character, when reading single characters.
    3685 \item
    3686 \Indexc{nlOff}\index{manipulator!nlOff@©nlOff©} does \emph{not} read the newline character, when reading single characters.
    3687 \end{enumerate}
    3688 For example, in:
    3689 \begin{cfa}
    3690 sin | i | ®nl® | j;
    3691 1 ®2®
    3692 3
    3693 \end{cfa}
    3694 variable ©i© is assigned 1, the 2 is skipped, and variable ©j© is assigned 3.
    3695 
    3696 For output:
    3697 \begin{enumerate}[parsep=0pt]
    3698 \item
    3699 \Indexc{nl}\index{manipulator!nl@©nl©} inserts a newline.
    3700 \begin{cfa}
    3701 sout | nl; §\C{// only print newline}§
    3702 sout | 2; §\C{// implicit newline}§
    3703 sout | 3 | nl | 4 | nl; §\C{// terminating nl merged with implicit newline}§
    3704 sout | 5 | nl | nl; §\C{// again terminating nl merged with implicit newline}§
    3705 sout | 6; §\C{// implicit newline}§
    3706 
    3707 2
    3708 3
    3709 4
    3710 5
    3711 
    3712 6
    3713 \end{cfa}
    3714 Note, a terminating ©nl© is merged (overrides) with the implicit newline at the end of the ©sout© expression, otherwise it is impossible to to print a single newline
    3715 \item
    3716 \Indexc{nlOn}\index{manipulator!nlOn@©nlOn©} implicitly prints a newline at the end of each output expression.
    3717 \item
    3718 \Indexc{nlOff}\index{manipulator!nlOff@©nlOff©} does \emph{not} implicitly print a newline at the end of each output expression.
    3719 \end{enumerate}
    3720 
    3721 
    3722 \subsection{Output Value Manipulators}
    3723 
    3724 The following \Index{manipulator}s control formatting of output values (printing), and only affect the format of the argument.
    3725 \begin{enumerate}
    3726 \item
    3727 \Indexc{bin}( integer )\index{manipulator!bin@©bin©} print value in base 2 preceded by ©0b©/©0B©.
    3728 \begin{cfa}[belowskip=0pt]
    3729 sout | bin( 0 ) | bin( 27HH ) | bin( 27H ) | bin( 27 ) | bin( 27L );
    3730 0b0 0b11011 0b11011 0b11011 0b11011
    3731 sout | bin( -27HH ) | bin( -27H ) | bin( -27 ) | bin( -27L );
    3732 0b11100101 0b1111111111100101 0b11111111111111111111111111100101 0b®(58 1s)®100101
    3733 \end{cfa}
    3734 
    3735 \item
    3736 \Indexc{oct}( integer )\index{manipulator!oct@©oct©} print value in base 8 preceded by ©0©.
    3737 \begin{cfa}[belowskip=0pt]
    3738 sout | oct( 0 ) | oct( 27HH ) | oct( 27H ) | oct( 27 ) | oct( 27L );
    3739 0 033 033 033 033
    3740 sout | oct( -27HH ) | oct( -27H ) | oct( -27 ) | oct( -27L );
    3741 0345 0177745 037777777745 01777777777777777777745
    3742 \end{cfa}
    3743 Note, octal 0 is \emph{not} preceded by ©0© to prevent confusion.
    3744 
    3745 \item
    3746 \Indexc{hex}( integer / floating-point )\index{manipulator!hex@©hex©} print value in base 16 preceded by ©0x©/©0X©.
    3747 \begin{cfa}[belowskip=0pt]
    3748 sout | hex( 0 ) | hex( 27HH ) | hex( 27H ) | hex( 27 ) | hex( 27L );
    3749 0 0x1b 0x1b 0x1b 0x1b
    3750 sout | hex( -27HH ) | hex( -27H ) | hex( -27 ) | hex( -27L );
    3751 0xe5 0xffe5 0xffffffe5 0xffffffffffffffe5
    3752 
    3753 sout | hex( 0.0 ) | hex( 27.5F ) | hex( 27.5 ) | hex( 27.5L );
    3754 0x0.p+0 0x1.b8p+4 0x1.b8p+4 0xd.cp+1
    3755 sout | hex( -27.5F ) | hex( -27.5 ) | hex( -27.5L );
    3756 -0x1.b8p+4 -0x1.b8p+4 -0xd.cp+1
    3757 \end{cfa}
    3758 
    3759 \item
    3760 \Indexc{sci}( floating-point )\index{manipulator!sci@©sci©} print value in scientific notation with exponent.
    3761 Default is 6 digits of precision.
    3762 \begin{cfa}[belowskip=0pt]
    3763 sout | sci( 0.0 ) | sci( 27.5 ) | sci( -27.5 );
    3764 0.000000e+00 2.750000e+01 -2.750000e+01
    3765 \end{cfa}
    3766 
    3767 \item
    3768 \Indexc{upcase}( bin / hex / floating-point )\index{manipulator!upcase@©upcase©} print letters in a value in upper case. Lower case is the default.
    3769 \begin{cfa}[belowskip=0pt]
    3770 sout | upcase( bin( 27 ) ) | upcase( hex( 27 ) ) | upcase( 27.5e-10 ) | upcase( hex( 27.5 ) );
    3771 0®B®11011 0®X®1®B® 2.75®E®-09 0®X®1.®B®8®P®+4
    3772 \end{cfa}
    3773 
    3774 \item
    3775 \Indexc{nobase}( integer )\index{manipulator!nobase@©nobase©} do not precede ©bin©, ©oct©, ©hex© with ©0b©/©0B©, ©0©, or ©0x©/©0X©.
    3776 Printing the base is the default.
    3777 \begin{cfa}[belowskip=0pt]
    3778 sout | nobase( bin( 27 ) ) | nobase( oct( 27 ) ) | nobase( hex( 27 ) );
    3779 11011 33 1b
    3780 \end{cfa}
    3781 
    3782 \item
    3783 \Indexc{nodp}( floating-point )\index{manipulator!nodp@©nodp©} do not print a decimal point if there are no fractional digits.
    3784 Printing a decimal point is the default, if there are no fractional digits.
    3785 \begin{cfa}[belowskip=0pt]
    3786 sout | 0. | nodp( 0. ) | 27.0 | nodp( 27.0 ) | nodp( 27.5 );
    3787 0.0 ®0® 27.0 ®27® 27.5
    3788 \end{cfa}
    3789 
    3790 \item
    3791 \Indexc{sign}( integer / floating-point )\index{manipulator!sign@©sign©} prefix with plus or minus sign (©+© or ©-©). Only printing the minus sign is the default.
    3792 \begin{cfa}[belowskip=0pt]
    3793 sout | sign( 27 ) | sign( -27 ) | sign( 27. ) | sign( -27. ) | sign( 27.5 ) | sign( -27.5 );
    3794 ®+®27 -27 ®+®27.0 -27.0 ®+®27.5 -27.5
    3795 \end{cfa}
    3796 
    3797 \item
    3798 \Indexc{wd}©( unsigned char minimum, T val )©\index{manipulator!wd@©wd©}, ©wd( unsigned char minimum, unsigned char precision, T val )©
    3799 For all types, ©minimum© is the minimum number of printed characters.
    3800 If the value is shorter than the minimum, it is padded on the right with spaces.
    3801 \begin{cfa}[belowskip=0pt]
    3802 sout | wd( 4, 34) | wd( 3, 34 ) | wd( 2, 34 );
    3803 sout | wd( 10, 4.) | wd( 9, 4. ) | wd( 8, 4. );
    3804 sout | wd( 4, "ab" ) | wd( 3, "ab" ) | wd( 2, "ab" );
    3805 \end{cfa}
    3806 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3807 ®  ®34 ® ®34 34
    3808 ®  ®4.000000 ® ®4.000000 4.000000
    3809 ®  ®ab ® ®ab ab
    3810 \end{cfa}
    3811 If the value is larger, it is printed without truncation, ignoring the ©minimum©.
    3812 \begin{cfa}[belowskip=0pt]
    3813 sout | wd( 4, 34567 ) | wd( 3, 34567 ) | wd( 2, 34567 );
    3814 sout | wd( 4, 3456. ) | wd( 3, 3456. ) | wd( 2, 3456. );
    3815 sout | wd( 4, "abcde" ) | wd( 3, "abcde" ) | wd( 2,"abcde" );
    3816 \end{cfa}
    3817 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3818 3456®7® 345®67® 34®567®
    3819 3456®.® 345®6.® 34®56.®
    3820 abcd®e® abc®de® ab®cde®
    3821 \end{cfa}
    3822 
    3823 For integer types, ©precision© is the minimum number of printed digits.
    3824 If the value is shorter, it is padded on the left with leading zeros.
    3825 \begin{cfa}[belowskip=0pt]
    3826 sout | wd( 4,3, 34 ) | wd( 8,4, 34 ) | wd( 10,10, 34 );
    3827 \end{cfa}
    3828 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3829  ®0®34     ®00®34 ®00000000®34
    3830 \end{cfa}
    3831 If the value is larger, it is printed without truncation, ignoring the ©precision©.
    3832 \begin{cfa}[belowskip=0pt]
    3833 sout | wd( 4,1, 3456 ) | wd( 8,2, 3456 ) | wd( 10,3, 3456 );
    3834 \end{cfa}
    3835 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3836 3456     3456       3456
    3837 \end{cfa}
    3838 If ©precision© is 0, nothing is printed for zero.
    3839 If ©precision© is greater than the minimum, it becomes the minimum.
    3840 \begin{cfa}[belowskip=0pt]
    3841 sout | wd( 4,0, 0 ) | wd( 3,10, 34 );
    3842 \end{cfa}
    3843 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3844 ®    ® ®00000000®34
    3845 \end{cfa}
    3846 For floating-point types, ©precision© is the minimum number of digits after the decimal point.
    3847 \begin{cfa}[belowskip=0pt]
    3848 sout | wd( 6,3, 27.5 ) | wd( 8,1, 27.5 ) | wd( 8,0, 27.5 ) | wd( 3,8, 27.5 );
    3849 \end{cfa}
    3850 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3851 27.®500®     27.®5®      28. 27.®50000000®
    3852 \end{cfa}
    3853 For the C-string type, ©precision© is the maximum number of printed characters, so the string is truncared if it exceeds the maximum.
    3854 \begin{cfa}[belowskip=0pt]
    3855 sout | wd( 6,8, "abcd" ) | wd( 6,8, "abcdefghijk" ) | wd( 6,3, "abcd" );
    3856 \end{cfa}
    3857 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3858   abcd abcdefgh    abc
    3859 \end{cfa}
    3860 
    3861 \item
    3862 \Indexc{ws( unsigned char minimum, unsigned char significant, floating-point )}\index{manipulator!ws@©ws©}
    3863 For floating-point type, ©minimum© is the same as for manipulator ©wd©, but ©significant© is the maximum number of significant digits to be printed for both the integer and fractions (versus only the fraction for ©wd©).
    3864 If a value's significant digits is greater than ©significant©, the last significant digit is rounded up.
    3865 \begin{cfa}[belowskip=0pt]
    3866 sout | ws(6,6, 234.567) | ws(6,5, 234.567) | ws(6,4, 234.567) | ws(6,3, 234.567);
    3867 \end{cfa}
    3868 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3869 234.567 234.5®7®  234.®6®    23®5®
    3870 \end{cfa}
    3871 If a value's magnitude is greater than ©significant©, the value is printed in scientific notation with the specified number of significant digits.
    3872 \begin{cfa}[belowskip=0pt]
    3873 sout | ws(6,6, 234567.) | ws(6,5, 234567.) | ws(6,4, 234567.) | ws(6,3, 234567.);
    3874 \end{cfa}
    3875 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3876 234567. 2.3457®e+05® 2.346®e+05® 2.35®e+05®
    3877 \end{cfa}
    3878 If ©significant© is greater than ©minimum©, it defines the number of printed characters.
    3879 \begin{cfa}[belowskip=0pt]
    3880 sout | ws(3,6, 234567.) | ws(4,6, 234567.) | ws(5,6, 234567.) | ws(6,6, 234567.);
    3881 \end{cfa}
    3882 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3883 234567. 234567. 234567. 234567.
    3884 \end{cfa}
    3885 
    3886 \item
    3887 \Indexc{left}( field-width )\index{manipulator!left@©left©} left justify within the given field.
    3888 \begin{cfa}[belowskip=0pt]
    3889 sout | left(wd(4, 27)) | left(wd(10, 27.)) | left(wd(10, 27.5)) | left(wd(4,3, 27)) | left(wd(10,3, 27.5));
    3890 \end{cfa}
    3891 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3892 27®  ® 27.000000  27.500000  027  27.500®    ®
    3893 \end{cfa}
    3894 
    3895 \item
    3896 \Indexc{pad0}( field-width )\index{manipulator!pad0@©pad0©} left pad with zeroes (0).
    3897 \begin{cfa}[belowskip=0pt]
    3898 sout | pad0( wd( 4, 27 ) ) | pad0( wd( 4,3, 27 ) ) | pad0( wd( 8,3, 27.5 ) );
    3899 ®00®27  ®0®27 ®00®27.500
    39003334\end{cfa}
    39013335\end{enumerate}
     
    39073341int main( void ) {
    39083342        int x = 1, y = 2, z = 3;
    3909         sout | x | y | z;
     3343        sout | x | y | z | endl;
    39103344        [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];
    3911         sout | t1 | t2;                                         // print tuples
    3912         sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2);
    3913         sout | 1 | 2 | 3;
    3914         sout | '1' | '2' | '3';
    3915         sout | 1 | "" | 2 | "" | 3;
     3345        sout | t1 | t2 | endl;                                          // print tuples
     3346        sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl;
     3347        sout | 1 | 2 | 3 | endl;
     3348        sout | '1' | '2' | '3' | endl;
     3349        sout | 1 | "" | 2 | "" | 3 | endl;
    39163350        sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥"
    3917                 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;
     3351                | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10 | endl;
    39183352        sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x"
    3919                 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";
    3920         sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx";
    3921         sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4;
     3353                | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x" | endl;
     3354        sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx" | endl;
     3355        sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4 | endl;
    39223356
    39233357        sepSet( sout, ", $" );                                          // set separator from " " to ", $"
    3924         sout | 1 | 2 | 3 | " \"" | sep | "\"";
     3358        sout | 1 | 2 | 3 | " \"" | sep | "\"" | endl;
    39253359        sepSet( sout, " " );                                            // reset separator to " "
    3926         sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"";
     3360        sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"" | endl;
    39273361
    39283362        char store[sepSize];
    39293363        strcpy( store, sepGet( sout ) );
    39303364        sepSet( sout, "_" );
    3931         sout | 1 | 2 | 3;
     3365        sout | 1 | 2 | 3 | endl;
    39323366        sepSet( sout, store );
    3933         sout | 1 | 2 | 3;
     3367        sout | 1 | 2 | 3 | endl;
    39343368
    39353369        sepSetTuple( sout, " " );                                       // set tuple separator from ", " to " "
    3936         sout | t1 | t2 | " \"" | sepTuple | "\"";
     3370        sout | t1 | t2 | " \"" | sepTuple | "\"" | endl;
    39373371        sepSetTuple( sout, ", " );                                      // reset tuple separator to ", "
    3938         sout | t1 | t2 | " \"" | sepGetTuple( sout ) | "\"";
    3939 
    3940         sout | sepDisable | 1 | 2 | 3;          // globally turn off implicit separator
    3941         sout | sepEnable | 1 | 2 | 3;           // globally turn on implicit separator
    3942 
    3943         sout | 1 | sepOff | 2 | 3;                      // locally turn on implicit separator
    3944         sout | sepDisable | 1 | sepOn | 2 | 3; // globally turn off implicit separator
     3372        sout | t1 | t2 | " \"" | sepGetTuple( sout ) | "\"" | endl;
     3373
     3374        sout | sepDisable | 1 | 2 | 3 | endl;           // globally turn off implicit separator
     3375        sout | sepEnable | 1 | 2 | 3 | endl;            // globally turn on implicit separator
     3376       
     3377        sout | 1 | sepOff | 2 | 3 | endl;                       // locally turn on implicit separator
     3378        sout | sepDisable | 1 | sepOn | 2 | 3 | endl; // globally turn off implicit separator
    39453379        sout | sepEnable;
    3946         sout | t1 | sepOff | t2;                                // locally turn on/off implicit separator
    3947 
    3948         sout | sepOn | 1 | 2 | 3 | sepOn ;      // sepOn does nothing at start/end of line
    3949         sout | sep | 1 | 2 | 3 | sep ;          // use sep to print separator at start/end of line
     3380        sout | t1 | sepOff | t2 | endl;                         // locally turn on/off implicit separator
     3381
     3382        sout | sepOn | 1 | 2 | 3 | sepOn | endl ;       // sepOn does nothing at start/end of line
     3383        sout | sep | 1 | 2 | 3 | sep | endl ;           // use sep to print separator at start/end of line
    39503384}
    39513385
     
    39563390\end{comment}
    39573391%$
    3958 
    3959 
    3960 \subsection{Input Value Manipulators}
    3961 
    3962 The format of numeric input values in the same as C constants without a trailing type suffix, as the input value-type is denoted by the input variable.
    3963 For ©_Bool© type, the constants are ©true© and ©false©.
    3964 For integral types, any number of digits, optionally preceded by a sign (©+© or ©-©), where a
    3965 \begin{itemize}
    3966 \item
    3967 ©1©-©9© prefix introduces a decimal value (©0©-©9©),
    3968 \item
    3969 ©0© prefix introduces an octal value (©0©-©7©), and
    3970 \item
    3971 ©0x© or ©0X© prefix introduces a hexadecimal value (©0©-©f©) with lower or upper case letters.
    3972 \end{itemize}
    3973 For floating-point types, any number of decimal digits, optionally preceded by a sign (©+© or ©-©), optionally containing a decimal point, and optionally followed by an exponent, ©e© or ©E©, with signed (optional) decimal digits.
    3974 Floating-point values can also be written in hexadecimal format preceded by ©0x© or ©0X© with hexadecimal digits and exponent denoted by ©p© or ©P©.
    3975 
    3976 For the C-string type, the input values are \emph{not} the same as C-string constants, \ie double quotes bracketing arbitrary text with escape sequences.
    3977 Instead, the next sequence of non-whitespace characters are read, and the input sequence is terminated with delimiter ©'\0'©.
    3978 The string variable \emph{must} be large enough to contain the input sequence.
    3979 
    3980 The following \Index{manipulator}s control formatting of input values (reading), and only affect the format of the argument.
    3981 
    3982 \begin{enumerate}
    3983 \item
    3984 \Indexc{skip( const char * pattern )}\index{manipulator!skip@©skip©} / ©skip( unsigned int length )© / ©const char * pattern©
    3985 The argument defines a ©pattern© or ©length©.
    3986 The ©pattern© is composed of white-space and non-white-space characters, where \emph{any} white-space character matches 0 or more input white-space characters (hence, consecutive white-space characters in the pattern are combined), and each non-white-space character matches exactly with an input character.
    3987 The ©length© is composed of the next $N$ characters, including the newline character.
    3988 If the match successes, the input characters are discarded, and input continues with the next character.
    3989 If the match fails, the input characters are left unread.
    3990 \begin{cfa}[belowskip=0pt]
    3991 char sk[$\,$] = "abc";
    3992 sin | "abc " | skip( sk ) | skip( 5 ); // match input sequence
    3993 \end{cfa}
    3994 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3995 ®abc   ®
    3996 ®abc  ®
    3997 ®xx®
    3998 \end{cfa}
    3999 
    4000 \item
    4001 \Indexc{wdi}©( unsigned int maximum, T & val )©\index{manipulator!wdi@©wdi©}
    4002 For all types except ©char©, ©maximum© is the maximum number of characters read for the current operation.
    4003 \begin{cfa}[belowskip=0pt]
    4004 char s[10];   int i;   double d;   
    4005 sin | wdi( 4, s ) | wdi( 3, i ) | wdi( 8, d );  // c == "abcd", i == 123, d == 3.456E+2
    4006 \end{cfa}
    4007 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    4008 ®abcd1233.456E+2®
    4009 \end{cfa}
    4010 Note, input ©wdi© cannot be overloaded with output ©wd© because both have the same parameters but return different types.
    4011 Currently, \CFA cannot distinguish between these two manipulators in the middle of an ©sout©/©sin© expression based on return type.
    4012 
    4013 \item
    4014 \Indexc{ignore( T & val )}\index{manipulator!ignore@©ignore©}
    4015 For all types, the data is read from the stream depending on the argument type but ignored, \ie it is not stored in the argument.
    4016 \begin{cfa}[belowskip=0pt]
    4017 double d;
    4018 sin | ignore( d );  // d is unchanged
    4019 \end{cfa}
    4020 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    4021 ®  -75.35e-4® 25
    4022 \end{cfa}
    4023 
    4024 \item
    4025 \Indexc{incl( const char * scanset, char * s )}\index{manipulator!incl@©incl©}
    4026 For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{in} the set.
    4027 Matching characters are read into the C string and null terminated.
    4028 \begin{cfa}[belowskip=0pt]
    4029 char s[10];
    4030 sin | incl( "abc", s );
    4031 \end{cfa}
    4032 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    4033 ®bca®xyz
    4034 \end{cfa}
    4035 
    4036 \item
    4037 \Indexc{excl( const char * scanset, char * s )}\index{manipulator!excl@©excl©}
    4038 For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{not in} the set.
    4039 Non-matching characters are read into the C string and null terminated.
    4040 \begin{cfa}[belowskip=0pt]
    4041 char s[10];
    4042 sin | excl( "abc", s );
    4043 \end{cfa}
    4044 \begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    4045 ®xyz®bca
    4046 \end{cfa}
    4047 \end{enumerate}
    40483392
    40493393
     
    44153759\begin{itemize}
    44163760\item
    4417 not determining or writing long generic types,
    4418 \item
    4419 ensuring secondary variables, related to a primary variable, always have the same type.
     3761preventing having to determine or write long generic types,
     3762\item
     3763ensure secondary variables, related to a primary variable, always have the same type.
    44203764\end{itemize}
    44213765
     
    44393783There is also the conundrum in type inferencing of when to \emph{\Index{brand}} a type.
    44403784That is, when is the type of the variable more important than the type of its initialization expression.
    4441 For example, if a change is made in an initialization expression, it can cause cascading type changes and/or errors.
     3785For example, if a change is made in an initialization expression, it can cause significant cascading type changes and/or errors.
    44423786At some point, a variable type needs to remain constant and the expression to be in error when it changes.
    44433787
     
    46724016
    46734017coroutine Fibonacci {
    4674         int fn; §\C{// used for communication}§
     4018        int fn;                                                         §\C{// used for communication}§
    46754019};
    46764020void ?{}( Fibonacci * this ) {
     
    46784022}
    46794023void main( Fibonacci * this ) {
    4680         int fn1, fn2; §\C{// retained between resumes}§
    4681         this->fn = 0; §\C{// case 0}§
     4024        int fn1, fn2;                                           §\C{// retained between resumes}§
     4025        this->fn = 0;                                           §\C{// case 0}§
    46824026        fn1 = this->fn;
    4683         suspend(); §\C{// return to last resume}§
    4684 
    4685         this->fn = 1; §\C{// case 1}§
     4027        suspend();                                                      §\C{// return to last resume}§
     4028
     4029        this->fn = 1;                                           §\C{// case 1}§
    46864030        fn2 = fn1;
    46874031        fn1 = this->fn;
    4688         suspend(); §\C{// return to last resume}§
    4689 
    4690         for ( ;; ) { §\C{// general case}§
     4032        suspend();                                                      §\C{// return to last resume}§
     4033
     4034        for ( ;; ) {                                            §\C{// general case}§
    46914035                this->fn = fn1 + fn2;
    46924036                fn2 = fn1;
    46934037                fn1 = this->fn;
    4694                 suspend(); §\C{// return to last resume}§
     4038                suspend();                                              §\C{// return to last resume}§
    46954039        } // for
    46964040}
    46974041int next( Fibonacci * this ) {
    4698         resume( this ); §\C{// transfer to last suspend}§
     4042        resume( this );                                         §\C{// transfer to last suspend}§
    46994043        return this->fn;
    47004044}
     
    47024046        Fibonacci f1, f2;
    47034047        for ( int i = 1; i <= 10; i += 1 ) {
    4704                 sout | next( &f1 ) | ' ' | next( &f2 );
     4048                sout | next( &f1 ) | ' ' | next( &f2 ) | endl;
    47054049        } // for
    47064050}
     
    47684112                MyThread f[4];
    47694113        }
    4770         sout | global.value;
     4114        sout | global.value | endl;
    47714115}
    47724116\end{cfa}
     
    48464190void main( First * this ) {
    48474191        for ( int i = 0; i < 10; i += 1 ) {
    4848                 sout | "First : Suspend No." | i + 1;
     4192                sout | "First : Suspend No." | i + 1 | endl;
    48494193                yield();
    48504194        }
     
    48554199        wait( this->lock );
    48564200        for ( int i = 0; i < 10; i += 1 ) {
    4857                 sout | "Second : Suspend No." | i + 1;
     4201                sout | "Second : Suspend No." | i + 1 | endl;
    48584202                yield();
    48594203        }
     
    48624206int main( void ) {
    48634207        signal_once lock;
    4864         sout | "User main begin";
     4208        sout | "User main begin" | endl;
    48654209        {
    48664210                processor p;
     
    48704214                }
    48714215        }
    4872         sout | "User main end";
     4216        sout | "User main end" | endl;
    48734217}
    48744218\end{cfa}
     
    55674911void ?{}( Line * l ) {
    55684912        l->lnth = 0.0;
    5569         sout | "default";
     4913        sout | "default" | endl;
    55704914}
    55714915
     
    55744918void ?{}( Line * l, float lnth ) {
    55754919        l->lnth = lnth;
    5576         sout | "lnth" | l->lnth;
     4920        sout | "lnth" | l->lnth | endl;
    55774921
    55784922}
     
    55804924// destructor
    55814925void ^?() {
    5582         sout | "destroyed";
     4926        sout | "destroyed" | endl;
    55834927        l.lnth = 0.0;
    55844928}
     
    62415585In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as:
    62425586\begin{cfa}
    6243 *?§\color{red}\textvisiblespace§*? §\C{// dereference operator, dereference operator}§
    6244 *§\color{red}\textvisiblespace§?*? §\C{// dereference, multiplication operator}§
     5587*?§\color{red}\textvisiblespace§*?              §\C{// dereference operator, dereference operator}§
     5588*§\color{red}\textvisiblespace§?*?              §\C{// dereference, multiplication operator}§
    62455589\end{cfa}
    62465590By default, the first interpretation is selected, which does not yield a meaningful parse.
     
    62945638\eg:
    62955639\begin{cfa}
    6296 x; §\C{// int x}§
    6297 *y; §\C{// int *y}§
    6298 f( p1, p2 ); §\C{// int f( int p1, int p2 );}§
    6299 g( p1, p2 ) int p1, p2; §\C{// int g( int p1, int p2 );}§
     5640x;                                                              §\C{// int x}§
     5641*y;                                                             §\C{// int *y}§
     5642f( p1, p2 );                                    §\C{// int f( int p1, int p2 );}§
     5643g( p1, p2 ) int p1, p2;                 §\C{// int g( int p1, int p2 );}§
    63005644\end{cfa}
    63015645\CFA continues to support K\&R routine definitions:
    63025646\begin{cfa}
    6303 f( a, b, c ) §\C{// default int return}§
    6304         int a, b; char c §\C{// K\&R parameter declarations}§
     5647f( a, b, c )                                    §\C{// default int return}§
     5648        int a, b; char c                        §\C{// K\&R parameter declarations}§
    63055649{
    63065650        ...
     
    63215665int rtn( int i );
    63225666int rtn( char c );
    6323 rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§
     5667rtn( 'x' );                                             §\C{// programmer expects 2nd rtn to be called}§
    63245668\end{cfa}
    63255669\item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first.
    63265670In particular, output of ©char© variable now print a character rather than the decimal ASCII value of the character.
    63275671\begin{cfa}
    6328 sout | 'x' | " " | (int)'x';
     5672sout | 'x' | " " | (int)'x' | endl;
    63295673x 120
    63305674\end{cfa}
     
    63435687\item[Change:] make string literals ©const©:
    63445688\begin{cfa}
    6345 char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§
    6346 char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§
     5689char * p = "abc";                               §\C{// valid in C, deprecated in \CFA}§
     5690char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§
    63475691\end{cfa}
    63485692The type of a string literal is changed from ©[] char© to ©const [] char©.
     
    63515695\begin{cfa}
    63525696char * p = "abc";
    6353 p[0] = 'w'; §\C{// segment fault or change constant literal}§
     5697p[0] = 'w';                                             §\C{// segment fault or change constant literal}§
    63545698\end{cfa}
    63555699The same problem occurs when passing a string literal to a routine that changes its argument.
     
    63635707\item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope:
    63645708\begin{cfa}
    6365 int i; §\C{// forward definition}§
    6366 int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§
    6367 int i = 0; §\C{// definition}§
     5709int i;                                                  §\C{// forward definition}§
     5710int *j = ®&i®;                                  §\C{// forward reference, valid in C, invalid in \CFA}§
     5711int i = 0;                                              §\C{// definition}§
    63685712\end{cfa}
    63695713is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed.
     
    63715715\begin{cfa}
    63725716struct X { int i; struct X *next; };
    6373 static struct X a; §\C{// forward definition}§
     5717static struct X a;                              §\C{// forward definition}§
    63745718static struct X b = { 0, ®&a® };§\C{// forward reference, valid in C, invalid in \CFA}§
    6375 static struct X a = { 1, &b }; §\C{// definition}§
     5719static struct X a = { 1, &b };  §\C{// definition}§
    63765720\end{cfa}
    63775721\item[Rationale:] avoids having different initialization rules for builtin types and user-defined types.
     
    63885732struct Person {
    63895733        enum ®Colour® { R, G, B };      §\C[7cm]{// nested type}§
    6390         struct Face { §\C{// nested type}§
    6391                 ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§
     5734        struct Face {                           §\C{// nested type}§
     5735                ®Colour® Eyes, Hair;    §\C{// type defined outside (1 level)}§
    63925736        };
    6393         ®.Colour® shirt; §\C{// type defined outside (top level)}§
    6394         ®Colour® pants; §\C{// type defined same level}§
    6395         Face looks[10]; §\C{// type defined same level}§
     5737        ®.Colour® shirt;                        §\C{// type defined outside (top level)}§
     5738        ®Colour® pants;                         §\C{// type defined same level}§
     5739        Face looks[10];                         §\C{// type defined same level}§
    63965740};
    6397 ®Colour® c = R; §\C{// type/enum defined same level}§
     5741®Colour® c = R;                                 §\C{// type/enum defined same level}§
    63985742Person®.Colour® pc = Person®.®R;§\C{// type/enum defined inside}§
    6399 Person®.®Face pretty; §\C{// type defined inside}\CRT§
     5743Person®.®Face pretty;                   §\C{// type defined inside}\CRT§
    64005744\end{cfa}
    64015745In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing structure, \ie the nested types are hoisted to the scope of the outer-most type, which is not useful and confusing.
     
    64145758\item[Difficulty of converting:] Semantic transformation. To make the struct type name visible in the scope of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing struct is defined. Example:
    64155759\begin{cfa}
    6416 struct Y; §\C{// struct Y and struct X are at the same scope}§
     5760struct Y;                                               §\C{// struct Y and struct X are at the same scope}§
    64175761struct X {
    64185762        struct Y { /* ... */ } y;
     
    64295773\begin{cfa}
    64305774void foo() {
    6431         int * b = malloc( sizeof(int) ); §\C{// implicitly convert void * to int *}§
    6432         char * c = b; §\C{// implicitly convert int * to void *, and then void * to char *}§
     5775        int * b = malloc( sizeof(int) );        §\C{// implicitly convert void * to int *}§
     5776        char * c = b;                           §\C{// implicitly convert int * to void *, and then void * to char *}§
    64335777}
    64345778\end{cfa}
     
    66035947void * memalign( size_t align, size_t size );§\indexc{memalign}§
    66045948int posix_memalign( void ** ptr, size_t align, size_t size );§\indexc{posix_memalign}§
     5949}
     5950
     5951// §\CFA§ safe equivalents, i.e., implicit size specification
     5952forall( dtype T | sized(T) ) T * malloc( void );
     5953forall( dtype T | sized(T) ) T * calloc( size_t dim );
     5954forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size );
     5955forall( dtype T | sized(T) ) T * memalign( size_t align );
     5956forall( dtype T | sized(T) ) T * aligned_alloc( size_t align );
     5957forall( dtype T | sized(T) ) int posix_memalign( T ** ptr, size_t align );
     5958
     5959// §\CFA§ safe general allocation, fill, resize, array
     5960forall( dtype T | sized(T) ) T * alloc( void );§\indexc{alloc}§
     5961forall( dtype T | sized(T) ) T * alloc( char fill );
     5962forall( dtype T | sized(T) ) T * alloc( size_t dim );
     5963forall( dtype T | sized(T) ) T * alloc( size_t dim, char fill );
     5964forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim );
     5965forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
     5966
     5967// §\CFA§ safe general allocation, align, fill, array
     5968forall( dtype T | sized(T) ) T * align_alloc( size_t align );
     5969forall( dtype T | sized(T) ) T * align_alloc( size_t align, char fill );
     5970forall( dtype T | sized(T) ) T * align_alloc( size_t align, size_t dim );
     5971forall( dtype T | sized(T) ) T * align_alloc( size_t align, size_t dim, char fill );
    66055972
    66065973// C unsafe initialization/copy
     5974extern "C" {
    66075975void * memset( void * dest, int c, size_t size );
    66085976void * memcpy( void * dest, const void * src, size_t size );
    66095977}
    66105978
    6611 forall( dtype T | sized(T) ) {
    6612 // §\CFA§ safe equivalents, i.e., implicit size specification
    6613         T * malloc( void );
    6614         T * calloc( size_t dim );
    6615         T * realloc( T * ptr, size_t size );
    6616         T * memalign( size_t align );
    6617         T * aligned_alloc( size_t align );
    6618         int posix_memalign( T ** ptr, size_t align );
    6619 
    6620 // §\CFA§ safe general allocation, fill, resize, array
    6621         T * alloc( void );§\indexc{alloc}§
    6622         T * alloc( char fill );
    6623         T * alloc( size_t dim );
    6624         T * alloc( size_t dim, char fill );
    6625         T * alloc( T ptr[], size_t dim );
    6626         T * alloc( T ptr[], size_t dim, char fill );
    6627 
    6628 // §\CFA§ safe general allocation, align, fill, array
    6629         T * align_alloc( size_t align );
    6630         T * align_alloc( size_t align, char fill );
    6631         T * align_alloc( size_t align, size_t dim );
    6632         T * align_alloc( size_t align, size_t dim, char fill );
    6633 
    66345979// §\CFA§ safe initialization/copy, i.e., implicit size specification
    6635         T * memset( T * dest, char c );§\indexc{memset}§
    6636         T * memcpy( T * dest, const T * src );§\indexc{memcpy}§
     5980forall( dtype T | sized(T) ) T * memset( T * dest, char c );§\indexc{memset}§
     5981forall( dtype T | sized(T) ) T * memcpy( T * dest, const T * src );§\indexc{memcpy}§
    66375982
    66385983// §\CFA§ safe initialization/copy array
    6639         T * amemset( T dest[], char c, size_t dim );
    6640         T * amemcpy( T dest[], const T src[], size_t dim );
    6641 }
     5984forall( dtype T | sized(T) ) T * memset( T dest[], size_t dim, char c );
     5985forall( dtype T | sized(T) ) T * memcpy( T dest[], const T src[], size_t dim );
    66425986
    66435987// §\CFA§ allocation/deallocation and constructor/destructor
     
    66555999
    66566000
    6657 \subsection{String to Value Conversion}
     6001\subsection{Conversion}
    66586002
    66596003\leavevmode
     
    66916035\leavevmode
    66926036\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    6693 forall( otype T | { int ?<?( T, T ); } ) §\C{// location}§
     6037forall( otype T | { int ?<?( T, T ); } )        §\C{// location}§
    66946038T * bsearch( T key, const T * arr, size_t dim );§\indexc{bsearch}§
    66956039
    6696 forall( otype T | { int ?<?( T, T ); } ) §\C{// position}§
     6040forall( otype T | { int ?<?( T, T ); } )        §\C{// position}§
    66976041unsigned int bsearch( T key, const T * arr, size_t dim );
    66986042
    66996043forall( otype T | { int ?<?( T, T ); } )
    67006044void qsort( const T * arr, size_t dim );§\indexc{qsort}§
    6701 
    6702 forall( otype E | { int ?<?( E, E ); } ) {
    6703         E * bsearch( E key, const E * vals, size_t dim );§\indexc{bsearch}§ §\C{// location}§
    6704         size_t bsearch( E key, const E * vals, size_t dim );§\C{// position}§
    6705         E * bsearchl( E key, const E * vals, size_t dim );§\indexc{bsearchl}§
    6706         size_t bsearchl( E key, const E * vals, size_t dim );
    6707         E * bsearchu( E key, const E * vals, size_t dim );§\indexc{bsearchu}§
    6708         size_t bsearchu( E key, const E * vals, size_t dim );
    6709 }
    6710 
    6711 forall( otype K, otype E | { int ?<?( K, K ); K getKey( const E & ); } ) {
    6712         E * bsearch( K key, const E * vals, size_t dim );
    6713         size_t bsearch( K key, const E * vals, size_t dim );
    6714         E * bsearchl( K key, const E * vals, size_t dim );
    6715         size_t bsearchl( K key, const E * vals, size_t dim );
    6716         E * bsearchu( K key, const E * vals, size_t dim );
    6717         size_t bsearchu( K key, const E * vals, size_t dim );
    6718 }
    6719 
    6720 forall( otype E | { int ?<?( E, E ); } ) {
    6721         void qsort( E * vals, size_t dim );§\indexc{qsort}§
    6722 }
    67236045\end{cfa}
    67246046
     
    67476069\leavevmode
    67486070\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    6749 void srandom( unsigned int seed );§\indexc{srandom}§
    6750 char random( void );§\indexc{random}§
    6751 char random( char u ); §\C{// [0,u)}§
    6752 char random( char l, char u ); §\C{// [l,u)}§
    6753 int random( void );
    6754 int random( int u ); §\C{// [0,u)}§
    6755 int random( int l, int u ); §\C{// [l,u)}§
    6756 unsigned int random( void );
    6757 unsigned int random( unsigned int u ); §\C{// [0,u)}§
    6758 unsigned int random( unsigned int l, unsigned int u ); §\C{// [l,u)}§
    6759 long int random( void );
    6760 long int random( long int u ); §\C{// [0,u)}§
    6761 long int random( long int l, long int u ); §\C{// [l,u)}§
    6762 unsigned long int random( void );
    6763 unsigned long int random( unsigned long int u ); §\C{// [0,u)}§
    6764 unsigned long int random( unsigned long int l, unsigned long int u ); §\C{// [l,u)}§
    6765 float random( void );                                            §\C{// [0.0, 1.0)}§
    6766 double random( void );                                           §\C{// [0.0, 1.0)}§
    6767 float _Complex random( void );                           §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
    6768 double _Complex random( void );                          §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
    6769 long double _Complex random( void );             §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
     6071void rand48seed( long int s );§\indexc{rand48seed}§
     6072char rand48();§\indexc{rand48}§
     6073int rand48();
     6074unsigned int rand48();
     6075long int rand48();
     6076unsigned long int rand48();
     6077float rand48();
     6078double rand48();
     6079float _Complex rand48();
     6080double _Complex rand48();
     6081long double _Complex rand48();
    67706082\end{cfa}
    67716083
     
    68106122[ int, long double ] remquo( long double, long double );
    68116123
    6812 float div( float, float, int * );§\indexc{div}§ §\C{// alternative name for remquo}§
     6124float div( float, float, int * );§\indexc{div}§ §\C{// alternative name for remquo}§
    68136125double div( double, double, int * );
    68146126long double div( long double, long double, int * );
     
    69666278long double atan2( long double, long double );
    69676279
    6968 float atan( float, float ); §\C{// alternative name for atan2}§
     6280float atan( float, float );                                     §\C{// alternative name for atan2}§
    69696281double atan( double, double );§\indexc{atan}§
    69706282long double atan( long double, long double );
     
    71466458
    71476459
    7148 \section{Time Keeping}
    7149 \label{s:TimeKeeping}
     6460\section{Time}
     6461\label{s:TimeLib}
    71506462
    71516463
    71526464%\subsection{\texorpdfstring{\protect\lstinline@Duration@}{Duration}}
    7153 \subsection{\texorpdfstring{\LstBasicStyle{Duration}}{Duration}}
     6465\subsection{\texorpdfstring{\LstKeywordStyle{\textmd{Duration}}}{Duration}}
    71546466\label{s:Duration}
    71556467
     
    71576469\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    71586470struct Duration {
    7159         int64_t tv; §\C{// nanoseconds}§
     6471        int64_t tv;                                                     §\C{// nanoseconds}§
    71606472};
    71616473
     
    72006512
    72016513Duration abs( Duration rhs );
     6514
     6515forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Duration dur );
    72026516
    72036517Duration ?`ns( int64_t nsec );
     
    72236537int64_t ?`d( Duration dur );
    72246538int64_t ?`w( Duration dur );
    7225 
    7226 Duration max( Duration lhs, Duration rhs );
    7227 Duration min( Duration lhs, Duration rhs );
    72286539\end{cfa}
    72296540
    72306541
    72316542%\subsection{\texorpdfstring{\protect\lstinline@\timeval@}{timeval}}
    7232 \subsection{\texorpdfstring{\LstBasicStyle{timeval}}{timeval}}
     6543\subsection{\texorpdfstring{\LstKeywordStyle{\textmd{timeval}}}{timeval}}
    72336544\label{s:timeval}
    72346545
     
    72496560
    72506561
    7251 %\subsection{\texorpdfstring{\protect\lstinline@timespec@}{timespec}}
    7252 \subsection{\texorpdfstring{\LstBasicStyle{timespec}}{timespec}}
     6562\subsection{\texorpdfstring{\protect\lstinline@timespec@}{timespec}}
    72536563\label{s:timespec}
    72546564
     
    72696579
    72706580
    7271 %\subsection{\texorpdfstring{\protect\lstinline@itimerval@}{itimerval}}
    7272 \subsection{\texorpdfstring{\LstBasicStyle{itimerval}}{itimerval}}
     6581\subsection{\texorpdfstring{\protect\lstinline@itimerval@}{itimerval}}
    72736582\label{s:itimerval}
    72746583
     
    72806589
    72816590
    7282 %\subsection{\texorpdfstring{\protect\lstinline@Time@}{Time}}
    7283 \subsection{\texorpdfstring{\LstBasicStyle{Time}}{Time}}
     6591\subsection{\texorpdfstring{\protect\lstinline@Time@}{Time}}
    72846592\label{s:Time}
    72856593
     
    72876595\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    72886596struct Time {
    7289         uint64_t tv; §\C{// nanoseconds since UNIX epoch}§
     6597        uint64_t tv;                                            §\C{// nanoseconds since UNIX epoch}§
    72906598};
    72916599
    72926600void ?{}( Time & time );
    72936601void ?{}( Time & time, zero_t );
    7294 
     6602void ?{}( Time & time, int year, int month = 0, int day = 0, int hour = 0, int min = 0, int sec = 0, int nsec = 0 );
    72956603Time ?=?( Time & time, zero_t );
    72966604
     
    73016609Time ?=?( Time & time, timespec t );
    73026610
    7303 Time ?+?( Time & lhs, Duration rhs );
    7304 Time ?+?( Duration lhs, Time rhs );
    7305 Time ?+=?( Time & lhs, Duration rhs );
    7306 
    7307 Duration ?-?( Time lhs, Time rhs );
    7308 Time ?-?( Time lhs, Duration rhs );
    7309 Time ?-=?( Time & lhs, Duration rhs );
    7310 _Bool ?==?( Time lhs, Time rhs );
    7311 _Bool ?!=?( Time lhs, Time rhs );
    7312 _Bool ?<?( Time lhs, Time rhs );
    7313 _Bool ?<=?( Time lhs, Time rhs );
    7314 _Bool ?>?( Time lhs, Time rhs );
    7315 _Bool ?>=?( Time lhs, Time rhs );
     6611Time ?+?( Time & lhs, Duration rhs ) { return (Time)@{ lhs.tv + rhs.tv }; }
     6612Time ?+?( Duration lhs, Time rhs ) { return rhs + lhs; }
     6613Time ?+=?( Time & lhs, Duration rhs ) { lhs = lhs + rhs; return lhs; }
     6614
     6615Duration ?-?( Time lhs, Time rhs ) { return (Duration)@{ lhs.tv - rhs.tv }; }
     6616Time ?-?( Time lhs, Duration rhs ) { return (Time)@{ lhs.tv - rhs.tv }; }
     6617Time ?-=?( Time & lhs, Duration rhs ) { lhs = lhs - rhs; return lhs; }
     6618_Bool ?==?( Time lhs, Time rhs ) { return lhs.tv == rhs.tv; }
     6619_Bool ?!=?( Time lhs, Time rhs ) { return lhs.tv != rhs.tv; }
     6620_Bool ?<?( Time lhs, Time rhs ) { return lhs.tv < rhs.tv; }
     6621_Bool ?<=?( Time lhs, Time rhs ) { return lhs.tv <= rhs.tv; }
     6622_Bool ?>?( Time lhs, Time rhs ) { return lhs.tv > rhs.tv; }
     6623_Bool ?>=?( Time lhs, Time rhs ) { return lhs.tv >= rhs.tv; }
     6624
     6625forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Time time );
    73166626
    73176627char * yy_mm_dd( Time time, char * buf );
     
    73316641
    73326642size_t strftime( char * buf, size_t size, const char * fmt, Time time );
    7333 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Time time );
    73346643\end{cfa}
    73356644
     
    73526661
    73536662%\subsection{\texorpdfstring{\protect\lstinline@Clock@}{Clock}}
    7354 \subsection{\texorpdfstring{\LstBasicStyle{Clock}}{Clock}}
     6663\subsection{\texorpdfstring{\LstKeywordStyle{\textmd{Clock}}}{Clock}}
    73556664\label{s:Clock}
    73566665
     
    73586667\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    73596668struct Clock {
    7360         Duration offset; §\C{// for virtual clock: contains offset from real-time}§
    7361         int clocktype; §\C{// implementation only -1 (virtual), CLOCK\_REALTIME}§
     6669        Duration offset;                                        §\C{// for virtual clock: contains offset from real-time}§
     6670        int clocktype;                                          §\C{// implementation only -1 (virtual), CLOCK\_REALTIME}§
    73626671};
    73636672
     
    73666675void ?{}( Clock & clk );
    73676676void ?{}( Clock & clk, Duration adj );
    7368 
    7369 Duration getResNsec(); §\C{// with nanoseconds}§
    7370 Duration getRes(); §\C{// without nanoseconds}§
    7371 
    7372 Time getTimeNsec(); §\C{// with nanoseconds}§
    7373 Time getTime(); §\C{// without nanoseconds}§
     6677Duration getRes();
     6678Time getTimeNsec();                                             §\C{// with nanoseconds}§
     6679Time getTime();                                                 §\C{// without nanoseconds}§
    73746680Time getTime( Clock & clk );
    73756681Time ?()( Clock & clk );
     
    73876693
    73886694\begin{cfa}
    7389 void ?{}( Int * this ); §\C{// constructor/destructor}§
     6695void ?{}( Int * this );                                 §\C{// constructor/destructor}§
    73906696void ?{}( Int * this, Int init );
    73916697void ?{}( Int * this, zero_t );
     
    73966702void ^?{}( Int * this );
    73976703
    7398 Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§
     6704Int ?=?( Int * lhs, Int rhs );                  §\C{// assignment}§
    73996705Int ?=?( Int * lhs, long int rhs );
    74006706Int ?=?( Int * lhs, unsigned long int rhs );
     
    74136719unsigned long int narrow( Int val );
    74146720
    7415 int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§
     6721int ?==?( Int oper1, Int oper2 );               §\C{// comparison}§
    74166722int ?==?( Int oper1, long int oper2 );
    74176723int ?==?( long int oper2, Int oper1 );
     
    74496755int ?>=?( unsigned long int oper1, Int oper2 );
    74506756
    7451 Int +?( Int oper ); §\C{// arithmetic}§
     6757Int +?( Int oper );                                             §\C{// arithmetic}§
    74526758Int -?( Int oper );
    74536759Int ~?( Int oper );
     
    75316837Int ?>>=?( Int * lhs, mp_bitcnt_t shift );
    75326838
    7533 Int abs( Int oper ); §\C{// number functions}§
     6839Int abs( Int oper );                                    §\C{// number functions}§
    75346840Int fact( unsigned long int N );
    75356841Int gcd( Int oper1, Int oper2 );
     
    75566862#include <gmp>§\indexc{gmp}§
    75576863int main( void ) {
    7558         sout | "Factorial Numbers";
     6864        sout | "Factorial Numbers" | endl;
    75596865        Int fact = 1;
    75606866
    7561         sout | 0 | fact;
     6867        sout | 0 | fact | endl;
    75626868        for ( unsigned int i = 1; i <= 40; i += 1 ) {
    75636869                fact *= i;
    7564                 sout | i | fact;
     6870                sout | i | fact | endl;
    75656871        }
    75666872}
     
    76426948// implementation
    76436949struct Rational {§\indexc{Rational}§
    7644         long int numerator, denominator; §\C{// invariant: denominator > 0}§
     6950        long int numerator, denominator;        §\C{// invariant: denominator > 0}§
    76456951}; // Rational
    76466952
    7647 Rational rational(); §\C{// constructors}§
     6953Rational rational();                                    §\C{// constructors}§
    76486954Rational rational( long int n );
    76496955Rational rational( long int n, long int d );
     
    76516957void ?{}( Rational * r, one_t );
    76526958
    7653 long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§
     6959long int numerator( Rational r );               §\C{// numerator/denominator getter/setter}§
    76546960long int numerator( Rational r, long int n );
    76556961long int denominator( Rational r );
    76566962long int denominator( Rational r, long int d );
    76576963
    7658 int ?==?( Rational l, Rational r ); §\C{// comparison}§
     6964int ?==?( Rational l, Rational r );             §\C{// comparison}§
    76596965int ?!=?( Rational l, Rational r );
    76606966int ?<?( Rational l, Rational r );
     
    76636969int ?>=?( Rational l, Rational r );
    76646970
    7665 Rational -?( Rational r ); §\C{// arithmetic}§
     6971Rational -?( Rational r );                              §\C{// arithmetic}§
    76666972Rational ?+?( Rational l, Rational r );
    76676973Rational ?-?( Rational l, Rational r );
     
    76696975Rational ?/?( Rational l, Rational r );
    76706976
    7671 double widen( Rational r ); §\C{// conversion}§
     6977double widen( Rational r );                             §\C{// conversion}§
    76726978Rational narrow( double f, long int md );
    76736979
  • doc/working/exception/impl/exception.c

    rb067d9b r7951100  
    243243
    244244                                        // Get a function pointer from the relative offset and call it
    245                                         // _Unwind_Reason_Code (*matcher)() = (_Unwind_Reason_Code (*)())lsd_info.LPStart + imatcher;
     245                                        // _Unwind_Reason_Code (*matcher)() = (_Unwind_Reason_Code (*)())lsd_info.LPStart + imatcher;                                   
    246246
    247247                                        _Unwind_Reason_Code (*matcher)() =
     
    320320        // on how the assembly works.
    321321        // Setup the personality routine
    322         #if defined(__PIC__)
    323         asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0");
    324         // Setup the exception table
    325         asm volatile (".cfi_lsda 0x1b, .LLSDACFA2");
    326         #else
    327322        asm volatile (".cfi_personality 0x3,__gcfa_personality_v0");
    328323        // Setup the exception table
    329324        asm volatile (".cfi_lsda 0x3, .LLSDACFA2");
    330         #endif
    331325
    332326        // Label which defines the start of the area for which the handler is setup
     
    362356// Some more works need to be done if we want to have a single
    363357// call to the try routine
    364 #if defined(__PIC__)
    365 asm (
    366         //HEADER
    367         ".LFECFA1:\n"
    368         "       .globl  __gcfa_personality_v0\n"
    369         "       .section        .gcc_except_table,\"a\",@progbits\n"
    370         ".LLSDACFA2:\n"                                                 //TABLE header
    371         "       .byte   0xff\n"
    372         "       .byte   0xff\n"
    373         "       .byte   0x1\n"
    374         "       .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n"         // BODY length
    375         // Body uses language specific data and therefore could be modified arbitrarily
    376         ".LLSDACSBCFA2:\n"                                              // BODY start
    377         "       .uleb128 .TRYSTART-__try_terminate\n"           // Handled area start  (relative to start of function)
    378         "       .uleb128 .TRYEND-.TRYSTART\n"                           // Handled area length
    379         "       .uleb128 .CATCH-__try_terminate\n"                      // Handler landing pad adress  (relative to start of function)
    380         "       .uleb128 1\n"                                           // Action code, gcc seems to use always 0
    381         ".LLSDACSECFA2:\n"                                              // BODY end
    382         "       .text\n"                                                        // TABLE footer
    383         "       .size   __try_terminate, .-__try_terminate\n"
    384 );
    385 
    386 // Somehow this piece of helps with the resolution of debug symbols.
    387 __attribute__((unused)) static const int dummy = 0;
    388 asm (
    389         "       .hidden CFA.ref.__gcfa_personality_v0\n"        // Declare an new hidden symbol
    390         "       .weak   CFA.ref.__gcfa_personality_v0\n"
    391         "       .section        .data.rel.local.CFA.ref.__gcfa_personality_v0,\"awG\",@progbits,CFA.ref.__gcfa_personality_v0,comdat\n" // No clue what this does specifically
    392         "       .align 8\n"
    393         "       .type CFA.ref.__gcfa_personality_v0, @object\n" // Type of our hidden symbol (it's not actually the function itself)
    394         "       .size CFA.ref.__gcfa_personality_v0, 8\n"               // Size of our hidden symbol
    395         "CFA.ref.__gcfa_personality_v0:\n"
    396         "       .quad __gcfa_personality_v0\n"
    397 );
    398 #else
    399358asm (
    400359        //HEADER
     
    416375        "       .text\n"                                                        // TABLE footer
    417376        "       .size   __try_terminate, .-__try_terminate\n"
     377        "       .ident  \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n"
     378//      "       .section        .note.GNU-stack,\"x\",@progbits\n"
    418379);
    419 #endif
  • src/CodeGen/CodeGenerator.cc

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Oct 19 19:30:38 2019
    13 // Update Count     : 506
     12// Last Modified On : Sat May  5 09:08:32 2018
     13// Update Count     : 494
    1414//
    1515#include "CodeGenerator.h"
     
    8383        void CodeGenerator::updateLocation( CodeLocation const & to ) {
    8484                // skip if linemarks shouldn't appear or if codelocation is unset
    85                 if ( !options.lineMarks || to.isUnset() ) return;
     85                if ( !lineMarks || to.isUnset() ) return;
    8686
    8787                if ( currentLocation.followedBy( to, 0 ) ) {
     
    116116        }
    117117
    118         CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks, bool printExprTypes ) : indent( 0, CodeGenerator::tabsize ), output( os ), printLabels( *this ), options( pretty, genC, lineMarks, printExprTypes ), endl( *this ) {}
    119         CodeGenerator::CodeGenerator( std::ostream & os, const Options &options ) : indent( 0, CodeGenerator::tabsize ), output( os ), printLabels( *this ), options(options), endl( *this ) {}
     118        CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks, bool printExprTypes ) : indent( CodeGenerator::tabsize ), output( os ), printLabels( *this ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ), printExprTypes( printExprTypes ), endl( *this ) {}
    120119
    121120        string CodeGenerator::mangleName( DeclarationWithType * decl ) {
    122121                // GCC builtins should always be printed unmangled
    123                 if ( options.pretty || decl->linkage.is_gcc_builtin ) return decl->name;
     122                if ( pretty || decl->linkage.is_gcc_builtin ) return decl->name;
    124123                if ( decl->mangleName != "" ) {
    125124                        // need to incorporate scope level in order to differentiate names for destructors
     
    134133                output << "__attribute__ ((";
    135134                for ( list< Attribute * >::iterator attr( attributes.begin() );; ) {
    136                         output << (*attr)->name;
    137                         if ( ! (*attr)->parameters.empty() ) {
     135                        output << (*attr)->get_name();
     136                        if ( ! (*attr)->get_parameters().empty() ) {
    138137                                output << "(";
    139                                 genCommaList( (*attr)->parameters.begin(), (*attr)->parameters.end() );
     138                                genCommaList( (*attr)->get_parameters().begin(), (*attr)->get_parameters().end() );
    140139                                output << ")";
    141140                        } // if
     
    165164                previsit( (BaseSyntaxNode *)node );
    166165                GuardAction( [this, node](){
    167                         if ( options.printExprTypes && node->result ) {
    168                                 output << " /* " << genType( node->result, "", options ) << " */ ";
     166                        if ( printExprTypes ) {
     167                                output << " /* " << genType( node->result, "", pretty, genC ) << " */ ";
    169168                        }
    170169                } );
     
    174173        void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
    175174                // deleted decls should never be used, so don't print them
    176                 if ( functionDecl->isDeleted && options.genC ) return;
     175                if ( functionDecl->isDeleted && genC ) return;
    177176                extension( functionDecl );
    178177                genAttributes( functionDecl->get_attributes() );
     
    181180                functionDecl->get_funcSpec().print( output );
    182181
    183                 Options subOptions = options;
    184                 subOptions.anonymousUnused = functionDecl->has_body();
    185                 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), subOptions );
     182                output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), pretty, genC );
    186183
    187184                asmName( functionDecl );
     
    197194        void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
    198195                // deleted decls should never be used, so don't print them
    199                 if ( objectDecl->isDeleted && options.genC ) return;
    200 
    201                 // gcc allows an empty declarator (no name) for bit-fields and C states: 6.7.2.1 Structure and union specifiers,
    202                 // point 4, page 113: If the (bit field) value is zero, the declaration shall have no declarator.  For anything
    203                 // else, the anonymous name refers to the anonymous object for plan9 inheritance.
    204                 if ( objectDecl->get_name().empty() && options.genC && ! objectDecl->get_bitfieldWidth() ) {
     196                if ( objectDecl->isDeleted && genC ) return;
     197                if (objectDecl->get_name().empty() && genC ) {
    205198                        // only generate an anonymous name when generating C code, otherwise it clutters the output too much
    206199                        static UniqueName name = { "__anonymous_object" };
    207200                        objectDecl->set_name( name.newName() );
    208                         // Stops unused parameter warnings.
    209                         if ( options.anonymousUnused ) {
    210                                 objectDecl->attributes.push_back( new Attribute( "unused" ) );
    211                         }
    212201                }
    213202
     
    216205
    217206                handleStorageClass( objectDecl );
    218                 output << genType( objectDecl->get_type(), mangleName( objectDecl ), options.pretty, options.genC );
     207                output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty, genC );
    219208
    220209                asmName( objectDecl );
     
    235224
    236225        void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) {
    237                 if( ! aggDecl->parameters.empty() && ! options.genC ) {
     226                if( ! aggDecl->get_parameters().empty() && ! genC ) {
    238227                        // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    239228                        output << "forall(";
    240                         genCommaList( aggDecl->parameters.begin(), aggDecl->parameters.end() );
     229                        genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() );
    241230                        output << ")" << endl;
    242231                        output << indent;
     
    244233
    245234                output << kind;
    246                 genAttributes( aggDecl->attributes );
    247                 output << aggDecl->name;
     235                genAttributes( aggDecl->get_attributes() );
     236                output << aggDecl->get_name();
    248237
    249238                if ( aggDecl->has_body() ) {
    250                         std::list< Declaration * > & memb = aggDecl->members;
     239                        std::list< Declaration * > & memb = aggDecl->get_members();
    251240                        output << " {" << endl;
    252241
     
    305294
    306295        void CodeGenerator::postvisit( TraitDecl * traitDecl ) {
    307                 assertf( ! options.genC, "TraitDecls should not reach code generation." );
     296                assertf( ! genC, "TraitDecls should not reach code generation." );
    308297                extension( traitDecl );
    309298                handleAggregate( traitDecl, "trait " );
     
    311300
    312301        void CodeGenerator::postvisit( TypedefDecl * typeDecl ) {
    313                 assertf( ! options.genC, "Typedefs are removed and substituted in earlier passes." );
     302                assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );
    314303                output << "typedef ";
    315                 output << genType( typeDecl->get_base(), typeDecl->get_name(), options ) << endl;
     304                output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl;
    316305        }
    317306
    318307        void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
    319                 assertf( ! options.genC, "TypeDecls should not reach code generation." );
     308                assertf( ! genC, "TypeDecls should not reach code generation." );
    320309                output << typeDecl->genTypeString() << " " << typeDecl->name;
    321310                if ( typeDecl->sized ) {
     
    382371
    383372        void CodeGenerator::postvisit( ConstructorInit * init ){
    384                 assertf( ! options.genC, "ConstructorInit nodes should not reach code generation." );
     373                assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
    385374                // pseudo-output for constructor/destructor pairs
    386375                output << "<ctorinit>{" << endl << ++indent << "ctor: ";
     
    518507                                        } else {
    519508                                                // no constructors with 0 or more than 2 parameters
    520                                                 assertf( ! options.genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
     509                                                assertf( ! genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
    521510                                                output << "(";
    522511                                                (*arg++)->accept( *visitor );
     
    615604                        // an lvalue cast, this has been taken out.
    616605                        output << "(";
    617                         output << genType( castExpr->get_result(), "", options );
     606                        output << genType( castExpr->get_result(), "", pretty, genC );
    618607                        output << ")";
    619608                } // if
     
    623612
    624613        void CodeGenerator::postvisit( KeywordCastExpr * castExpr ) {
    625                 assertf( ! options.genC, "KeywordCast should not reach code generation." );
     614                assertf( ! genC, "KeywordCast should not reach code generation." );
    626615                extension( castExpr );
    627616                output << "((" << castExpr->targetString() << " &)";
     
    631620
    632621        void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
    633                 assertf( ! options.genC, "VirtualCastExpr should not reach code generation." );
     622                assertf( ! genC, "VirtualCastExpr should not reach code generation." );
    634623                extension( castExpr );
    635624                output << "(virtual ";
     
    639628
    640629        void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
    641                 assertf( ! options.genC, "UntypedMemberExpr should not reach code generation." );
     630                assertf( ! genC, "UntypedMemberExpr should not reach code generation." );
    642631                extension( memberExpr );
    643632                memberExpr->get_aggregate()->accept( *visitor );
     
    672661                output << "sizeof(";
    673662                if ( sizeofExpr->get_isType() ) {
    674                         output << genType( sizeofExpr->get_type(), "", options );
     663                        output << genType( sizeofExpr->get_type(), "", pretty, genC );
    675664                } else {
    676665                        sizeofExpr->get_expr()->accept( *visitor );
     
    684673                output << "__alignof__(";
    685674                if ( alignofExpr->get_isType() ) {
    686                         output << genType( alignofExpr->get_type(), "", options );
     675                        output << genType( alignofExpr->get_type(), "", pretty, genC );
    687676                } else {
    688677                        alignofExpr->get_expr()->accept( *visitor );
     
    692681
    693682        void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
    694                 assertf( ! options.genC, "UntypedOffsetofExpr should not reach code generation." );
     683                assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );
    695684                output << "offsetof(";
    696                 output << genType( offsetofExpr->get_type(), "", options );
     685                output << genType( offsetofExpr->get_type(), "", pretty, genC );
    697686                output << ", " << offsetofExpr->get_member();
    698687                output << ")";
     
    702691                // use GCC builtin
    703692                output << "__builtin_offsetof(";
    704                 output << genType( offsetofExpr->get_type(), "", options );
     693                output << genType( offsetofExpr->get_type(), "", pretty, genC );
    705694                output << ", " << mangleName( offsetofExpr->get_member() );
    706695                output << ")";
     
    708697
    709698        void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
    710                 assertf( ! options.genC, "OffsetPackExpr should not reach code generation." );
    711                 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", options ) << ")";
     699                assertf( ! genC, "OffsetPackExpr should not reach code generation." );
     700                output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")";
    712701        }
    713702
     
    739728                extension( commaExpr );
    740729                output << "(";
    741                 if ( options.genC ) {
     730                if ( genC ) {
    742731                        // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
    743732                        commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
     
    750739
    751740        void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
    752                 assertf( ! options.genC, "TupleAssignExpr should not reach code generation." );
     741                assertf( ! genC, "TupleAssignExpr should not reach code generation." );
    753742                tupleExpr->stmtExpr->accept( *visitor );
    754743        }
    755744
    756745        void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
    757                 assertf( ! options.genC, "UntypedTupleExpr should not reach code generation." );
     746                assertf( ! genC, "UntypedTupleExpr should not reach code generation." );
    758747                extension( tupleExpr );
    759748                output << "[";
     
    763752
    764753        void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
    765                 assertf( ! options.genC, "TupleExpr should not reach code generation." );
     754                assertf( ! genC, "TupleExpr should not reach code generation." );
    766755                extension( tupleExpr );
    767756                output << "[";
     
    771760
    772761        void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
    773                 assertf( ! options.genC, "TupleIndexExpr should not reach code generation." );
     762                assertf( ! genC, "TupleIndexExpr should not reach code generation." );
    774763                extension( tupleExpr );
    775764                tupleExpr->get_tuple()->accept( *visitor );
     
    778767
    779768        void CodeGenerator::postvisit( TypeExpr * typeExpr ) {
    780                 // if ( options.genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
    781                 // assertf( ! options.genC, "TypeExpr should not reach code generation." );
    782                 if ( ! options.genC ) {
    783                         output << genType( typeExpr->get_type(), "", options );
     769                // if ( genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
     770                // assertf( ! genC, "TypeExpr should not reach code generation." );
     771                if ( ! genC ) {
     772                        output<< genType( typeExpr->get_type(), "", pretty, genC );
    784773                }
    785774        }
     
    799788        void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
    800789                assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
    801                 output << "(" << genType( compLitExpr->get_result(), "", options ) << ")";
     790                output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
    802791                compLitExpr->get_initializer()->accept( *visitor );
    803792        }
    804793
    805794        void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
    806                 assertf( ! options.genC, "Unique expressions should not reach code generation." );
     795                assertf( ! genC, "Unique expressions should not reach code generation." );
    807796                output << "unq<" << unqExpr->get_id() << ">{ ";
    808797                unqExpr->get_expr()->accept( *visitor );
     
    840829
    841830        void CodeGenerator::postvisit( ConstructorExpr * expr ) {
    842                 assertf( ! options.genC, "Unique expressions should not reach code generation." );
     831                assertf( ! genC, "Unique expressions should not reach code generation." );
    843832                expr->callExpr->accept( *visitor );
    844833        }
    845834
    846835        void CodeGenerator::postvisit( DeletedExpr * expr ) {
    847                 assertf( ! options.genC, "Deleted expressions should not reach code generation." );
     836                assertf( ! genC, "Deleted expressions should not reach code generation." );
    848837                expr->expr->accept( *visitor );
    849838        }
    850839
    851         void CodeGenerator::postvisit( DefaultArgExpr * arg ) {
    852                 assertf( ! options.genC, "Default argument expressions should not reach code generation." );
    853                 arg->expr->accept( *visitor );
    854         }
    855 
    856840        void CodeGenerator::postvisit( GenericExpr * expr ) {
    857                 assertf( ! options.genC, "C11 _Generic expressions should not reach code generation." );
     841                assertf( ! genC, "C11 _Generic expressions should not reach code generation." );
    858842                output << "_Generic(";
    859843                expr->control->accept( *visitor );
     
    865849                                output << "default: ";
    866850                        } else {
    867                                 output << genType( assoc.type, "", options ) << ": ";
     851                                output << genType( assoc.type, "", pretty, genC ) << ": ";
    868852                        }
    869853                        assoc.expr->accept( *visitor );
     
    900884        void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
    901885                assert( exprStmt );
    902                 if ( options.genC ) {
     886                if ( genC ) {
    903887                        // cast the top-level expression to void to reduce gcc warnings.
    904888                        exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
     
    1010994                  case BranchStmt::FallThrough:
    1011995                  case BranchStmt::FallThroughDefault:
    1012                         assertf( ! options.genC, "fallthru should not reach code generation." );
     996                        assertf( ! genC, "fallthru should not reach code generation." );
    1013997                  output << "fallthru";
    1014998                        break;
    1015999                } // switch
    10161000                // print branch target for labelled break/continue/fallthru in debug mode
    1017                 if ( ! options.genC && branchStmt->get_type() != BranchStmt::Goto ) {
     1001                if ( ! genC && branchStmt->get_type() != BranchStmt::Goto ) {
    10181002                        if ( ! branchStmt->get_target().empty() ) {
    10191003                                output << " " << branchStmt->get_target();
     
    10321016
    10331017        void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
    1034                 assertf( ! options.genC, "Throw statements should not reach code generation." );
     1018                assertf( ! genC, "Throw statements should not reach code generation." );
    10351019
    10361020                output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ?
     
    10471031        }
    10481032        void CodeGenerator::postvisit( CatchStmt * stmt ) {
    1049                 assertf( ! options.genC, "Catch statements should not reach code generation." );
     1033                assertf( ! genC, "Catch statements should not reach code generation." );
    10501034
    10511035                output << ((stmt->get_kind() == CatchStmt::Terminate) ?
     
    10641048
    10651049        void CodeGenerator::postvisit( WaitForStmt * stmt ) {
    1066                 assertf( ! options.genC, "Waitfor statements should not reach code generation." );
     1050                assertf( ! genC, "Waitfor statements should not reach code generation." );
    10671051
    10681052                bool first = true;
     
    11101094
    11111095        void CodeGenerator::postvisit( WithStmt * with ) {
    1112                 if ( ! options.genC ) {
     1096                if ( ! genC ) {
    11131097                        output << "with ( ";
    11141098                        genCommaList( with->exprs.begin(), with->exprs.end() );
     
    11761160
    11771161        void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
    1178                 assertf( ! options.genC, "ImplicitCtorDtorStmts should not reach code generation." );
     1162                assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );
    11791163                stmt->callStmt->accept( *visitor );
    11801164        }
  • src/CodeGen/CodeGenerator.h

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr 30 12:01:00 2019
    13 // Update Count     : 57
     12// Last Modified On : Fri Aug 18 15:40:00 2017
     13// Update Count     : 56
    1414//
    1515
     
    2020#include <string>                 // for string
    2121
    22 #include "CodeGen/Options.h"      // for Options
    2322#include "Common/Indenter.h"      // for Indenter
    2423#include "Common/PassVisitor.h"   // for PassVisitor
     
    3231
    3332                CodeGenerator( std::ostream &os, bool pretty = false, bool genC = false, bool lineMarks = false, bool printExprTypes = false );
    34                 CodeGenerator( std::ostream &os, const Options &options );
    3533
    3634                //*** Turn off visit_children for all nodes
     
    9694                void postvisit( ConstructorExpr * );
    9795                void postvisit( DeletedExpr * );
    98                 void postvisit( DefaultArgExpr * );
    9996                void postvisit( GenericExpr * );
    10097
     
    146143                std::ostream & output;
    147144                LabelPrinter printLabels;
    148                 Options options;
     145                bool pretty = false;  // pretty print
     146                bool genC = false;    // true if output has to be C code
     147                bool lineMarks = false;
     148                bool printExprTypes = false;
    149149        public:
    150150                LineEnder endl;
  • src/CodeGen/GenType.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May  1 15:24:00 2019
    13 // Update Count     : 23
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Mar 17 09:02:28 2017
     13// Update Count     : 22
    1414//
    1515#include "GenType.h"
     
    2727namespace CodeGen {
    2828        struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
    29                 std::string typeString;
    30                 GenType( const std::string &typeString, const Options &options );
     29                GenType( const std::string &typeString, bool pretty = false, bool genC = false, bool lineMarks = false );
     30                std::string get_typeString() const { return typeString; }
     31                void set_typeString( const std::string &newValue ) { typeString = newValue; }
    3132
    3233                void previsit( BaseSyntaxNode * );
     
    4748                void postvisit( ZeroType * zeroType );
    4849                void postvisit( OneType * oneType );
    49                 void postvisit( GlobalScopeType * globalType );
    5050                void postvisit( TraitInstType * inst );
    5151                void postvisit( TypeofType * typeof );
    52                 void postvisit( QualifiedType * qualType );
    5352
    5453          private:
     
    5756                void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
    5857
    59                 Options options;
     58                std::string typeString;
     59                bool pretty = false; // pretty print
     60                bool genC = false;   // generating C code?
     61                bool lineMarks = false;
    6062        };
    6163
    62         std::string genType( Type *type, const std::string &baseString, const Options &options ) {
    63                 PassVisitor<GenType> gt( baseString, options );
     64        std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
     65                PassVisitor<GenType> gt( baseString, pretty, genC, lineMarks );
    6466                std::ostringstream os;
    6567
    6668                if ( ! type->get_attributes().empty() ) {
    67                         PassVisitor<CodeGenerator> cg( os, options );
     69                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    6870                        cg.pass.genAttributes( type->get_attributes() );
    6971                } // if
    7072
    7173                type->accept( gt );
    72                 return os.str() + gt.pass.typeString;
    73         }
    74 
    75         std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
    76                 return genType( type, baseString, Options(pretty, genC, lineMarks, false ) );
    77         }
    78 
    79         std::string genPrettyType( Type * type, const std::string & baseString ) {
    80                 return genType( type, baseString, true, false );
    81         }
    82 
    83         GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {}
     74                return os.str() + gt.pass.get_typeString();
     75        }
     76
     77  std::string genPrettyType( Type * type, const std::string & baseString ) {
     78        return genType( type, baseString, true, false );
     79  }
     80
     81        GenType::GenType( const std::string &typeString, bool pretty, bool genC, bool lineMarks ) : typeString( typeString ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ) {}
    8482
    8583        // *** BaseSyntaxNode
     
    135133                } // if
    136134                if ( dimension != 0 ) {
    137                         PassVisitor<CodeGenerator> cg( os, options );
     135                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    138136                        dimension->accept( cg );
    139137                } else if ( isVarLen ) {
     
    169167        void GenType::postvisit( ReferenceType * refType ) {
    170168                assert( refType->base != 0);
    171                 assertf( ! options.genC, "Reference types should not reach code generation." );
     169                assertf( ! genC, "Reference types should not reach code generation." );
    172170                handleQualifiers( refType );
    173171                typeString = "&" + typeString;
     
    197195                        } // if
    198196                } else {
    199                         PassVisitor<CodeGenerator> cg( os, options );
     197                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    200198                        os << "(" ;
    201199
     
    217215
    218216                // add forall
    219                 if( ! funcType->forall.empty() && ! options.genC ) {
     217                if( ! funcType->forall.empty() && ! genC ) {
    220218                        // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    221219                        std::ostringstream os;
    222                         PassVisitor<CodeGenerator> cg( os, options );
     220                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    223221                        os << "forall(";
    224222                        cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() );
     
    231229                if ( ! refType->parameters.empty() ) {
    232230                        std::ostringstream os;
    233                         PassVisitor<CodeGenerator> cg( os, options );
     231                        PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    234232                        os << "(";
    235233                        cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
     
    242240        void GenType::postvisit( StructInstType * structInst )  {
    243241                typeString = structInst->name + handleGeneric( structInst ) + " " + typeString;
    244                 if ( options.genC ) typeString = "struct " + typeString;
     242                if ( genC ) typeString = "struct " + typeString;
    245243                handleQualifiers( structInst );
    246244        }
     
    248246        void GenType::postvisit( UnionInstType * unionInst ) {
    249247                typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString;
    250                 if ( options.genC ) typeString = "union " + typeString;
     248                if ( genC ) typeString = "union " + typeString;
    251249                handleQualifiers( unionInst );
    252250        }
     
    254252        void GenType::postvisit( EnumInstType * enumInst ) {
    255253                typeString = enumInst->name + " " + typeString;
    256                 if ( options.genC ) typeString = "enum " + typeString;
     254                if ( genC ) typeString = "enum " + typeString;
    257255                handleQualifiers( enumInst );
    258256        }
     
    264262
    265263        void GenType::postvisit( TupleType * tupleType ) {
    266                 assertf( ! options.genC, "Tuple types should not reach code generation." );
     264                assertf( ! genC, "Tuple types should not reach code generation." );
    267265                unsigned int i = 0;
    268266                std::ostringstream os;
     
    270268                for ( Type * t : *tupleType ) {
    271269                        i++;
    272                         os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", ");
     270                        os << genType( t, "", pretty, genC, lineMarks ) << (i == tupleType->size() ? "" : ", ");
    273271                }
    274272                os << "] ";
     
    283281        void GenType::postvisit( ZeroType * zeroType ) {
    284282                // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    285                 typeString = (options.pretty ? "zero_t " : "long int ") + typeString;
     283                typeString = (pretty ? "zero_t " : "long int ") + typeString;
    286284                handleQualifiers( zeroType );
    287285        }
     
    289287        void GenType::postvisit( OneType * oneType ) {
    290288                // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    291                 typeString = (options.pretty ? "one_t " : "long int ") + typeString;
     289                typeString = (pretty ? "one_t " : "long int ") + typeString;
    292290                handleQualifiers( oneType );
    293291        }
    294292
    295         void GenType::postvisit( GlobalScopeType * globalType ) {
    296                 assertf( ! options.genC, "Global scope type should not reach code generation." );
    297                 handleQualifiers( globalType );
    298         }
    299 
    300293        void GenType::postvisit( TraitInstType * inst ) {
    301                 assertf( ! options.genC, "Trait types should not reach code generation." );
     294                assertf( ! genC, "Trait types should not reach code generation." );
    302295                typeString = inst->name + " " + typeString;
    303296                handleQualifiers( inst );
     
    306299        void GenType::postvisit( TypeofType * typeof ) {
    307300                std::ostringstream os;
    308                 PassVisitor<CodeGenerator> cg( os, options );
     301                PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    309302                os << "typeof(";
    310303                typeof->expr->accept( cg );
     
    314307        }
    315308
    316         void GenType::postvisit( QualifiedType * qualType ) {
    317                 assertf( ! options.genC, "Qualified types should not reach code generation." );
    318                 std::ostringstream os;
    319                 os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString;
    320                 typeString = os.str();
    321                 handleQualifiers( qualType );
    322         }
    323 
    324309        void GenType::handleQualifiers( Type * type ) {
    325310                if ( type->get_const() ) {
     
    335320                        typeString = "_Atomic " + typeString;
    336321                } // if
     322                if ( type->get_lvalue() && ! genC ) {
     323                        // when not generating C code, print lvalue for debugging.
     324                        typeString = "lvalue " + typeString;
     325                }
    337326        }
    338327} // namespace CodeGen
  • src/CodeGen/GenType.h

    rb067d9b r7951100  
    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 : Tue Apr 30 11:47:00 2019
    13 // Update Count     : 3
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 22:17:23 2017
     13// Update Count     : 2
    1414//
    1515
     
    1818#include <string>  // for string
    1919
    20 #include "CodeGen/Options.h" // for Options
    21 
    2220class Type;
    2321
    2422namespace CodeGen {
    25         std::string genType( Type *type, const std::string &baseString, const Options &options );
    2623        std::string genType( Type *type, const std::string &baseString, bool pretty = false, bool genC = false, bool lineMarks = false );
    2724  std::string genPrettyType( Type * type, const std::string & baseString );
  • src/CodeGen/module.mk

    rb067d9b r7951100  
    1818#       ArgTweak/Mutate.cc
    1919
    20 SRC_CODEGEN = \
     20SRC +=  CodeGen/Generate.cc \
    2121        CodeGen/CodeGenerator.cc \
     22        CodeGen/GenType.cc \
     23        CodeGen/FixNames.cc \
    2224        CodeGen/FixMain.cc \
    23         CodeGen/GenType.cc \
    2425        CodeGen/OperatorTable.cc
    25 
    26 
    27 SRC += $(SRC_CODEGEN) CodeGen/Generate.cc CodeGen/FixNames.cc
    28 SRCDEMANGLE += $(SRC_CODEGEN)
  • src/CodeTools/module.mk

    rb067d9b r7951100  
    1616
    1717SRC += CodeTools/DeclStats.cc \
    18         CodeTools/ResolvProtoDump.cc \
    1918        CodeTools/TrackLoc.cc
  • src/Common/Assert.cc

    rb067d9b r7951100  
    3939}
    4040
    41 void abort(const char *fmt, ... ) noexcept __attribute__((noreturn, format(printf, 1, 2)));
    42 void abort(const char *fmt, ... ) noexcept {
    43         va_list args;
    44         va_start( args, fmt );
    45         vfprintf( stderr, fmt, args );
    46         va_end( args );
    47         fprintf( stderr, "\n" );
    48         abort();
    49 }
    50 
    5141// Local Variables: //
    5242// tab-width: 4 //
  • src/Common/Debug.h

    rb067d9b r7951100  
    2828namespace Debug {
    2929        /// debug codegen a translation unit
    30         static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Builtin ) {
     30        static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
    3131        #ifdef DEBUG
    3232                std::list< Declaration * > decls;
  • src/Common/Indenter.h

    rb067d9b r7951100  
    1818
    1919struct Indenter {
    20         static unsigned tabsize;  ///< default number of spaces in one level of indentation
     20        static unsigned tabsize;
    2121
    22         unsigned int indent;      ///< number of spaces to indent
    23         unsigned int amt;         ///< spaces in one level of indentation
     22        Indenter( unsigned int amt = tabsize, unsigned int indent = 0 ) : amt( amt ), indent( indent ) {}
     23        unsigned int amt;  // amount 1 level increases indent by (i.e. how much to increase by in operator++)
     24        unsigned int indent;
    2425
    25         Indenter( unsigned int indent = 0, unsigned int amt = tabsize )
    26         : indent( indent ), amt( amt ) {}
    27 
    28         Indenter & operator+=(int nlevels) { indent += nlevels; return *this; }
    29         Indenter & operator-=(int nlevels) { indent -= nlevels; return *this; }
     26        Indenter & operator+=(int nlevels) { indent += amt*nlevels; return *this; }
     27        Indenter & operator-=(int nlevels) { indent -= amt*nlevels; return *this; }
    3028        Indenter operator+(int nlevels) { Indenter indenter = *this; return indenter += nlevels; }
    3129        Indenter operator-(int nlevels) { Indenter indenter = *this; return indenter -= nlevels; }
     
    3533
    3634inline std::ostream & operator<<( std::ostream & out, const Indenter & indent ) {
    37         return out << std::string(indent.indent * indent.amt, ' ');
     35        return out << std::string(indent.indent, ' ');
    3836}
    3937
  • src/Common/PassVisitor.h

    rb067d9b r7951100  
    44
    55#include <stack>
    6 #include <type_traits>
    7 
    8 #include "Common/Stats.h"
     6
    97#include "Common/utility.h"
    108
     
    6058
    6159        virtual void visit( ObjectDecl * objectDecl ) override final;
    62         virtual void visit( const ObjectDecl * objectDecl ) override final;
    6360        virtual void visit( FunctionDecl * functionDecl ) override final;
    64         virtual void visit( const FunctionDecl * functionDecl ) override final;
    6561        virtual void visit( StructDecl * aggregateDecl ) override final;
    66         virtual void visit( const StructDecl * aggregateDecl ) override final;
    6762        virtual void visit( UnionDecl * aggregateDecl ) override final;
    68         virtual void visit( const UnionDecl * aggregateDecl ) override final;
    6963        virtual void visit( EnumDecl * aggregateDecl ) override final;
    70         virtual void visit( const EnumDecl * aggregateDecl ) override final;
    7164        virtual void visit( TraitDecl * aggregateDecl ) override final;
    72         virtual void visit( const TraitDecl * aggregateDecl ) override final;
    7365        virtual void visit( TypeDecl * typeDecl ) override final;
    74         virtual void visit( const TypeDecl * typeDecl ) override final;
    7566        virtual void visit( TypedefDecl * typeDecl ) override final;
    76         virtual void visit( const TypedefDecl * typeDecl ) override final;
    7767        virtual void visit( AsmDecl * asmDecl ) override final;
    78         virtual void visit( const AsmDecl * asmDecl ) override final;
    7968        virtual void visit( StaticAssertDecl * assertDecl ) override final;
    80         virtual void visit( const StaticAssertDecl * assertDecl ) override final;
    8169
    8270        virtual void visit( CompoundStmt * compoundStmt ) override final;
    83         virtual void visit( const CompoundStmt * compoundStmt ) override final;
    8471        virtual void visit( ExprStmt * exprStmt ) override final;
    85         virtual void visit( const ExprStmt * exprStmt ) override final;
    8672        virtual void visit( AsmStmt * asmStmt ) override final;
    87         virtual void visit( const AsmStmt * asmStmt ) override final;
    8873        virtual void visit( DirectiveStmt * dirStmt ) override final;
    89         virtual void visit( const DirectiveStmt * dirStmt ) override final;
    9074        virtual void visit( IfStmt * ifStmt ) override final;
    91         virtual void visit( const IfStmt * ifStmt ) override final;
    9275        virtual void visit( WhileStmt * whileStmt ) override final;
    93         virtual void visit( const WhileStmt * whileStmt ) override final;
    9476        virtual void visit( ForStmt * forStmt ) override final;
    95         virtual void visit( const ForStmt * forStmt ) override final;
    9677        virtual void visit( SwitchStmt * switchStmt ) override final;
    97         virtual void visit( const SwitchStmt * switchStmt ) override final;
    9878        virtual void visit( CaseStmt * caseStmt ) override final;
    99         virtual void visit( const CaseStmt * caseStmt ) override final;
    10079        virtual void visit( BranchStmt * branchStmt ) override final;
    101         virtual void visit( const BranchStmt * branchStmt ) override final;
    10280        virtual void visit( ReturnStmt * returnStmt ) override final;
    103         virtual void visit( const ReturnStmt * returnStmt ) override final;
    10481        virtual void visit( ThrowStmt * throwStmt ) override final;
    105         virtual void visit( const ThrowStmt * throwStmt ) override final;
    10682        virtual void visit( TryStmt * tryStmt ) override final;
    107         virtual void visit( const TryStmt * tryStmt ) override final;
    10883        virtual void visit( CatchStmt * catchStmt ) override final;
    109         virtual void visit( const CatchStmt * catchStmt ) override final;
    11084        virtual void visit( FinallyStmt * finallyStmt ) override final;
    111         virtual void visit( const FinallyStmt * finallyStmt ) override final;
    11285        virtual void visit( WaitForStmt * waitforStmt ) override final;
    113         virtual void visit( const WaitForStmt * waitforStmt ) override final;
    11486        virtual void visit( WithStmt * withStmt ) override final;
    115         virtual void visit( const WithStmt * withStmt ) override final;
    11687        virtual void visit( NullStmt * nullStmt ) override final;
    117         virtual void visit( const NullStmt * nullStmt ) override final;
    11888        virtual void visit( DeclStmt * declStmt ) override final;
    119         virtual void visit( const DeclStmt * declStmt ) override final;
    12089        virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
    121         virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
    12290
    12391        virtual void visit( ApplicationExpr * applicationExpr ) override final;
    124         virtual void visit( const ApplicationExpr * applicationExpr ) override final;
    12592        virtual void visit( UntypedExpr * untypedExpr ) override final;
    126         virtual void visit( const UntypedExpr * untypedExpr ) override final;
    12793        virtual void visit( NameExpr * nameExpr ) override final;
    128         virtual void visit( const NameExpr * nameExpr ) override final;
    12994        virtual void visit( CastExpr * castExpr ) override final;
    130         virtual void visit( const CastExpr * castExpr ) override final;
    13195        virtual void visit( KeywordCastExpr * castExpr ) override final;
    132         virtual void visit( const KeywordCastExpr * castExpr ) override final;
    13396        virtual void visit( VirtualCastExpr * castExpr ) override final;
    134         virtual void visit( const VirtualCastExpr * castExpr ) override final;
    13597        virtual void visit( AddressExpr * addressExpr ) override final;
    136         virtual void visit( const AddressExpr * addressExpr ) override final;
    13798        virtual void visit( LabelAddressExpr * labAddressExpr ) override final;
    138         virtual void visit( const LabelAddressExpr * labAddressExpr ) override final;
    13999        virtual void visit( UntypedMemberExpr * memberExpr ) override final;
    140         virtual void visit( const UntypedMemberExpr * memberExpr ) override final;
    141100        virtual void visit( MemberExpr * memberExpr ) override final;
    142         virtual void visit( const MemberExpr * memberExpr ) override final;
    143101        virtual void visit( VariableExpr * variableExpr ) override final;
    144         virtual void visit( const VariableExpr * variableExpr ) override final;
    145102        virtual void visit( ConstantExpr * constantExpr ) override final;
    146         virtual void visit( const ConstantExpr * constantExpr ) override final;
    147103        virtual void visit( SizeofExpr * sizeofExpr ) override final;
    148         virtual void visit( const SizeofExpr * sizeofExpr ) override final;
    149104        virtual void visit( AlignofExpr * alignofExpr ) override final;
    150         virtual void visit( const AlignofExpr * alignofExpr ) override final;
    151105        virtual void visit( UntypedOffsetofExpr * offsetofExpr ) override final;
    152         virtual void visit( const UntypedOffsetofExpr * offsetofExpr ) override final;
    153106        virtual void visit( OffsetofExpr * offsetofExpr ) override final;
    154         virtual void visit( const OffsetofExpr * offsetofExpr ) override final;
    155107        virtual void visit( OffsetPackExpr * offsetPackExpr ) override final;
    156         virtual void visit( const OffsetPackExpr * offsetPackExpr ) override final;
     108        virtual void visit( AttrExpr * attrExpr ) override final;
    157109        virtual void visit( LogicalExpr * logicalExpr ) override final;
    158         virtual void visit( const LogicalExpr * logicalExpr ) override final;
    159110        virtual void visit( ConditionalExpr * conditionalExpr ) override final;
    160         virtual void visit( const ConditionalExpr * conditionalExpr ) override final;
    161111        virtual void visit( CommaExpr * commaExpr ) override final;
    162         virtual void visit( const CommaExpr * commaExpr ) override final;
    163112        virtual void visit( TypeExpr * typeExpr ) override final;
    164         virtual void visit( const TypeExpr * typeExpr ) override final;
    165113        virtual void visit( AsmExpr * asmExpr ) override final;
    166         virtual void visit( const AsmExpr * asmExpr ) override final;
    167114        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
    168         virtual void visit( const ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
    169115        virtual void visit( ConstructorExpr *  ctorExpr ) override final;
    170         virtual void visit( const ConstructorExpr *  ctorExpr ) override final;
    171116        virtual void visit( CompoundLiteralExpr * compLitExpr ) override final;
    172         virtual void visit( const CompoundLiteralExpr * compLitExpr ) override final;
    173117        virtual void visit( RangeExpr * rangeExpr ) override final;
    174         virtual void visit( const RangeExpr * rangeExpr ) override final;
    175118        virtual void visit( UntypedTupleExpr * tupleExpr ) override final;
    176         virtual void visit( const UntypedTupleExpr * tupleExpr ) override final;
    177119        virtual void visit( TupleExpr * tupleExpr ) override final;
    178         virtual void visit( const TupleExpr * tupleExpr ) override final;
    179120        virtual void visit( TupleIndexExpr * tupleExpr ) override final;
    180         virtual void visit( const TupleIndexExpr * tupleExpr ) override final;
    181121        virtual void visit( TupleAssignExpr * assignExpr ) override final;
    182         virtual void visit( const TupleAssignExpr * assignExpr ) override final;
    183122        virtual void visit( StmtExpr *  stmtExpr ) override final;
    184         virtual void visit( const StmtExpr *  stmtExpr ) override final;
    185123        virtual void visit( UniqueExpr *  uniqueExpr ) override final;
    186         virtual void visit( const UniqueExpr *  uniqueExpr ) override final;
    187124        virtual void visit( UntypedInitExpr *  initExpr ) override final;
    188         virtual void visit( const UntypedInitExpr *  initExpr ) override final;
    189125        virtual void visit( InitExpr *  initExpr ) override final;
    190         virtual void visit( const InitExpr *  initExpr ) override final;
    191126        virtual void visit( DeletedExpr *  delExpr ) override final;
    192         virtual void visit( const DeletedExpr *  delExpr ) override final;
    193         virtual void visit( DefaultArgExpr * argExpr ) override final;
    194         virtual void visit( const DefaultArgExpr * argExpr ) override final;
    195127        virtual void visit( GenericExpr * genExpr ) override final;
    196         virtual void visit( const GenericExpr * genExpr ) override final;
    197128
    198129        virtual void visit( VoidType * basicType ) override final;
    199         virtual void visit( const VoidType * basicType ) override final;
    200130        virtual void visit( BasicType * basicType ) override final;
    201         virtual void visit( const BasicType * basicType ) override final;
    202131        virtual void visit( PointerType * pointerType ) override final;
    203         virtual void visit( const PointerType * pointerType ) override final;
    204132        virtual void visit( ArrayType * arrayType ) override final;
    205         virtual void visit( const ArrayType * arrayType ) override final;
    206133        virtual void visit( ReferenceType * referenceType ) override final;
    207         virtual void visit( const ReferenceType * referenceType ) override final;
    208         virtual void visit( QualifiedType * qualType ) override final;
    209         virtual void visit( const QualifiedType * qualType ) override final;
    210134        virtual void visit( FunctionType * functionType ) override final;
    211         virtual void visit( const FunctionType * functionType ) override final;
    212135        virtual void visit( StructInstType * aggregateUseType ) override final;
    213         virtual void visit( const StructInstType * aggregateUseType ) override final;
    214136        virtual void visit( UnionInstType * aggregateUseType ) override final;
    215         virtual void visit( const UnionInstType * aggregateUseType ) override final;
    216137        virtual void visit( EnumInstType * aggregateUseType ) override final;
    217         virtual void visit( const EnumInstType * aggregateUseType ) override final;
    218138        virtual void visit( TraitInstType * aggregateUseType ) override final;
    219         virtual void visit( const TraitInstType * aggregateUseType ) override final;
    220139        virtual void visit( TypeInstType * aggregateUseType ) override final;
    221         virtual void visit( const TypeInstType * aggregateUseType ) override final;
    222140        virtual void visit( TupleType * tupleType ) override final;
    223         virtual void visit( const TupleType * tupleType ) override final;
    224141        virtual void visit( TypeofType * typeofType ) override final;
    225         virtual void visit( const TypeofType * typeofType ) override final;
    226142        virtual void visit( AttrType * attrType ) override final;
    227         virtual void visit( const AttrType * attrType ) override final;
    228143        virtual void visit( VarArgsType * varArgsType ) override final;
    229         virtual void visit( const VarArgsType * varArgsType ) override final;
    230144        virtual void visit( ZeroType * zeroType ) override final;
    231         virtual void visit( const ZeroType * zeroType ) override final;
    232145        virtual void visit( OneType * oneType ) override final;
    233         virtual void visit( const OneType * oneType ) override final;
    234         virtual void visit( GlobalScopeType * globalType ) override final;
    235         virtual void visit( const GlobalScopeType * globalType ) override final;
    236146
    237147        virtual void visit( Designation * designation ) override final;
    238         virtual void visit( const Designation * designation ) override final;
    239148        virtual void visit( SingleInit * singleInit ) override final;
    240         virtual void visit( const SingleInit * singleInit ) override final;
    241149        virtual void visit( ListInit * listInit ) override final;
    242         virtual void visit( const ListInit * listInit ) override final;
    243150        virtual void visit( ConstructorInit * ctorInit ) override final;
    244         virtual void visit( const ConstructorInit * ctorInit ) override final;
     151
     152        virtual void visit( Subrange * subrange ) override final;
    245153
    246154        virtual void visit( Constant * constant ) override final;
    247         virtual void visit( const Constant * constant ) override final;
    248155
    249156        virtual void visit( Attribute * attribute ) override final;
    250         virtual void visit( const Attribute * attribute ) override final;
    251157
    252158        virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override final;
     
    277183        virtual Statement * mutate( FinallyStmt * finallyStmt ) override final;
    278184        virtual Statement * mutate( WaitForStmt * waitforStmt ) override final;
    279         virtual Declaration * mutate( WithStmt * withStmt ) override final;
     185        virtual Statement * mutate( WithStmt * withStmt ) override final;
    280186        virtual NullStmt * mutate( NullStmt * nullStmt ) override final;
    281187        virtual Statement * mutate( DeclStmt * declStmt ) override final;
     
    299205        virtual Expression * mutate( OffsetofExpr * offsetofExpr ) override final;
    300206        virtual Expression * mutate( OffsetPackExpr * offsetPackExpr ) override final;
     207        virtual Expression * mutate( AttrExpr * attrExpr ) override final;
    301208        virtual Expression * mutate( LogicalExpr * logicalExpr ) override final;
    302209        virtual Expression * mutate( ConditionalExpr * conditionalExpr ) override final;
     
    317224        virtual Expression * mutate( InitExpr *  initExpr ) override final;
    318225        virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
    319         virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
    320226        virtual Expression * mutate( GenericExpr * genExpr ) override final;
    321227
     
    325231        virtual Type * mutate( ArrayType * arrayType ) override final;
    326232        virtual Type * mutate( ReferenceType * referenceType ) override final;
    327         virtual Type * mutate( QualifiedType * qualType ) override final;
    328233        virtual Type * mutate( FunctionType * functionType ) override final;
    329234        virtual Type * mutate( StructInstType * aggregateUseType ) override final;
     
    338243        virtual Type * mutate( ZeroType * zeroType ) override final;
    339244        virtual Type * mutate( OneType * oneType ) override final;
    340         virtual Type * mutate( GlobalScopeType * globalType ) override final;
    341245
    342246        virtual Designation * mutate( Designation * designation ) override final;
     
    345249        virtual Initializer * mutate( ConstructorInit * ctorInit ) override final;
    346250
     251        virtual Subrange * mutate( Subrange * subrange ) override final;
     252
    347253        virtual Constant * mutate( Constant * constant ) override final;
    348254
     
    352258
    353259private:
    354         bool inFunction = false;
    355 
    356260        template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
    357         template<typename pass_t> friend void acceptAll( const std::list< const Declaration * > &decls, PassVisitor< pass_t >& visitor );
    358261        template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
    359262        template< typename TreeType, typename pass_t > friend void maybeAccept_impl( TreeType * tree, PassVisitor< pass_t > & visitor );
    360         template< typename TreeType, typename pass_t > friend void maybeAccept_impl( const TreeType * tree, PassVisitor< pass_t > & visitor );
    361263        template< typename TreeType, typename pass_t > friend void maybeMutate_impl( TreeType *& tree, PassVisitor< pass_t > & mutator );
    362264        template< typename Container, typename pass_t > friend void maybeAccept_impl( Container & container, PassVisitor< pass_t > & visitor );
    363         template< typename Container, typename pass_t > friend void maybeAccept_impl( const Container & container, PassVisitor< pass_t > & visitor );
    364265        template< typename Container, typename pass_t > friend void maybeMutate_impl( Container & container, PassVisitor< pass_t > & mutator );
    365266
    366267        template<typename node_type> void call_previsit ( node_type * node ) { previsit_impl ( pass, node, 0 ); }
    367         template<typename node_type> void call_previsit ( const node_type * node ) { previsit_impl ( pass, node, 0 ); }
    368268        template<typename node_type> void call_postvisit( node_type * node ) { postvisit_impl( pass, node, 0 ); }
    369         template<typename node_type> void call_postvisit( const node_type * node ) { postvisit_impl( pass, node, 0 ); }
    370269
    371270        template<typename node_type> void call_premutate ( node_type * node ) { premutate_impl( pass, node, 0 ); }
     
    381280        void visitStatementList ( std::list< Statement* > &statements );
    382281        void mutateStatementList( std::list< Statement* > &statements );
    383         void visitStatementList ( const std::list< Statement * > & statements );
    384282
    385283        template< typename func_t >
     
    387285        Statement * visitStatement ( Statement * stmt );
    388286        Statement * mutateStatement( Statement * stmt );
    389         void visitStatement ( const Statement * stmt );
    390287
    391288        template< typename func_t >
     
    393290        Expression * visitExpression ( Expression * expr );
    394291        Expression * mutateExpression( Expression * expr );
    395         void visitExpression ( const Expression * expr );
    396 
    397 
    398         auto                                    get_env_ptr    () -> decltype(env_impl( pass, 0)) { return env_impl( pass, 0); }
     292
     293
     294        TypeSubstitution **             get_env_ptr    () { return env_impl             ( pass, 0); }
    399295        std::list< Statement* > *       get_beforeStmts() { return stmtsToAddBefore_impl( pass, 0); }
    400296        std::list< Statement* > *       get_afterStmts () { return stmtsToAddAfter_impl ( pass, 0); }
     
    407303        void indexerScopeEnter  ()                                    { indexer_impl_enterScope  ( pass, 0       ); }
    408304        void indexerScopeLeave  ()                                    { indexer_impl_leaveScope  ( pass, 0       ); }
    409         void indexerAddId       ( const DeclarationWithType * node  ) { indexer_impl_addId       ( pass, 0, node ); }
    410         void indexerAddType     ( const NamedTypeDecl       * node  ) { indexer_impl_addType     ( pass, 0, node ); }
     305        void indexerAddId       ( DeclarationWithType      * node  ) { indexer_impl_addId       ( pass, 0, node ); }
     306        void indexerAddType     ( NamedTypeDecl             * node  ) { indexer_impl_addType     ( pass, 0, node ); }
    411307        void indexerAddStruct   ( const std::string         & id    ) { indexer_impl_addStruct   ( pass, 0, id   ); }
    412         void indexerAddStruct   ( const StructDecl          * node  ) { indexer_impl_addStruct   ( pass, 0, node ); }
    413         void indexerAddStructFwd( const StructDecl          * node  ) { indexer_impl_addStructFwd( pass, 0, node ); }
    414         void indexerAddEnum     ( const EnumDecl            * node  ) { indexer_impl_addEnum     ( pass, 0, node ); }
     308        void indexerAddStruct   ( StructDecl                * node  ) { indexer_impl_addStruct   ( pass, 0, node ); }
     309        void indexerAddStructFwd( StructDecl                * node  ) { indexer_impl_addStructFwd( pass, 0, node ); }
     310        void indexerAddEnum     ( EnumDecl                  * node  ) { indexer_impl_addEnum     ( pass, 0, node ); }
    415311        void indexerAddUnion    ( const std::string         & id    ) { indexer_impl_addUnion    ( pass, 0, id   ); }
    416         void indexerAddUnion    ( const UnionDecl           * node  ) { indexer_impl_addUnion    ( pass, 0, node ); }
    417         void indexerAddUnionFwd ( const UnionDecl           * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
    418         void indexerAddTrait    ( const TraitDecl           * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
    419         void indexerAddWith     ( const std::list< Expression * > & exprs, const Declaration * withStmt ) { indexer_impl_addWith( pass, 0, exprs, withStmt ); }
     312        void indexerAddUnion    ( UnionDecl                 * node  ) { indexer_impl_addUnion    ( pass, 0, node ); }
     313        void indexerAddUnionFwd ( UnionDecl                 * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
     314        void indexerAddTrait    ( TraitDecl                 * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
     315        void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith( pass, 0, exprs, withStmt ); }
    420316
    421317
    422318        template< typename TreeType, typename VisitorType >
    423         friend inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor );
     319        friend inline void indexerScopedAccept( TreeType * tree, VisitorType &visitor );
    424320
    425321        template< typename TreeType, typename VisitorType >
    426         friend inline void indexerScopedAccept( const TreeType * tree, VisitorType & visitor );
    427 
    428         template< typename TreeType, typename VisitorType >
    429         friend inline void indexerScopedMutate( TreeType *& tree, VisitorType & visitor );
     322        friend inline void indexerScopedMutate( TreeType *& tree, VisitorType &visitor );
    430323};
    431324
     
    444337public:
    445338        TypeSubstitution * env = nullptr;
    446 };
    447 
    448 class WithConstTypeSubstitution {
    449 protected:
    450         WithConstTypeSubstitution() = default;
    451         ~WithConstTypeSubstitution() = default;
    452 
    453 public:
    454         const TypeSubstitution * env = nullptr;
    455339};
    456340
     
    534418};
    535419
    536 #include "Common/Stats.h"
    537 
    538 extern struct PassVisitorStats {
    539         size_t depth = 0;
    540         Stats::Counters::MaxCounter<double> * max = nullptr;
    541         Stats::Counters::AverageCounter<double> * avg = nullptr;
    542 } pass_visitor_stats;
    543 
    544420#include "SynTree/TypeSubstitution.h"
    545421#include "PassVisitor.impl.h"
  • src/Common/PassVisitor.impl.h

    rb067d9b r7951100  
    2020
    2121#define MUTATE_END( type, node )                \
    22         auto __return = call_postmutate< type * >( node ); \
    23         assert( __return ); \
    24         return __return;
     22        return call_postmutate< type * >( node ); \
     23
     24
     25#define VISIT_BODY( node )          \
     26        VISIT_START( node );          \
     27        if( children_guard ) {        \
     28                Visitor::visit( node ); \
     29        }                             \
     30        VISIT_END( node );            \
     31
     32
     33#define MUTATE_BODY( type, node )    \
     34        MUTATE_START( node );          \
     35        if( children_guard ) {         \
     36                Mutator::mutate( node ); \
     37        }                              \
     38        MUTATE_END( type, node );      \
     39
    2540
    2641
     
    5267        SemanticErrorException errors;
    5368
    54         pass_visitor_stats.depth++;
    55         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    56         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    5769        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
    58 
    59 
    6070                // splice in new declarations after previous decl
    6171                if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
     
    7383                if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
    7484        }
    75         pass_visitor_stats.depth--;
    76         if ( ! errors.isEmpty() ) {
    77                 throw errors;
    78         }
    79 }
    80 
    81 template< typename pass_type >
    82 inline void acceptAll( const std::list< const Declaration * > & decls, PassVisitor< pass_type >& visitor ) {
    83         SemanticErrorException errors;
    84 
    85         pass_visitor_stats.depth++;
    86         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    87         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    88         for ( const Declaration * decl : decls ) {
    89                 try {
    90                         // run visitor on declaration
    91                         maybeAccept_impl( decl, visitor );
    92                 }
    93                 catch( SemanticErrorException &e ) {
    94                         errors.append( e );
    95                 }
    96         }
    97         pass_visitor_stats.depth--;
    9885        if ( ! errors.isEmpty() ) {
    9986                throw errors;
     
    10794        SemanticErrorException errors;
    10895
    109         pass_visitor_stats.depth++;
    110         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    111         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    11296        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
    11397                // splice in new declarations after previous decl
     
    125109                if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
    126110        }
    127         pass_visitor_stats.depth--;
    128111        if ( ! errors.isEmpty() ) {
    129112                throw errors;
     
    139122}
    140123
    141 template< typename TreeType, typename pass_type >
    142 inline void maybeAccept_impl( const TreeType * tree, PassVisitor< pass_type > & visitor ) {
    143         if ( ! visitor.get_visit_children() ) return;
    144         if ( tree ) {
    145                 tree->accept( visitor );
    146         }
    147 }
    148 
    149124template< typename Container, typename pass_type >
    150125inline void maybeAccept_impl( Container & container, PassVisitor< pass_type > & visitor ) {
    151126        if ( ! visitor.get_visit_children() ) return;
    152127        SemanticErrorException errors;
    153 
    154         pass_visitor_stats.depth++;
    155         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    156         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    157128        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    158129                try {
     
    164135                }
    165136        }
    166         pass_visitor_stats.depth--;
    167         if ( ! errors.isEmpty() ) {
    168                 throw errors;
    169         }
    170 }
    171 
    172 template< typename Container, typename pass_type >
    173 inline void maybeAccept_impl( const Container & container, PassVisitor< pass_type > & visitor ) {
    174         if ( ! visitor.get_visit_children() ) return;
    175         SemanticErrorException errors;
    176 
    177         pass_visitor_stats.depth++;
    178         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    179         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    180         for ( const auto & i : container ) {
    181                 try {
    182                         if ( i ) {
    183                                 i->accept( visitor );
    184                         }
    185                 } catch( SemanticErrorException &e ) {
    186                         errors.append( e );
    187                 }
    188         }
    189         pass_visitor_stats.depth--;
    190137        if ( ! errors.isEmpty() ) {
    191138                throw errors;
     
    204151template< typename Container, typename pass_type >
    205152inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
    206 
    207153        if ( ! mutator.get_visit_children() ) return;
    208154        SemanticErrorException errors;
    209 
    210         pass_visitor_stats.depth++;
    211         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    212         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    213155        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    214156                try {
     
    221163                } // try
    222164        } // for
    223         pass_visitor_stats.depth--;
    224165        if ( ! errors.isEmpty() ) {
    225166                throw errors;
     
    244185        DeclList_t* afterDecls  = get_afterDecls();
    245186
    246         pass_visitor_stats.depth++;
    247         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    248         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    249187        for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
    250188
     
    254192                try {
    255193                        func( *i );
    256                         assert( *i );
    257194                        assert(( empty( beforeStmts ) && empty( afterStmts ))
    258195                            || ( empty( beforeDecls ) && empty( afterDecls )) );
     
    265202                if ( !empty( beforeStmts ) ) { statements.splice( i, *beforeStmts ); }
    266203        }
    267         pass_visitor_stats.depth--;
    268204
    269205        if ( !empty( afterDecls ) ) { splice( std::back_inserter( statements ), afterDecls); }
     
    280216
    281217template< typename pass_type >
    282 void PassVisitor< pass_type >::visitStatementList( const std::list< Statement * > & statements ) {
    283         if ( ! get_visit_children() ) return;
    284         SemanticErrorException errors;
    285 
    286         pass_visitor_stats.depth++;
    287         pass_visitor_stats.max->push(pass_visitor_stats.depth);
    288         pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    289         for ( const Statement * i : statements ) {
    290                 try {
    291                         maybeAccept_impl( i, *this );
    292                 } catch ( SemanticErrorException &e ) {
    293                         errors.append( e );
    294                 }
    295         }
    296         pass_visitor_stats.depth--;
    297         if ( !errors.isEmpty() ) { throw errors; }
    298 }
    299 
    300 template< typename pass_type >
    301218void PassVisitor< pass_type >::mutateStatementList( std::list< Statement * > & statements ) {
    302219        handleStatementList( statements, [this]( Statement *& stmt) {
     
    312229
    313230        // don't want statements from outer CompoundStmts to be added to this CompoundStmt
    314         ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
     231        ValueGuardPtr< TypeSubstitution * >  oldEnv        ( get_env_ptr    () );
    315232        ValueGuardPtr< DeclList_t >          oldBeforeDecls( get_beforeDecls() );
    316233        ValueGuardPtr< DeclList_t >          oldAfterDecls ( get_afterDecls () );
     
    347264
    348265template< typename pass_type >
    349 void PassVisitor< pass_type >::visitStatement( const Statement * stmt ) {
    350         if ( ! get_visit_children() ) return;
    351 
    352         // don't want statements from outer CompoundStmts to be added to this CompoundStmt
    353         ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    354 
    355         maybeAccept_impl( stmt, *this );
    356 }
    357 
    358 template< typename pass_type >
    359266Statement * PassVisitor< pass_type >::mutateStatement( Statement * stmt ) {
    360267        return handleStatement( stmt, [this]( Statement * stmt ) {
     
    388295
    389296template< typename pass_type >
    390 void PassVisitor< pass_type >::visitExpression( const Expression * expr ) {
    391         if ( ! get_visit_children() ) return;
    392         if( !expr ) return;
    393 
    394         auto env_ptr = get_env_ptr();
    395         if ( env_ptr && expr->get_env() ) {
    396                 *env_ptr = expr->get_env();
    397         }
    398 
    399         maybeAccept_impl( expr, *this );
    400 }
    401 
    402 template< typename pass_type >
    403297Expression * PassVisitor< pass_type >::mutateExpression( Expression * expr ) {
    404298        return handleExpression(expr, [this]( Expression * expr ) {
     
    410304template< typename TreeType, typename VisitorType >
    411305inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor ) {
    412         if ( ! visitor.get_visit_children() ) return;
    413         auto guard = makeFuncGuard(
    414                 [&visitor]() { visitor.indexerScopeEnter(); },
    415                 [&visitor]() { visitor.indexerScopeLeave(); }
    416         );
    417         maybeAccept_impl( tree, visitor );
    418 }
    419 
    420 template< typename TreeType, typename VisitorType >
    421 inline void indexerScopedAccept( const TreeType * tree, VisitorType & visitor ) {
    422306        if ( ! visitor.get_visit_children() ) return;
    423307        auto guard = makeFuncGuard(
     
    482366
    483367template< typename pass_type >
    484 void PassVisitor< pass_type >::visit( const ObjectDecl * node ) {
    485         VISIT_START( node );
    486 
    487         maybeAccept_impl( node->type         , *this );
    488         maybeAccept_impl( node->init         , *this );
    489         maybeAccept_impl( node->bitfieldWidth, *this );
    490         maybeAccept_impl( node->attributes   , *this );
    491 
    492         VISIT_END( node );
    493 }
    494 
    495 template< typename pass_type >
    496368DeclarationWithType * PassVisitor< pass_type >::mutate( ObjectDecl * node ) {
    497369        MUTATE_START( node );
     
    532404                        indexerAddId( &func );
    533405                        maybeAccept_impl( node->type, *this );
    534                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    535                         // a new scope if inFunction is true
    536                         ValueGuard< bool > oldInFunction( inFunction );
    537                         inFunction = true;
    538                         maybeAccept_impl( node->statements, *this );
    539                         maybeAccept_impl( node->attributes, *this );
    540                 }
    541         }
    542 
    543         VISIT_END( node );
    544 }
    545 
    546 template< typename pass_type >
    547 void PassVisitor< pass_type >::visit( const FunctionDecl * node ) {
    548         VISIT_START( node );
    549 
    550         indexerAddId( node );
    551 
    552         maybeAccept_impl( node->withExprs, *this );
    553         {
    554                 // with clause introduces a level of scope (for the with expression members).
    555                 // with clause exprs are added to the indexer before parameters so that parameters
    556                 // shadow with exprs and not the other way around.
    557                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    558                 indexerAddWith( node->withExprs, node );
    559                 {
    560                         auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    561                         // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    562                         static ObjectDecl func(
    563                                 "__func__", noStorageClasses, LinkageSpec::C, nullptr,
    564                                 new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
    565                                 nullptr
    566                         );
    567                         indexerAddId( &func );
    568                         maybeAccept_impl( node->type, *this );
    569                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    570                         // a new scope if inFunction is true
    571                         ValueGuard< bool > oldInFunction( inFunction );
    572                         inFunction = true;
    573406                        maybeAccept_impl( node->statements, *this );
    574407                        maybeAccept_impl( node->attributes, *this );
     
    601434                        indexerAddId( &func );
    602435                        maybeMutate_impl( node->type, *this );
    603                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    604                         // a new scope if inFunction is true
    605                         ValueGuard< bool > oldInFunction( inFunction );
    606                         inFunction = true;
    607436                        maybeMutate_impl( node->statements, *this );
    608437                        maybeMutate_impl( node->attributes, *this );
     
    636465
    637466template< typename pass_type >
    638 void PassVisitor< pass_type >::visit( const StructDecl * node ) {
    639         VISIT_START( node );
     467Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
     468        MUTATE_START( node );
    640469
    641470        // make up a forward declaration and add it before processing the members
     
    645474        {
    646475                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     476                maybeMutate_impl( node->parameters, *this );
     477                maybeMutate_impl( node->members   , *this );
     478        }
     479
     480        // this addition replaces the forward declaration
     481        indexerAddStruct( node );
     482
     483        MUTATE_END( Declaration, node );
     484}
     485
     486//--------------------------------------------------------------------------
     487// UnionDecl
     488template< typename pass_type >
     489void PassVisitor< pass_type >::visit( UnionDecl * node ) {
     490        VISIT_START( node );
     491
     492        // make up a forward declaration and add it before processing the members
     493        indexerAddUnionFwd( node );
     494
     495        {
     496                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    647497                maybeAccept_impl( node->parameters, *this );
    648498                maybeAccept_impl( node->members   , *this );
    649499        }
    650500
    651         // this addition replaces the forward declaration
    652         indexerAddStruct( node );
    653 
    654         VISIT_END( node );
    655 }
    656 
    657 template< typename pass_type >
    658 Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
     501        indexerAddUnion( node );
     502
     503        VISIT_END( node );
     504}
     505
     506template< typename pass_type >
     507Declaration * PassVisitor< pass_type >::mutate( UnionDecl * node ) {
    659508        MUTATE_START( node );
    660509
    661510        // make up a forward declaration and add it before processing the members
    662         // needs to be on the heap because addStruct saves the pointer
    663         indexerAddStructFwd( node );
     511        indexerAddUnionFwd( node );
    664512
    665513        {
     
    669517        }
    670518
    671         // this addition replaces the forward declaration
    672         indexerAddStruct( node );
    673 
    674         MUTATE_END( Declaration, node );
    675 }
    676 
    677 //--------------------------------------------------------------------------
    678 // UnionDecl
    679 template< typename pass_type >
    680 void PassVisitor< pass_type >::visit( UnionDecl * node ) {
    681         VISIT_START( node );
    682 
    683         // make up a forward declaration and add it before processing the members
    684         indexerAddUnionFwd( node );
    685 
    686         {
    687                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    688                 maybeAccept_impl( node->parameters, *this );
    689                 maybeAccept_impl( node->members   , *this );
    690         }
    691 
    692         indexerAddUnion( node );
    693 
    694         VISIT_END( node );
    695 }
    696 template< typename pass_type >
    697 void PassVisitor< pass_type >::visit( const UnionDecl * node ) {
    698         VISIT_START( node );
    699 
    700         // make up a forward declaration and add it before processing the members
    701         indexerAddUnionFwd( node );
    702 
    703         {
    704                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    705                 maybeAccept_impl( node->parameters, *this );
    706                 maybeAccept_impl( node->members   , *this );
    707         }
    708 
    709         indexerAddUnion( node );
    710 
    711         VISIT_END( node );
    712 }
    713 
    714 template< typename pass_type >
    715 Declaration * PassVisitor< pass_type >::mutate( UnionDecl * node ) {
    716         MUTATE_START( node );
    717 
    718         // make up a forward declaration and add it before processing the members
    719         indexerAddUnionFwd( node );
    720 
    721         {
    722                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    723                 maybeMutate_impl( node->parameters, *this );
    724                 maybeMutate_impl( node->members   , *this );
    725         }
    726 
    727519        indexerAddUnion( node );
    728520
     
    746538
    747539template< typename pass_type >
    748 void PassVisitor< pass_type >::visit( const EnumDecl * node ) {
    749         VISIT_START( node );
    750 
    751         indexerAddEnum( node );
    752 
    753         // unlike structs, traits, and unions, enums inject their members into the global scope
    754         maybeAccept_impl( node->parameters, *this );
    755         maybeAccept_impl( node->members   , *this );
    756 
    757         VISIT_END( node );
    758 }
    759 
    760 template< typename pass_type >
    761540Declaration * PassVisitor< pass_type >::mutate( EnumDecl * node ) {
    762541        MUTATE_START( node );
     
    775554template< typename pass_type >
    776555void PassVisitor< pass_type >::visit( TraitDecl * node ) {
    777         VISIT_START( node );
    778 
    779         {
    780                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    781                 maybeAccept_impl( node->parameters, *this );
    782                 maybeAccept_impl( node->members   , *this );
    783         }
    784 
    785         indexerAddTrait( node );
    786 
    787         VISIT_END( node );
    788 }
    789 
    790 template< typename pass_type >
    791 void PassVisitor< pass_type >::visit( const TraitDecl * node ) {
    792556        VISIT_START( node );
    793557
     
    842606}
    843607
    844 
    845 template< typename pass_type >
    846 void PassVisitor< pass_type >::visit( const TypeDecl * node ) {
    847         VISIT_START( node );
     608template< typename pass_type >
     609Declaration * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
     610        MUTATE_START( node );
    848611
    849612        {
    850613                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    851                 maybeAccept_impl( node->parameters, *this );
    852                 maybeAccept_impl( node->base      , *this );
     614                maybeMutate_impl( node->parameters, *this );
     615                maybeMutate_impl( node->base      , *this );
    853616        }
    854617
     
    858621        indexerAddType( node );
    859622
     623        maybeMutate_impl( node->assertions, *this );
     624
     625        indexerScopedMutate( node->init, *this );
     626
     627        MUTATE_END( Declaration, node );
     628}
     629
     630//--------------------------------------------------------------------------
     631// TypedefDecl
     632template< typename pass_type >
     633void PassVisitor< pass_type >::visit( TypedefDecl * node ) {
     634        VISIT_START( node );
     635
     636        {
     637                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     638                maybeAccept_impl( node->parameters, *this );
     639                maybeAccept_impl( node->base      , *this );
     640        }
     641
     642        indexerAddType( node );
     643
    860644        maybeAccept_impl( node->assertions, *this );
    861645
    862         indexerScopedAccept( node->init, *this );
    863 
    864         VISIT_END( node );
    865 }
    866 
    867 template< typename pass_type >
    868 Declaration * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
     646        VISIT_END( node );
     647}
     648
     649template< typename pass_type >
     650Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
    869651        MUTATE_START( node );
    870652
     
    875657        }
    876658
    877         // see A NOTE ON THE ORDER OF TRAVERSAL, above
    878         // note that assertions come after the type is added to the symtab, since they are not part of the type proper
    879         // and may depend on the type itself
    880659        indexerAddType( node );
    881660
    882661        maybeMutate_impl( node->assertions, *this );
    883662
    884         indexerScopedMutate( node->init, *this );
    885 
    886663        MUTATE_END( Declaration, node );
    887664}
    888665
    889666//--------------------------------------------------------------------------
    890 // TypedefDecl
    891 template< typename pass_type >
    892 void PassVisitor< pass_type >::visit( TypedefDecl * node ) {
    893         VISIT_START( node );
    894 
    895         {
    896                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    897                 maybeAccept_impl( node->parameters, *this );
    898                 maybeAccept_impl( node->base      , *this );
    899         }
    900 
    901         indexerAddType( node );
    902 
    903         maybeAccept_impl( node->assertions, *this );
    904 
    905         VISIT_END( node );
    906 }
    907 
    908 template< typename pass_type >
    909 void PassVisitor< pass_type >::visit( const TypedefDecl * node ) {
    910         VISIT_START( node );
    911 
    912         {
    913                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    914                 maybeAccept_impl( node->parameters, *this );
    915                 maybeAccept_impl( node->base      , *this );
    916         }
    917 
    918         indexerAddType( node );
    919 
    920         maybeAccept_impl( node->assertions, *this );
    921 
    922         VISIT_END( node );
    923 }
    924 
    925 template< typename pass_type >
    926 Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
    927         MUTATE_START( node );
    928 
    929         {
    930                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    931                 maybeMutate_impl( node->parameters, *this );
    932                 maybeMutate_impl( node->base      , *this );
    933         }
    934 
    935         indexerAddType( node );
    936 
    937         maybeMutate_impl( node->assertions, *this );
    938 
    939         MUTATE_END( Declaration, node );
    940 }
    941 
    942 //--------------------------------------------------------------------------
    943667// AsmDecl
    944668template< typename pass_type >
    945669void PassVisitor< pass_type >::visit( AsmDecl * node ) {
    946         VISIT_START( node );
    947 
    948         maybeAccept_impl( node->stmt, *this );
    949 
    950         VISIT_END( node );
    951 }
    952 
    953 template< typename pass_type >
    954 void PassVisitor< pass_type >::visit( const AsmDecl * node ) {
    955670        VISIT_START( node );
    956671
     
    982697
    983698template< typename pass_type >
    984 void PassVisitor< pass_type >::visit( const StaticAssertDecl * node ) {
    985         VISIT_START( node );
    986 
    987         visitExpression( node->condition );
    988         maybeAccept_impl( node->message, *this );
    989 
    990         VISIT_END( node );
    991 }
    992 
    993 template< typename pass_type >
    994699StaticAssertDecl * PassVisitor< pass_type >::mutate( StaticAssertDecl * node ) {
    995700        MUTATE_START( node );
     
    1007712        VISIT_START( node );
    1008713        {
    1009                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    1010                 ValueGuard< bool > oldInFunction( inFunction );
    1011                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
     714                auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1012715                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1013                 inFunction = false;
    1014716                visitStatementList( node->kids );
    1015717        }
     
    1018720
    1019721template< typename pass_type >
    1020 void PassVisitor< pass_type >::visit( const CompoundStmt * node ) {
    1021         VISIT_START( node );
    1022         {
    1023                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    1024                 ValueGuard< bool > oldInFunction( inFunction );
    1025                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
     722CompoundStmt * PassVisitor< pass_type >::mutate( CompoundStmt * node ) {
     723        MUTATE_START( node );
     724        {
     725                auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1026726                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1027                 inFunction = false;
    1028                 visitStatementList( node->kids );
    1029         }
    1030         VISIT_END( node );
    1031 }
    1032 
    1033 template< typename pass_type >
    1034 CompoundStmt * PassVisitor< pass_type >::mutate( CompoundStmt * node ) {
    1035         MUTATE_START( node );
    1036         {
    1037                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    1038                 ValueGuard< bool > oldInFunction( inFunction );
    1039                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
    1040                 auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1041                 inFunction = false;
    1042727                mutateStatementList( node->kids );
    1043728        }
     
    1049734template< typename pass_type >
    1050735void PassVisitor< pass_type >::visit( ExprStmt * node ) {
    1051         VISIT_START( node );
    1052 
    1053         visitExpression( node->expr );
    1054 
    1055         VISIT_END( node );
    1056 }
    1057 
    1058 template< typename pass_type >
    1059 void PassVisitor< pass_type >::visit( const ExprStmt * node ) {
    1060736        VISIT_START( node );
    1061737
     
    1089765
    1090766template< typename pass_type >
    1091 void PassVisitor< pass_type >::visit( const AsmStmt * node ) {
    1092         VISIT_START( node )
    1093 
    1094         maybeAccept_impl( node->instruction, *this );
    1095         maybeAccept_impl( node->output, *this );
    1096         maybeAccept_impl( node->input, *this );
    1097         maybeAccept_impl( node->clobber, *this );
    1098 
    1099         VISIT_END( node );
    1100 }
    1101 
    1102 template< typename pass_type >
    1103767Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
    1104768        MUTATE_START( node );
     
    1122786
    1123787template< typename pass_type >
    1124 void PassVisitor< pass_type >::visit( const DirectiveStmt * node ) {
    1125         VISIT_START( node )
    1126 
    1127         VISIT_END( node );
    1128 }
    1129 
    1130 template< typename pass_type >
    1131788Statement * PassVisitor< pass_type >::mutate( DirectiveStmt * node ) {
    1132789        MUTATE_START( node );
     
    1143800                // if statements introduce a level of scope (for the initialization)
    1144801                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1145                 maybeAccept_impl( node->initialization, *this );
     802                maybeAccept_impl( node->get_initialization(), *this );
    1146803                visitExpression ( node->condition );
    1147804                node->thenPart = visitStatement( node->thenPart );
     
    1152809
    1153810template< typename pass_type >
    1154 void PassVisitor< pass_type >::visit( const IfStmt * node ) {
    1155         VISIT_START( node );
     811Statement * PassVisitor< pass_type >::mutate( IfStmt * node ) {
     812        MUTATE_START( node );
    1156813        {
    1157814                // if statements introduce a level of scope (for the initialization)
    1158815                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1159                 maybeAccept_impl( node->initialization, *this );
    1160                 visitExpression ( node->condition );
    1161                 visitStatement  ( node->thenPart );
    1162                 visitStatement  ( node->elsePart );
    1163         }
    1164         VISIT_END( node );
    1165 }
    1166 
    1167 template< typename pass_type >
    1168 Statement * PassVisitor< pass_type >::mutate( IfStmt * node ) {
    1169         MUTATE_START( node );
    1170         {
    1171                 // if statements introduce a level of scope (for the initialization)
    1172                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1173                 maybeMutate_impl( node->initialization, *this );
     816                maybeMutate_impl( node->get_initialization(), *this );
    1174817                node->condition = mutateExpression( node->condition );
    1175818                node->thenPart  = mutateStatement ( node->thenPart  );
     
    1191834                visitExpression ( node->condition );
    1192835                node->body = visitStatement( node->body );
    1193         }
    1194 
    1195         VISIT_END( node );
    1196 }
    1197 
    1198 template< typename pass_type >
    1199 void PassVisitor< pass_type >::visit( const WhileStmt * node ) {
    1200         VISIT_START( node );
    1201 
    1202         {
    1203                 // while statements introduce a level of scope (for the initialization)
    1204                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1205                 maybeAccept_impl( node->initialization, *this );
    1206                 visitExpression ( node->condition );
    1207                 visitStatement  ( node->body );
    1208836        }
    1209837
     
    1244872
    1245873template< typename pass_type >
    1246 void PassVisitor< pass_type >::visit( const ForStmt * node ) {
    1247         VISIT_START( node );
    1248         {
    1249                 // for statements introduce a level of scope (for the initialization)
    1250                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1251                 maybeAccept_impl( node->initialization, *this );
    1252                 visitExpression( node->condition );
    1253                 visitExpression( node->increment );
    1254                 visitStatement ( node->body );
    1255         }
    1256         VISIT_END( node );
    1257 }
    1258 
    1259 template< typename pass_type >
    1260874Statement * PassVisitor< pass_type >::mutate( ForStmt * node ) {
    1261875        MUTATE_START( node );
     
    1284898
    1285899template< typename pass_type >
    1286 void PassVisitor< pass_type >::visit( const SwitchStmt * node ) {
    1287         VISIT_START( node );
    1288 
    1289         visitExpression   ( node->condition  );
    1290         visitStatementList( node->statements );
    1291 
    1292         VISIT_END( node );
    1293 }
    1294 
    1295 template< typename pass_type >
    1296900Statement * PassVisitor< pass_type >::mutate( SwitchStmt * node ) {
    1297901        MUTATE_START( node );
     
    1316920
    1317921template< typename pass_type >
    1318 void PassVisitor< pass_type >::visit( const CaseStmt * node ) {
    1319         VISIT_START( node );
    1320 
    1321         visitExpression   ( node->condition );
    1322         visitStatementList( node->stmts     );
    1323 
    1324         VISIT_END( node );
    1325 }
    1326 
    1327 template< typename pass_type >
    1328922Statement * PassVisitor< pass_type >::mutate( CaseStmt * node ) {
    1329923        MUTATE_START( node );
     
    1344938
    1345939template< typename pass_type >
    1346 void PassVisitor< pass_type >::visit( const BranchStmt * node ) {
    1347         VISIT_START( node );
    1348         VISIT_END( node );
    1349 }
    1350 
    1351 template< typename pass_type >
    1352940Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
    1353941        MUTATE_START( node );
     
    1367955
    1368956template< typename pass_type >
    1369 void PassVisitor< pass_type >::visit( const ReturnStmt * node ) {
    1370         VISIT_START( node );
    1371 
    1372         visitExpression( node->expr );
    1373 
    1374         VISIT_END( node );
    1375 }
    1376 
    1377 template< typename pass_type >
    1378957Statement * PassVisitor< pass_type >::mutate( ReturnStmt * node ) {
    1379958        MUTATE_START( node );
     
    1386965//--------------------------------------------------------------------------
    1387966// ThrowStmt
     967
    1388968template< typename pass_type >
    1389969void PassVisitor< pass_type >::visit( ThrowStmt * node ) {
     
    1397977
    1398978template< typename pass_type >
    1399 void PassVisitor< pass_type >::visit( const ThrowStmt * node ) {
    1400         VISIT_START( node );
    1401 
    1402         maybeAccept_impl( node->expr, *this );
    1403         maybeAccept_impl( node->target, *this );
    1404 
    1405         VISIT_END( node );
    1406 }
    1407 
    1408 template< typename pass_type >
    1409979Statement * PassVisitor< pass_type >::mutate( ThrowStmt * node ) {
    1410980        MUTATE_START( node );
     
    1420990template< typename pass_type >
    1421991void PassVisitor< pass_type >::visit( TryStmt * node ) {
    1422         VISIT_START( node );
    1423 
    1424         maybeAccept_impl( node->block       , *this );
    1425         maybeAccept_impl( node->handlers    , *this );
    1426         maybeAccept_impl( node->finallyBlock, *this );
    1427 
    1428         VISIT_END( node );
    1429 }
    1430 
    1431 template< typename pass_type >
    1432 void PassVisitor< pass_type >::visit( const TryStmt * node ) {
    1433992        VISIT_START( node );
    1434993
     
    14671026
    14681027template< typename pass_type >
    1469 void PassVisitor< pass_type >::visit( const CatchStmt * node ) {
    1470         VISIT_START( node );
    1471         {
    1472                 // catch statements introduce a level of scope (for the caught exception)
    1473                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1474                 maybeAccept_impl( node->decl, *this );
    1475                 visitExpression ( node->cond );
    1476                 visitStatement  ( node->body );
    1477         }
    1478         VISIT_END( node );
    1479 }
    1480 
    1481 template< typename pass_type >
    14821028Statement * PassVisitor< pass_type >::mutate( CatchStmt * node ) {
    14831029        MUTATE_START( node );
     
    15041050
    15051051template< typename pass_type >
    1506 void PassVisitor< pass_type >::visit( const FinallyStmt * node ) {
    1507         VISIT_START( node );
    1508 
    1509         maybeAccept_impl( node->block, *this );
    1510 
    1511         VISIT_END( node );
    1512 }
    1513 
    1514 template< typename pass_type >
    15151052Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
    15161053        MUTATE_START( node );
     
    15451082
    15461083template< typename pass_type >
    1547 void PassVisitor< pass_type >::visit( const WaitForStmt * node ) {
    1548         VISIT_START( node );
    1549 
    1550         for( auto & clause : node->clauses ) {
    1551                 maybeAccept_impl( clause.target.function, *this );
    1552                 maybeAccept_impl( clause.target.arguments, *this );
    1553 
    1554                 maybeAccept_impl( clause.statement, *this );
    1555                 maybeAccept_impl( clause.condition, *this );
    1556         }
    1557 
    1558         maybeAccept_impl( node->timeout.time, *this );
    1559         maybeAccept_impl( node->timeout.statement, *this );
    1560         maybeAccept_impl( node->timeout.condition, *this );
    1561         maybeAccept_impl( node->orelse.statement, *this );
    1562         maybeAccept_impl( node->orelse.condition, *this );
    1563 
    1564         VISIT_END( node );
    1565 }
    1566 
    1567 template< typename pass_type >
    15681084Statement * PassVisitor< pass_type >::mutate( WaitForStmt * node ) {
    15691085        MUTATE_START( node );
     
    15891105
    15901106//--------------------------------------------------------------------------
    1591 // WithStmt
     1107// NullStmt
    15921108template< typename pass_type >
    15931109void PassVisitor< pass_type >::visit( WithStmt * node ) {
     
    16041120
    16051121template< typename pass_type >
    1606 void PassVisitor< pass_type >::visit( const WithStmt * node ) {
    1607         VISIT_START( node );
    1608         maybeAccept_impl( node->exprs, *this );
    1609         {
    1610                 // catch statements introduce a level of scope (for the caught exception)
    1611                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1612                 indexerAddWith( node->exprs, node );
    1613                 maybeAccept_impl( node->stmt, *this );
    1614         }
    1615         VISIT_END( node );
    1616 }
    1617 
    1618 template< typename pass_type >
    1619 Declaration * PassVisitor< pass_type >::mutate( WithStmt * node ) {
     1122Statement * PassVisitor< pass_type >::mutate( WithStmt * node ) {
    16201123        MUTATE_START( node );
    16211124        maybeMutate_impl( node->exprs, *this );
     
    16261129                maybeMutate_impl( node->stmt, *this );
    16271130        }
    1628         MUTATE_END( Declaration, node );
     1131        MUTATE_END( Statement, node );
    16291132}
    16301133
     
    16381141
    16391142template< typename pass_type >
    1640 void PassVisitor< pass_type >::visit( const NullStmt * node ) {
    1641         VISIT_START( node );
    1642         VISIT_END( node );
    1643 }
    1644 
    1645 template< typename pass_type >
    16461143NullStmt * PassVisitor< pass_type >::mutate( NullStmt * node ) {
    16471144        MUTATE_START( node );
     
    16611158
    16621159template< typename pass_type >
    1663 void PassVisitor< pass_type >::visit( const DeclStmt * node ) {
    1664         VISIT_START( node );
    1665 
    1666         maybeAccept_impl( node->decl, *this );
    1667 
    1668         VISIT_END( node );
    1669 }
    1670 
    1671 template< typename pass_type >
    16721160Statement * PassVisitor< pass_type >::mutate( DeclStmt * node ) {
    16731161        MUTATE_START( node );
     
    16901178
    16911179template< typename pass_type >
    1692 void PassVisitor< pass_type >::visit( const ImplicitCtorDtorStmt * node ) {
    1693         VISIT_START( node );
    1694 
    1695         maybeAccept_impl( node->callStmt, *this );
    1696 
    1697         VISIT_END( node );
    1698 }
    1699 
    1700 template< typename pass_type >
    17011180Statement * PassVisitor< pass_type >::mutate( ImplicitCtorDtorStmt * node ) {
    17021181        MUTATE_START( node );
     
    17141193
    17151194        indexerScopedAccept( node->result  , *this );
    1716         maybeAccept_impl   ( node->function, *this );
    1717         maybeAccept_impl   ( node->args    , *this );
    1718 
    1719         VISIT_END( node );
    1720 }
    1721 
    1722 template< typename pass_type >
    1723 void PassVisitor< pass_type >::visit( const ApplicationExpr * node ) {
    1724         VISIT_START( node );
    1725 
    1726         indexerScopedAccept( node->result  , *this );
    1727         maybeAccept_impl   ( node->function, *this );
    1728         maybeAccept_impl   ( node->args    , *this );
     1195        maybeAccept_impl        ( node->function, *this );
     1196        maybeAccept_impl        ( node->args    , *this );
    17291197
    17301198        VISIT_END( node );
     
    17601228
    17611229template< typename pass_type >
    1762 void PassVisitor< pass_type >::visit( const UntypedExpr * node ) {
    1763         VISIT_START( node );
    1764 
    1765         indexerScopedAccept( node->result, *this );
    1766 
    1767         for ( auto expr : node->args ) {
    1768                 visitExpression( expr );
    1769         }
    1770 
    1771         VISIT_END( node );
    1772 }
    1773 
    1774 template< typename pass_type >
    17751230Expression * PassVisitor< pass_type >::mutate( UntypedExpr * node ) {
    17761231        MUTATE_START( node );
     
    17981253
    17991254template< typename pass_type >
    1800 void PassVisitor< pass_type >::visit( const NameExpr * node ) {
     1255Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
     1256        MUTATE_START( node );
     1257
     1258        indexerScopedMutate( node->env   , *this );
     1259        indexerScopedMutate( node->result, *this );
     1260
     1261        MUTATE_END( Expression, node );
     1262}
     1263
     1264//--------------------------------------------------------------------------
     1265// CastExpr
     1266template< typename pass_type >
     1267void PassVisitor< pass_type >::visit( CastExpr * node ) {
    18011268        VISIT_START( node );
    18021269
    18031270        indexerScopedAccept( node->result, *this );
    1804 
    1805         VISIT_END( node );
    1806 }
    1807 
    1808 template< typename pass_type >
    1809 Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
     1271        maybeAccept_impl        ( node->arg   , *this );
     1272
     1273        VISIT_END( node );
     1274}
     1275
     1276template< typename pass_type >
     1277Expression * PassVisitor< pass_type >::mutate( CastExpr * node ) {
    18101278        MUTATE_START( node );
    18111279
    18121280        indexerScopedMutate( node->env   , *this );
    18131281        indexerScopedMutate( node->result, *this );
    1814 
    1815         MUTATE_END( Expression, node );
    1816 }
    1817 
    1818 //--------------------------------------------------------------------------
    1819 // CastExpr
    1820 template< typename pass_type >
    1821 void PassVisitor< pass_type >::visit( CastExpr * node ) {
     1282        maybeMutate_impl   ( node->arg   , *this );
     1283
     1284        MUTATE_END( Expression, node );
     1285}
     1286
     1287//--------------------------------------------------------------------------
     1288// KeywordCastExpr
     1289template< typename pass_type >
     1290void PassVisitor< pass_type >::visit( KeywordCastExpr * node ) {
     1291        VISIT_START( node );
     1292
     1293        indexerScopedAccept( node->result, *this );
     1294        maybeAccept_impl        ( node->arg   , *this );
     1295
     1296        VISIT_END( node );
     1297}
     1298
     1299template< typename pass_type >
     1300Expression * PassVisitor< pass_type >::mutate( KeywordCastExpr * node ) {
     1301        MUTATE_START( node );
     1302
     1303        indexerScopedMutate( node->env   , *this );
     1304        indexerScopedMutate( node->result, *this );
     1305        maybeMutate_impl   ( node->arg   , *this );
     1306
     1307        MUTATE_END( Expression, node );
     1308}
     1309
     1310//--------------------------------------------------------------------------
     1311// VirtualCastExpr
     1312template< typename pass_type >
     1313void PassVisitor< pass_type >::visit( VirtualCastExpr * node ) {
     1314        VISIT_START( node );
     1315
     1316        indexerScopedAccept( node->result, *this );
     1317        maybeAccept_impl( node->arg, *this );
     1318
     1319        VISIT_END( node );
     1320}
     1321
     1322template< typename pass_type >
     1323Expression * PassVisitor< pass_type >::mutate( VirtualCastExpr * node ) {
     1324        MUTATE_START( node );
     1325
     1326        indexerScopedMutate( node->env   , *this );
     1327        indexerScopedMutate( node->result, *this );
     1328        maybeMutate_impl   ( node->arg   , *this );
     1329
     1330        MUTATE_END( Expression, node );
     1331}
     1332
     1333//--------------------------------------------------------------------------
     1334// AddressExpr
     1335template< typename pass_type >
     1336void PassVisitor< pass_type >::visit( AddressExpr * node ) {
    18221337        VISIT_START( node );
    18231338
     
    18291344
    18301345template< typename pass_type >
    1831 void PassVisitor< pass_type >::visit( const CastExpr * node ) {
     1346Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
     1347        MUTATE_START( node );
     1348
     1349        indexerScopedMutate( node->env   , *this );
     1350        indexerScopedMutate( node->result, *this );
     1351        maybeMutate_impl   ( node->arg   , *this );
     1352
     1353        MUTATE_END( Expression, node );
     1354}
     1355
     1356//--------------------------------------------------------------------------
     1357// LabelAddressExpr
     1358template< typename pass_type >
     1359void PassVisitor< pass_type >::visit( LabelAddressExpr * node ) {
    18321360        VISIT_START( node );
    18331361
    18341362        indexerScopedAccept( node->result, *this );
    1835         maybeAccept_impl   ( node->arg   , *this );
    1836 
    1837         VISIT_END( node );
    1838 }
    1839 
    1840 template< typename pass_type >
    1841 Expression * PassVisitor< pass_type >::mutate( CastExpr * node ) {
     1363
     1364        VISIT_END( node );
     1365}
     1366
     1367template< typename pass_type >
     1368Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
    18421369        MUTATE_START( node );
    18431370
    18441371        indexerScopedMutate( node->env   , *this );
    18451372        indexerScopedMutate( node->result, *this );
    1846         maybeMutate_impl   ( node->arg   , *this );
    1847 
    1848         MUTATE_END( Expression, node );
    1849 }
    1850 
    1851 //--------------------------------------------------------------------------
    1852 // KeywordCastExpr
    1853 template< typename pass_type >
    1854 void PassVisitor< pass_type >::visit( KeywordCastExpr * node ) {
    1855         VISIT_START( node );
    1856 
    1857         indexerScopedAccept( node->result, *this );
    1858         maybeAccept_impl        ( node->arg   , *this );
    1859 
    1860         VISIT_END( node );
    1861 }
    1862 
    1863 template< typename pass_type >
    1864 void PassVisitor< pass_type >::visit( const KeywordCastExpr * node ) {
    1865         VISIT_START( node );
    1866 
    1867         indexerScopedAccept( node->result, *this );
    1868         maybeAccept_impl   ( node->arg   , *this );
    1869 
    1870         VISIT_END( node );
    1871 }
    1872 
    1873 template< typename pass_type >
    1874 Expression * PassVisitor< pass_type >::mutate( KeywordCastExpr * node ) {
    1875         MUTATE_START( node );
    1876 
    1877         indexerScopedMutate( node->env   , *this );
    1878         indexerScopedMutate( node->result, *this );
    1879         maybeMutate_impl   ( node->arg   , *this );
    1880 
    1881         MUTATE_END( Expression, node );
    1882 }
    1883 
    1884 //--------------------------------------------------------------------------
    1885 // VirtualCastExpr
    1886 template< typename pass_type >
    1887 void PassVisitor< pass_type >::visit( VirtualCastExpr * node ) {
    1888         VISIT_START( node );
    1889 
    1890         indexerScopedAccept( node->result, *this );
    1891         maybeAccept_impl   ( node->arg, *this );
    1892 
    1893         VISIT_END( node );
    1894 }
    1895 
    1896 template< typename pass_type >
    1897 void PassVisitor< pass_type >::visit( const VirtualCastExpr * node ) {
    1898         VISIT_START( node );
    1899 
    1900         indexerScopedAccept( node->result, *this );
    1901         maybeAccept_impl   ( node->arg, *this );
    1902 
    1903         VISIT_END( node );
    1904 }
    1905 
    1906 template< typename pass_type >
    1907 Expression * PassVisitor< pass_type >::mutate( VirtualCastExpr * node ) {
    1908         MUTATE_START( node );
    1909 
    1910         indexerScopedMutate( node->env   , *this );
    1911         indexerScopedMutate( node->result, *this );
    1912         maybeMutate_impl   ( node->arg   , *this );
    1913 
    1914         MUTATE_END( Expression, node );
    1915 }
    1916 
    1917 //--------------------------------------------------------------------------
    1918 // AddressExpr
    1919 template< typename pass_type >
    1920 void PassVisitor< pass_type >::visit( AddressExpr * node ) {
    1921         VISIT_START( node );
    1922 
    1923         indexerScopedAccept( node->result, *this );
    1924         maybeAccept_impl   ( node->arg   , *this );
    1925 
    1926         VISIT_END( node );
    1927 }
    1928 
    1929 template< typename pass_type >
    1930 void PassVisitor< pass_type >::visit( const AddressExpr * node ) {
    1931         VISIT_START( node );
    1932 
    1933         indexerScopedAccept( node->result, *this );
    1934         maybeAccept_impl   ( node->arg   , *this );
    1935 
    1936         VISIT_END( node );
    1937 }
    1938 
    1939 template< typename pass_type >
    1940 Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
    1941         MUTATE_START( node );
    1942 
    1943         indexerScopedMutate( node->env   , *this );
    1944         indexerScopedMutate( node->result, *this );
    1945         maybeMutate_impl   ( node->arg   , *this );
    1946 
    1947         MUTATE_END( Expression, node );
    1948 }
    1949 
    1950 //--------------------------------------------------------------------------
    1951 // LabelAddressExpr
    1952 template< typename pass_type >
    1953 void PassVisitor< pass_type >::visit( LabelAddressExpr * node ) {
    1954         VISIT_START( node );
    1955 
    1956         indexerScopedAccept( node->result, *this );
    1957 
    1958         VISIT_END( node );
    1959 }
    1960 
    1961 template< typename pass_type >
    1962 void PassVisitor< pass_type >::visit( const LabelAddressExpr * node ) {
    1963         VISIT_START( node );
    1964 
    1965         indexerScopedAccept( node->result, *this );
    1966 
    1967         VISIT_END( node );
    1968 }
    1969 
    1970 template< typename pass_type >
    1971 Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
    1972         MUTATE_START( node );
    1973 
    1974         indexerScopedMutate( node->env   , *this );
    1975         indexerScopedMutate( node->result, *this );
    19761373
    19771374        MUTATE_END( Expression, node );
     
    19821379template< typename pass_type >
    19831380void PassVisitor< pass_type >::visit( UntypedMemberExpr * node ) {
    1984         VISIT_START( node );
    1985 
    1986         indexerScopedAccept( node->result   , *this );
    1987         maybeAccept_impl   ( node->aggregate, *this );
    1988         maybeAccept_impl   ( node->member   , *this );
    1989 
    1990         VISIT_END( node );
    1991 }
    1992 
    1993 template< typename pass_type >
    1994 void PassVisitor< pass_type >::visit( const UntypedMemberExpr * node ) {
    19951381        VISIT_START( node );
    19961382
     
    20271413
    20281414template< typename pass_type >
    2029 void PassVisitor< pass_type >::visit( const MemberExpr * node ) {
    2030         VISIT_START( node );
    2031 
    2032         indexerScopedAccept( node->result   , *this );
    2033         maybeAccept_impl   ( node->aggregate, *this );
    2034 
    2035         VISIT_END( node );
    2036 }
    2037 
    2038 template< typename pass_type >
    20391415Expression * PassVisitor< pass_type >::mutate( MemberExpr * node ) {
    20401416        MUTATE_START( node );
     
    20591435
    20601436template< typename pass_type >
    2061 void PassVisitor< pass_type >::visit( const VariableExpr * node ) {
    2062         VISIT_START( node );
    2063 
    2064         indexerScopedAccept( node->result, *this );
    2065 
    2066         VISIT_END( node );
    2067 }
    2068 
    2069 template< typename pass_type >
    20701437Expression * PassVisitor< pass_type >::mutate( VariableExpr * node ) {
    20711438        MUTATE_START( node );
     
    20811448template< typename pass_type >
    20821449void PassVisitor< pass_type >::visit( ConstantExpr * node ) {
    2083         VISIT_START( node );
    2084 
    2085         indexerScopedAccept( node->result   , *this );
    2086         maybeAccept_impl   ( &node->constant, *this );
    2087 
    2088         VISIT_END( node );
    2089 }
    2090 
    2091 template< typename pass_type >
    2092 void PassVisitor< pass_type >::visit( const ConstantExpr * node ) {
    20931450        VISIT_START( node );
    20941451
     
    21291486
    21301487template< typename pass_type >
    2131 void PassVisitor< pass_type >::visit( const SizeofExpr * node ) {
     1488Expression * PassVisitor< pass_type >::mutate( SizeofExpr * node ) {
     1489        MUTATE_START( node );
     1490
     1491        indexerScopedMutate( node->env   , *this );
     1492        indexerScopedMutate( node->result, *this );
     1493        if ( node->get_isType() ) {
     1494                maybeMutate_impl( node->type, *this );
     1495        } else {
     1496                maybeMutate_impl( node->expr, *this );
     1497        }
     1498
     1499        MUTATE_END( Expression, node );
     1500}
     1501
     1502//--------------------------------------------------------------------------
     1503// AlignofExpr
     1504template< typename pass_type >
     1505void PassVisitor< pass_type >::visit( AlignofExpr * node ) {
    21321506        VISIT_START( node );
    21331507
     
    21431517
    21441518template< typename pass_type >
    2145 Expression * PassVisitor< pass_type >::mutate( SizeofExpr * node ) {
     1519Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
    21461520        MUTATE_START( node );
    21471521
     
    21581532
    21591533//--------------------------------------------------------------------------
    2160 // AlignofExpr
    2161 template< typename pass_type >
    2162 void PassVisitor< pass_type >::visit( AlignofExpr * node ) {
     1534// UntypedOffsetofExpr
     1535template< typename pass_type >
     1536void PassVisitor< pass_type >::visit( UntypedOffsetofExpr * node ) {
     1537        VISIT_START( node );
     1538
     1539        indexerScopedAccept( node->result, *this );
     1540        maybeAccept_impl   ( node->type  , *this );
     1541
     1542        VISIT_END( node );
     1543}
     1544
     1545template< typename pass_type >
     1546Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
     1547        MUTATE_START( node );
     1548
     1549        indexerScopedMutate( node->env   , *this );
     1550        indexerScopedMutate( node->result, *this );
     1551        maybeMutate_impl   ( node->type  , *this );
     1552
     1553        MUTATE_END( Expression, node );
     1554}
     1555
     1556//--------------------------------------------------------------------------
     1557// OffsetofExpr
     1558template< typename pass_type >
     1559void PassVisitor< pass_type >::visit( OffsetofExpr * node ) {
     1560        VISIT_START( node );
     1561
     1562        indexerScopedAccept( node->result, *this );
     1563        maybeAccept_impl   ( node->type  , *this );
     1564
     1565        VISIT_END( node );
     1566}
     1567
     1568template< typename pass_type >
     1569Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
     1570        MUTATE_START( node );
     1571
     1572        indexerScopedMutate( node->env   , *this );
     1573        indexerScopedMutate( node->result, *this );
     1574        maybeMutate_impl   ( node->type  , *this );
     1575
     1576        MUTATE_END( Expression, node );
     1577}
     1578
     1579//--------------------------------------------------------------------------
     1580// OffsetPackExpr
     1581template< typename pass_type >
     1582void PassVisitor< pass_type >::visit( OffsetPackExpr * node ) {
     1583        VISIT_START( node );
     1584
     1585        indexerScopedAccept( node->result, *this );
     1586        maybeAccept_impl   ( node->type  , *this );
     1587
     1588        VISIT_END( node );
     1589}
     1590
     1591template< typename pass_type >
     1592Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
     1593        MUTATE_START( node );
     1594
     1595        indexerScopedMutate( node->env   , *this );
     1596        indexerScopedMutate( node->result, *this );
     1597        maybeMutate_impl   ( node->type  , *this );
     1598
     1599        MUTATE_END( Expression, node );
     1600}
     1601
     1602//--------------------------------------------------------------------------
     1603// AttrExpr
     1604template< typename pass_type >
     1605void PassVisitor< pass_type >::visit( AttrExpr * node ) {
    21631606        VISIT_START( node );
    21641607
     
    21741617
    21751618template< typename pass_type >
    2176 void PassVisitor< pass_type >::visit( const AlignofExpr * node ) {
    2177         VISIT_START( node );
    2178 
    2179         indexerScopedAccept( node->result, *this );
    2180         if ( node->get_isType() ) {
    2181                 maybeAccept_impl( node->type, *this );
    2182         } else {
    2183                 maybeAccept_impl( node->expr, *this );
    2184         }
    2185 
    2186         VISIT_END( node );
    2187 }
    2188 
    2189 template< typename pass_type >
    2190 Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
     1619Expression * PassVisitor< pass_type >::mutate( AttrExpr * node ) {
    21911620        MUTATE_START( node );
    21921621
     
    22031632
    22041633//--------------------------------------------------------------------------
    2205 // UntypedOffsetofExpr
    2206 template< typename pass_type >
    2207 void PassVisitor< pass_type >::visit( UntypedOffsetofExpr * node ) {
    2208         VISIT_START( node );
    2209 
    2210         indexerScopedAccept( node->result, *this );
    2211         maybeAccept_impl   ( node->type  , *this );
    2212 
    2213         VISIT_END( node );
    2214 }
    2215 
    2216 template< typename pass_type >
    2217 void PassVisitor< pass_type >::visit( const UntypedOffsetofExpr * node ) {
    2218         VISIT_START( node );
    2219 
    2220         indexerScopedAccept( node->result, *this );
    2221         maybeAccept_impl   ( node->type  , *this );
    2222 
    2223         VISIT_END( node );
    2224 }
    2225 
    2226 template< typename pass_type >
    2227 Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
    2228         MUTATE_START( node );
    2229 
    2230         indexerScopedMutate( node->env   , *this );
    2231         indexerScopedMutate( node->result, *this );
    2232         maybeMutate_impl   ( node->type  , *this );
    2233 
    2234         MUTATE_END( Expression, node );
    2235 }
    2236 
    2237 //--------------------------------------------------------------------------
    2238 // OffsetofExpr
    2239 template< typename pass_type >
    2240 void PassVisitor< pass_type >::visit( OffsetofExpr * node ) {
    2241         VISIT_START( node );
    2242 
    2243         indexerScopedAccept( node->result, *this );
    2244         maybeAccept_impl   ( node->type  , *this );
    2245 
    2246         VISIT_END( node );
    2247 }
    2248 
    2249 template< typename pass_type >
    2250 void PassVisitor< pass_type >::visit( const OffsetofExpr * node ) {
    2251         VISIT_START( node );
    2252 
    2253         indexerScopedAccept( node->result, *this );
    2254         maybeAccept_impl   ( node->type  , *this );
    2255 
    2256         VISIT_END( node );
    2257 }
    2258 
    2259 template< typename pass_type >
    2260 Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
    2261         MUTATE_START( node );
    2262 
    2263         indexerScopedMutate( node->env   , *this );
    2264         indexerScopedMutate( node->result, *this );
    2265         maybeMutate_impl   ( node->type  , *this );
    2266 
    2267         MUTATE_END( Expression, node );
    2268 }
    2269 
    2270 //--------------------------------------------------------------------------
    2271 // OffsetPackExpr
    2272 template< typename pass_type >
    2273 void PassVisitor< pass_type >::visit( OffsetPackExpr * node ) {
    2274         VISIT_START( node );
    2275 
    2276         indexerScopedAccept( node->result, *this );
    2277         maybeAccept_impl   ( node->type  , *this );
    2278 
    2279         VISIT_END( node );
    2280 }
    2281 
    2282 template< typename pass_type >
    2283 void PassVisitor< pass_type >::visit( const OffsetPackExpr * node ) {
    2284         VISIT_START( node );
    2285 
    2286         indexerScopedAccept( node->result, *this );
    2287         maybeAccept_impl   ( node->type  , *this );
    2288 
    2289         VISIT_END( node );
    2290 }
    2291 
    2292 template< typename pass_type >
    2293 Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
    2294         MUTATE_START( node );
    2295 
    2296         indexerScopedMutate( node->env   , *this );
    2297         indexerScopedMutate( node->result, *this );
    2298         maybeMutate_impl   ( node->type  , *this );
    2299 
    2300         MUTATE_END( Expression, node );
    2301 }
    2302 
    2303 //--------------------------------------------------------------------------
    23041634// LogicalExpr
    23051635template< typename pass_type >
    23061636void PassVisitor< pass_type >::visit( LogicalExpr * node ) {
    2307         VISIT_START( node );
    2308 
    2309         indexerScopedAccept( node->result, *this );
    2310         maybeAccept_impl   ( node->arg1  , *this );
    2311         maybeAccept_impl   ( node->arg2  , *this );
    2312 
    2313         VISIT_END( node );
    2314 }
    2315 
    2316 template< typename pass_type >
    2317 void PassVisitor< pass_type >::visit( const LogicalExpr * node ) {
    23181637        VISIT_START( node );
    23191638
     
    23521671
    23531672template< typename pass_type >
    2354 void PassVisitor< pass_type >::visit( const ConditionalExpr * node ) {
     1673Expression * PassVisitor< pass_type >::mutate( ConditionalExpr * node ) {
     1674        MUTATE_START( node );
     1675
     1676        indexerScopedMutate( node->env   , *this );
     1677        indexerScopedMutate( node->result, *this );
     1678        maybeMutate_impl   ( node->arg1  , *this );
     1679        maybeMutate_impl   ( node->arg2  , *this );
     1680        maybeMutate_impl   ( node->arg3  , *this );
     1681
     1682        MUTATE_END( Expression, node );
     1683}
     1684
     1685//--------------------------------------------------------------------------
     1686// CommaExpr
     1687template< typename pass_type >
     1688void PassVisitor< pass_type >::visit( CommaExpr * node ) {
    23551689        VISIT_START( node );
    23561690
     
    23581692        maybeAccept_impl   ( node->arg1  , *this );
    23591693        maybeAccept_impl   ( node->arg2  , *this );
    2360         maybeAccept_impl   ( node->arg3  , *this );
    2361 
    2362         VISIT_END( node );
    2363 }
    2364 
    2365 template< typename pass_type >
    2366 Expression * PassVisitor< pass_type >::mutate( ConditionalExpr * node ) {
     1694
     1695        VISIT_END( node );
     1696}
     1697
     1698template< typename pass_type >
     1699Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
    23671700        MUTATE_START( node );
    23681701
     
    23711704        maybeMutate_impl   ( node->arg1  , *this );
    23721705        maybeMutate_impl   ( node->arg2  , *this );
    2373         maybeMutate_impl   ( node->arg3  , *this );
    2374 
    2375         MUTATE_END( Expression, node );
    2376 }
    2377 
    2378 //--------------------------------------------------------------------------
    2379 // CommaExpr
    2380 template< typename pass_type >
    2381 void PassVisitor< pass_type >::visit( CommaExpr * node ) {
    2382         VISIT_START( node );
    2383 
    2384         indexerScopedAccept( node->result, *this );
    2385         maybeAccept_impl   ( node->arg1  , *this );
    2386         maybeAccept_impl   ( node->arg2  , *this );
    2387 
    2388         VISIT_END( node );
    2389 }
    2390 
    2391 template< typename pass_type >
    2392 void PassVisitor< pass_type >::visit( const CommaExpr * node ) {
    2393         VISIT_START( node );
    2394 
    2395         indexerScopedAccept( node->result, *this );
    2396         maybeAccept_impl   ( node->arg1  , *this );
    2397         maybeAccept_impl   ( node->arg2  , *this );
    2398 
    2399         VISIT_END( node );
    2400 }
    2401 
    2402 template< typename pass_type >
    2403 Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
    2404         MUTATE_START( node );
    2405 
    2406         indexerScopedMutate( node->env   , *this );
    2407         indexerScopedMutate( node->result, *this );
    2408         maybeMutate_impl   ( node->arg1  , *this );
    2409         maybeMutate_impl   ( node->arg2  , *this );
    24101706
    24111707        MUTATE_END( Expression, node );
     
    24251721
    24261722template< typename pass_type >
    2427 void PassVisitor< pass_type >::visit( const TypeExpr * node ) {
    2428         VISIT_START( node );
    2429 
    2430         indexerScopedAccept( node->result, *this );
    2431         maybeAccept_impl   ( node->type, *this );
    2432 
    2433         VISIT_END( node );
    2434 }
    2435 
    2436 template< typename pass_type >
    24371723Expression * PassVisitor< pass_type >::mutate( TypeExpr * node ) {
    24381724        MUTATE_START( node );
     
    24491735template< typename pass_type >
    24501736void PassVisitor< pass_type >::visit( AsmExpr * node ) {
    2451         VISIT_START( node );
    2452 
    2453         indexerScopedAccept( node->result    , *this );
    2454         maybeAccept_impl   ( node->inout     , *this );
    2455         maybeAccept_impl   ( node->constraint, *this );
    2456         maybeAccept_impl   ( node->operand   , *this );
    2457 
    2458         VISIT_END( node );
    2459 }
    2460 
    2461 template< typename pass_type >
    2462 void PassVisitor< pass_type >::visit( const AsmExpr * node ) {
    24631737        VISIT_START( node );
    24641738
     
    24901764        VISIT_START( node );
    24911765
    2492         indexerScopedAccept( node->result    , *this );
    2493         maybeAccept_impl   ( node->callExpr  , *this );
    2494 
    2495         VISIT_END( node );
    2496 }
    2497 
    2498 template< typename pass_type >
    2499 void PassVisitor< pass_type >::visit( const ImplicitCopyCtorExpr * node ) {
    2500         VISIT_START( node );
    2501 
    2502         indexerScopedAccept( node->result    , *this );
    2503         maybeAccept_impl   ( node->callExpr  , *this );
     1766        indexerScopedAccept( node->result     , *this );
     1767        maybeAccept_impl   ( node->callExpr   , *this );
     1768        maybeAccept_impl   ( node->tempDecls  , *this );
     1769        maybeAccept_impl   ( node->returnDecls, *this );
     1770        maybeAccept_impl   ( node->dtors      , *this );
    25041771
    25051772        VISIT_END( node );
     
    25101777        MUTATE_START( node );
    25111778
    2512         indexerScopedMutate( node->env       , *this );
    2513         indexerScopedMutate( node->result    , *this );
    2514         maybeMutate_impl   ( node->callExpr  , *this );
     1779        indexerScopedMutate( node->env        , *this );
     1780        indexerScopedMutate( node->result     , *this );
     1781        maybeMutate_impl   ( node->callExpr   , *this );
     1782        maybeMutate_impl   ( node->tempDecls  , *this );
     1783        maybeMutate_impl   ( node->returnDecls, *this );
     1784        maybeMutate_impl   ( node->dtors      , *this );
    25151785
    25161786        MUTATE_END( Expression, node );
     
    25211791template< typename pass_type >
    25221792void PassVisitor< pass_type >::visit( ConstructorExpr * node ) {
    2523         VISIT_START( node );
    2524 
    2525         indexerScopedAccept( node->result  , *this );
    2526         maybeAccept_impl   ( node->callExpr, *this );
    2527 
    2528         VISIT_END( node );
    2529 }
    2530 
    2531 template< typename pass_type >
    2532 void PassVisitor< pass_type >::visit( const ConstructorExpr * node ) {
    25331793        VISIT_START( node );
    25341794
     
    25631823
    25641824template< typename pass_type >
    2565 void PassVisitor< pass_type >::visit( const CompoundLiteralExpr * node ) {
    2566         VISIT_START( node );
    2567 
    2568         indexerScopedAccept( node->result     , *this );
    2569         maybeAccept_impl   ( node->initializer, *this );
    2570 
    2571         VISIT_END( node );
    2572 }
    2573 
    2574 template< typename pass_type >
    25751825Expression * PassVisitor< pass_type >::mutate( CompoundLiteralExpr * node ) {
    25761826        MUTATE_START( node );
     
    25971847
    25981848template< typename pass_type >
    2599 void PassVisitor< pass_type >::visit( const RangeExpr * node ) {
    2600         VISIT_START( node );
    2601 
    2602         indexerScopedAccept( node->result, *this );
    2603         maybeAccept_impl   ( node->low   , *this );
    2604         maybeAccept_impl   ( node->high  , *this );
    2605 
    2606         VISIT_END( node );
    2607 }
    2608 
    2609 template< typename pass_type >
    26101849Expression * PassVisitor< pass_type >::mutate( RangeExpr * node ) {
    26111850        MUTATE_START( node );
     
    26321871
    26331872template< typename pass_type >
    2634 void PassVisitor< pass_type >::visit( const UntypedTupleExpr * node ) {
     1873Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
     1874        MUTATE_START( node );
     1875
     1876        indexerScopedMutate( node->env   , *this );
     1877        indexerScopedMutate( node->result, *this );
     1878        maybeMutate_impl   ( node->exprs , *this );
     1879
     1880        MUTATE_END( Expression, node );
     1881}
     1882
     1883//--------------------------------------------------------------------------
     1884// TupleExpr
     1885template< typename pass_type >
     1886void PassVisitor< pass_type >::visit( TupleExpr * node ) {
    26351887        VISIT_START( node );
    26361888
     
    26421894
    26431895template< typename pass_type >
    2644 Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
    2645         MUTATE_START( node );
    2646 
    2647         indexerScopedMutate( node->env   , *this );
    2648         indexerScopedMutate( node->result, *this );
    2649         maybeMutate_impl   ( node->exprs , *this );
    2650 
    2651         MUTATE_END( Expression, node );
    2652 }
    2653 
    2654 //--------------------------------------------------------------------------
    2655 // TupleExpr
    2656 template< typename pass_type >
    2657 void PassVisitor< pass_type >::visit( TupleExpr * node ) {
    2658         VISIT_START( node );
    2659 
    2660         indexerScopedAccept( node->result, *this );
    2661         maybeAccept_impl   ( node->exprs , *this );
    2662 
    2663         VISIT_END( node );
    2664 }
    2665 
    2666 template< typename pass_type >
    2667 void PassVisitor< pass_type >::visit( const TupleExpr * node ) {
    2668         VISIT_START( node );
    2669 
    2670         indexerScopedAccept( node->result, *this );
    2671         maybeAccept_impl   ( node->exprs , *this );
    2672 
    2673         VISIT_END( node );
    2674 }
    2675 
    2676 template< typename pass_type >
    26771896Expression * PassVisitor< pass_type >::mutate( TupleExpr * node ) {
    26781897        MUTATE_START( node );
     
    26981917
    26991918template< typename pass_type >
    2700 void PassVisitor< pass_type >::visit( const TupleIndexExpr * node ) {
    2701         VISIT_START( node );
    2702 
    2703         indexerScopedAccept( node->result, *this );
    2704         maybeAccept_impl   ( node->tuple , *this );
    2705 
    2706         VISIT_END( node );
    2707 }
    2708 
    2709 template< typename pass_type >
    27101919Expression * PassVisitor< pass_type >::mutate( TupleIndexExpr * node ) {
    27111920        MUTATE_START( node );
     
    27261935        indexerScopedAccept( node->result  , *this );
    27271936        maybeAccept_impl   ( node->stmtExpr, *this );
    2728 
    2729         VISIT_END( node );
    2730 }
    2731 
    2732 template< typename pass_type >
    2733 void PassVisitor< pass_type >::visit( const TupleAssignExpr * node ) {
    2734         VISIT_START( node );
    2735 
    2736         indexerScopedAccept( node->result  , *this );
    2737         maybeAccept_impl( node->stmtExpr, *this );
    27381937
    27391938        VISIT_END( node );
     
    27581957
    27591958        // don't want statements from outer CompoundStmts to be added to this StmtExpr
    2760         ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
     1959        ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
    27611960        ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
    27621961        ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
     
    27711970
    27721971template< typename pass_type >
    2773 void PassVisitor< pass_type >::visit( const StmtExpr * node ) {
    2774         VISIT_START( node );
     1972Expression * PassVisitor< pass_type >::mutate( StmtExpr * node ) {
     1973        MUTATE_START( node );
    27751974
    27761975        // don't want statements from outer CompoundStmts to be added to this StmtExpr
    2777         ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    2778         ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
    2779         ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
    2780 
    2781         indexerScopedAccept( node->result     , *this );
    2782         maybeAccept_impl   ( node->statements , *this );
    2783         maybeAccept_impl   ( node->returnDecls, *this );
    2784         maybeAccept_impl   ( node->dtors      , *this );
    2785 
    2786         VISIT_END( node );
    2787 }
    2788 
    2789 template< typename pass_type >
    2790 Expression * PassVisitor< pass_type >::mutate( StmtExpr * node ) {
    2791         MUTATE_START( node );
    2792 
    2793         // don't want statements from outer CompoundStmts to be added to this StmtExpr
    2794         ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
     1976        ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
    27951977        ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
    27961978        ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
     
    28171999
    28182000template< typename pass_type >
    2819 void PassVisitor< pass_type >::visit( const UniqueExpr * node ) {
    2820         VISIT_START( node );
    2821 
    2822         indexerScopedAccept( node->result, *this );
    2823         maybeAccept_impl   ( node->expr  , *this );
    2824 
    2825         VISIT_END( node );
    2826 }
    2827 
    2828 template< typename pass_type >
    28292001Expression * PassVisitor< pass_type >::mutate( UniqueExpr * node ) {
    28302002        MUTATE_START( node );
     
    28512023
    28522024template< typename pass_type >
    2853 void PassVisitor< pass_type >::visit( const UntypedInitExpr * node ) {
    2854         VISIT_START( node );
    2855 
    2856         indexerScopedAccept( node->result, *this );
    2857         maybeAccept_impl   ( node->expr  , *this );
    2858         // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
    2859 
    2860         VISIT_END( node );
    2861 }
    2862 
    2863 template< typename pass_type >
    28642025Expression * PassVisitor< pass_type >::mutate( UntypedInitExpr * node ) {
    28652026        MUTATE_START( node );
     
    28872048
    28882049template< typename pass_type >
    2889 void PassVisitor< pass_type >::visit( const InitExpr * node ) {
    2890         VISIT_START( node );
    2891 
    2892         indexerScopedAccept( node->result, *this );
    2893         maybeAccept_impl   ( node->expr  , *this );
    2894         maybeAccept_impl   ( node->designation, *this );
    2895 
    2896         VISIT_END( node );
    2897 }
    2898 
    2899 template< typename pass_type >
    29002050Expression * PassVisitor< pass_type >::mutate( InitExpr * node ) {
    29012051        MUTATE_START( node );
     
    29162066
    29172067        indexerScopedAccept( node->result, *this );
    2918         maybeAccept_impl   ( node->expr, *this );
     2068        maybeAccept_impl( node->expr, *this );
    29192069        // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
    29202070
     
    29232073
    29242074template< typename pass_type >
    2925 void PassVisitor< pass_type >::visit( const DeletedExpr * node ) {
    2926         VISIT_START( node );
    2927 
    2928         indexerScopedAccept( node->result, *this );
    2929         maybeAccept_impl   ( node->expr, *this );
    2930         // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
    2931 
    2932         VISIT_END( node );
    2933 }
    2934 
    2935 template< typename pass_type >
    29362075Expression * PassVisitor< pass_type >::mutate( DeletedExpr * node ) {
    2937         MUTATE_START( node );
    2938 
    2939         indexerScopedMutate( node->env, *this );
    2940         indexerScopedMutate( node->result, *this );
    2941         maybeMutate_impl( node->expr, *this );
    2942 
    2943         MUTATE_END( Expression, node );
    2944 }
    2945 
    2946 //--------------------------------------------------------------------------
    2947 // DefaultArgExpr
    2948 template< typename pass_type >
    2949 void PassVisitor< pass_type >::visit( DefaultArgExpr * node ) {
    2950         VISIT_START( node );
    2951 
    2952         indexerScopedAccept( node->result, *this );
    2953         maybeAccept_impl   ( node->expr, *this );
    2954 
    2955         VISIT_END( node );
    2956 }
    2957 
    2958 template< typename pass_type >
    2959 void PassVisitor< pass_type >::visit( const DefaultArgExpr * node ) {
    2960         VISIT_START( node );
    2961 
    2962         indexerScopedAccept( node->result, *this );
    2963         maybeAccept_impl   ( node->expr, *this );
    2964 
    2965         VISIT_END( node );
    2966 }
    2967 
    2968 template< typename pass_type >
    2969 Expression * PassVisitor< pass_type >::mutate( DefaultArgExpr * node ) {
    29702076        MUTATE_START( node );
    29712077
     
    29942100
    29952101template< typename pass_type >
    2996 void PassVisitor< pass_type >::visit( const GenericExpr * node ) {
    2997         VISIT_START( node );
    2998 
    2999         indexerScopedAccept( node->result, *this );
    3000         maybeAccept_impl( node->control, *this );
    3001         for ( const GenericExpr::Association & assoc : node->associations ) {
    3002                 indexerScopedAccept( assoc.type, *this );
    3003                 maybeAccept_impl( assoc.expr, *this );
    3004         }
    3005 
    3006         VISIT_END( node );
    3007 }
    3008 
    3009 template< typename pass_type >
    30102102Expression * PassVisitor< pass_type >::mutate( GenericExpr * node ) {
    30112103        MUTATE_START( node );
     
    30342126
    30352127template< typename pass_type >
    3036 void PassVisitor< pass_type >::visit( const VoidType * node ) {
    3037         VISIT_START( node );
    3038 
    3039         maybeAccept_impl( node->forall, *this );
    3040 
    3041         VISIT_END( node );
    3042 }
    3043 
    3044 template< typename pass_type >
    30452128Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
    30462129        MUTATE_START( node );
     
    30552138template< typename pass_type >
    30562139void PassVisitor< pass_type >::visit( BasicType * node ) {
    3057         VISIT_START( node );
    3058 
    3059         maybeAccept_impl( node->forall, *this );
    3060 
    3061         VISIT_END( node );
    3062 }
    3063 
    3064 template< typename pass_type >
    3065 void PassVisitor< pass_type >::visit( const BasicType * node ) {
    30662140        VISIT_START( node );
    30672141
     
    30942168
    30952169template< typename pass_type >
    3096 void PassVisitor< pass_type >::visit( const PointerType * node ) {
    3097         VISIT_START( node );
    3098 
    3099         maybeAccept_impl( node->forall, *this );
    3100         // xxx - should PointerType visit/mutate dimension?
    3101         maybeAccept_impl( node->base, *this );
    3102 
    3103         VISIT_END( node );
    3104 }
    3105 
    3106 template< typename pass_type >
    31072170Type * PassVisitor< pass_type >::mutate( PointerType * node ) {
    31082171        MUTATE_START( node );
     
    31292192
    31302193template< typename pass_type >
    3131 void PassVisitor< pass_type >::visit( const ArrayType * node ) {
    3132         VISIT_START( node );
    3133 
    3134         maybeAccept_impl( node->forall, *this );
    3135         maybeAccept_impl( node->dimension, *this );
    3136         maybeAccept_impl( node->base, *this );
    3137 
    3138         VISIT_END( node );
    3139 }
    3140 
    3141 template< typename pass_type >
    31422194Type * PassVisitor< pass_type >::mutate( ArrayType * node ) {
    31432195        MUTATE_START( node );
     
    31632215
    31642216template< typename pass_type >
    3165 void PassVisitor< pass_type >::visit( const ReferenceType * node ) {
    3166         VISIT_START( node );
    3167 
    3168         maybeAccept_impl( node->forall, *this );
    3169         maybeAccept_impl( node->base, *this );
    3170 
    3171         VISIT_END( node );
    3172 }
    3173 
    3174 template< typename pass_type >
    31752217Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) {
    31762218        MUTATE_START( node );
     
    31782220        maybeMutate_impl( node->forall, *this );
    31792221        maybeMutate_impl( node->base, *this );
    3180 
    3181         MUTATE_END( Type, node );
    3182 }
    3183 
    3184 //--------------------------------------------------------------------------
    3185 // QualifiedType
    3186 template< typename pass_type >
    3187 void PassVisitor< pass_type >::visit( QualifiedType * node ) {
    3188         VISIT_START( node );
    3189 
    3190         maybeAccept_impl( node->forall, *this );
    3191         maybeAccept_impl( node->parent, *this );
    3192         maybeAccept_impl( node->child, *this );
    3193 
    3194         VISIT_END( node );
    3195 }
    3196 
    3197 template< typename pass_type >
    3198 void PassVisitor< pass_type >::visit( const QualifiedType * node ) {
    3199         VISIT_START( node );
    3200 
    3201         maybeAccept_impl( node->forall, *this );
    3202         maybeAccept_impl( node->parent, *this );
    3203         maybeAccept_impl( node->child, *this );
    3204 
    3205         VISIT_END( node );
    3206 }
    3207 
    3208 template< typename pass_type >
    3209 Type * PassVisitor< pass_type >::mutate( QualifiedType * node ) {
    3210         MUTATE_START( node );
    3211 
    3212         maybeMutate_impl( node->forall, *this );
    3213         maybeMutate_impl( node->parent, *this );
    3214         maybeMutate_impl( node->child, *this );
    32152222
    32162223        MUTATE_END( Type, node );
     
    32312238
    32322239template< typename pass_type >
    3233 void PassVisitor< pass_type >::visit( const FunctionType * node ) {
    3234         VISIT_START( node );
    3235 
    3236         maybeAccept_impl( node->forall, *this );
    3237         maybeAccept_impl( node->returnVals, *this );
    3238         maybeAccept_impl( node->parameters, *this );
    3239 
    3240         VISIT_END( node );
    3241 }
    3242 
    3243 template< typename pass_type >
    32442240Type * PassVisitor< pass_type >::mutate( FunctionType * node ) {
    32452241        MUTATE_START( node );
     
    32702266
    32712267template< typename pass_type >
    3272 void PassVisitor< pass_type >::visit( const StructInstType * node ) {
     2268Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
     2269        MUTATE_START( node );
     2270
     2271        indexerAddStruct( node->name );
     2272
     2273        {
     2274                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     2275                maybeMutate_impl( node->forall    , *this );
     2276                maybeMutate_impl( node->parameters, *this );
     2277        }
     2278
     2279        MUTATE_END( Type, node );
     2280}
     2281
     2282//--------------------------------------------------------------------------
     2283// UnionInstType
     2284template< typename pass_type >
     2285void PassVisitor< pass_type >::visit( UnionInstType * node ) {
    32732286        VISIT_START( node );
    32742287
     
    32852298
    32862299template< typename pass_type >
    3287 Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
     2300Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
    32882301        MUTATE_START( node );
    32892302
     
    33002313
    33012314//--------------------------------------------------------------------------
    3302 // UnionInstType
    3303 template< typename pass_type >
    3304 void PassVisitor< pass_type >::visit( UnionInstType * node ) {
    3305         VISIT_START( node );
    3306 
    3307         indexerAddStruct( node->name );
    3308 
    3309         {
    3310                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    3311                 maybeAccept_impl( node->forall    , *this );
    3312                 maybeAccept_impl( node->parameters, *this );
    3313         }
    3314 
    3315         VISIT_END( node );
    3316 }
    3317 
    3318 template< typename pass_type >
    3319 void PassVisitor< pass_type >::visit( const UnionInstType * node ) {
    3320         VISIT_START( node );
    3321 
    3322         indexerAddStruct( node->name );
    3323 
    3324         {
    3325                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    3326                 maybeAccept_impl( node->forall    , *this );
    3327                 maybeAccept_impl( node->parameters, *this );
    3328         }
    3329 
    3330         VISIT_END( node );
    3331 }
    3332 
    3333 template< typename pass_type >
    3334 Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
    3335         MUTATE_START( node );
    3336 
    3337         indexerAddStruct( node->name );
    3338 
    3339         {
    3340                 auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    3341                 maybeMutate_impl( node->forall    , *this );
    3342                 maybeMutate_impl( node->parameters, *this );
    3343         }
    3344 
    3345         MUTATE_END( Type, node );
    3346 }
    3347 
    3348 //--------------------------------------------------------------------------
    33492315// EnumInstType
    33502316template< typename pass_type >
     
    33592325
    33602326template< typename pass_type >
    3361 void PassVisitor< pass_type >::visit( const EnumInstType * node ) {
    3362         VISIT_START( node );
    3363 
    3364         maybeAccept_impl( node->forall, *this );
    3365         maybeAccept_impl( node->parameters, *this );
    3366 
    3367         VISIT_END( node );
    3368 }
    3369 
    3370 template< typename pass_type >
    33712327Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
    33722328        MUTATE_START( node );
     
    33912347
    33922348template< typename pass_type >
    3393 void PassVisitor< pass_type >::visit( const TraitInstType * node ) {
    3394         VISIT_START( node );
    3395 
    3396         maybeAccept_impl( node->forall    , *this );
    3397         maybeAccept_impl( node->parameters, *this );
    3398 
    3399         VISIT_END( node );
    3400 }
    3401 
    3402 template< typename pass_type >
    34032349Type * PassVisitor< pass_type >::mutate( TraitInstType * node ) {
    34042350        MUTATE_START( node );
     
    34142360template< typename pass_type >
    34152361void PassVisitor< pass_type >::visit( TypeInstType * node ) {
    3416         VISIT_START( node );
    3417 
    3418         maybeAccept_impl( node->forall    , *this );
    3419         maybeAccept_impl( node->parameters, *this );
    3420 
    3421         VISIT_END( node );
    3422 }
    3423 
    3424 template< typename pass_type >
    3425 void PassVisitor< pass_type >::visit( const TypeInstType * node ) {
    34262362        VISIT_START( node );
    34272363
     
    34562392
    34572393template< typename pass_type >
    3458 void PassVisitor< pass_type >::visit( const TupleType * node ) {
    3459         VISIT_START( node );
    3460 
    3461         maybeAccept_impl( node->forall, *this );
    3462         maybeAccept_impl( node->types, *this );
    3463         maybeAccept_impl( node->members, *this );
    3464 
    3465         VISIT_END( node );
    3466 }
    3467 
    3468 template< typename pass_type >
    34692394Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
    34702395        MUTATE_START( node );
     
    34812406template< typename pass_type >
    34822407void PassVisitor< pass_type >::visit( TypeofType * node ) {
    3483         VISIT_START( node );
    3484 
    3485         assert( node->expr );
    3486         maybeAccept_impl( node->expr, *this );
    3487 
    3488         VISIT_END( node );
    3489 }
    3490 
    3491 template< typename pass_type >
    3492 void PassVisitor< pass_type >::visit( const TypeofType * node ) {
    34932408        VISIT_START( node );
    34942409
     
    35272442
    35282443template< typename pass_type >
    3529 void PassVisitor< pass_type >::visit( const AttrType * node ) {
    3530         VISIT_START( node );
    3531 
    3532         if ( node->isType ) {
    3533                 assert( node->type );
    3534                 maybeAccept_impl( node->type, *this );
    3535         } else {
    3536                 assert( node->expr );
    3537                 maybeAccept_impl( node->expr, *this );
    3538         } // if
    3539 
    3540         VISIT_END( node );
    3541 }
    3542 
    3543 template< typename pass_type >
    35442444Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
    35452445        MUTATE_START( node );
     
    35682468
    35692469template< typename pass_type >
    3570 void PassVisitor< pass_type >::visit( const VarArgsType * node ) {
     2470Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
     2471        MUTATE_START( node );
     2472
     2473        maybeMutate_impl( node->forall, *this );
     2474
     2475        MUTATE_END( Type, node );
     2476}
     2477
     2478//--------------------------------------------------------------------------
     2479// ZeroType
     2480template< typename pass_type >
     2481void PassVisitor< pass_type >::visit( ZeroType * node ) {
    35712482        VISIT_START( node );
    35722483
     
    35772488
    35782489template< typename pass_type >
    3579 Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
     2490Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
    35802491        MUTATE_START( node );
    35812492
     
    35862497
    35872498//--------------------------------------------------------------------------
    3588 // ZeroType
    3589 template< typename pass_type >
    3590 void PassVisitor< pass_type >::visit( ZeroType * node ) {
     2499// OneType
     2500template< typename pass_type >
     2501void PassVisitor< pass_type >::visit( OneType * node ) {
    35912502        VISIT_START( node );
    35922503
     
    35972508
    35982509template< typename pass_type >
    3599 void PassVisitor< pass_type >::visit( const ZeroType * node ) {
    3600         VISIT_START( node );
    3601 
    3602         maybeAccept_impl( node->forall, *this );
    3603 
    3604         VISIT_END( node );
    3605 }
    3606 
    3607 template< typename pass_type >
    3608 Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
     2510Type * PassVisitor< pass_type >::mutate( OneType * node ) {
    36092511        MUTATE_START( node );
    36102512
     
    36152517
    36162518//--------------------------------------------------------------------------
    3617 // OneType
    3618 template< typename pass_type >
    3619 void PassVisitor< pass_type >::visit( OneType * node ) {
    3620         VISIT_START( node );
    3621 
    3622         maybeAccept_impl( node->forall, *this );
    3623 
    3624         VISIT_END( node );
    3625 }
    3626 
    3627 template< typename pass_type >
    3628 void PassVisitor< pass_type >::visit( const OneType * node ) {
    3629         VISIT_START( node );
    3630 
    3631         maybeAccept_impl( node->forall, *this );
    3632 
    3633         VISIT_END( node );
    3634 }
    3635 
    3636 template< typename pass_type >
    3637 Type * PassVisitor< pass_type >::mutate( OneType * node ) {
    3638         MUTATE_START( node );
    3639 
    3640         maybeMutate_impl( node->forall, *this );
    3641 
    3642         MUTATE_END( Type, node );
    3643 }
    3644 
    3645 //--------------------------------------------------------------------------
    3646 // GlobalScopeType
    3647 template< typename pass_type >
    3648 void PassVisitor< pass_type >::visit( GlobalScopeType * node ) {
    3649         VISIT_START( node );
    3650 
    3651         maybeAccept_impl( node->forall, *this );
    3652 
    3653         VISIT_END( node );
    3654 }
    3655 
    3656 template< typename pass_type >
    3657 void PassVisitor< pass_type >::visit( const GlobalScopeType * node ) {
    3658         VISIT_START( node );
    3659 
    3660         maybeAccept_impl( node->forall, *this );
    3661 
    3662         VISIT_END( node );
    3663 }
    3664 
    3665 template< typename pass_type >
    3666 Type * PassVisitor< pass_type >::mutate( GlobalScopeType * node ) {
    3667         MUTATE_START( node );
    3668 
    3669         maybeMutate_impl( node->forall, *this );
    3670 
    3671         MUTATE_END( Type, node );
    3672 }
    3673 
    3674 //--------------------------------------------------------------------------
    36752519// Designation
    36762520template< typename pass_type >
     
    36842528
    36852529template< typename pass_type >
    3686 void PassVisitor< pass_type >::visit( const Designation * node ) {
    3687         VISIT_START( node );
    3688 
    3689         maybeAccept_impl( node->designators, *this );
    3690 
    3691         VISIT_END( node );
    3692 }
    3693 
    3694 template< typename pass_type >
    36952530Designation * PassVisitor< pass_type >::mutate( Designation * node ) {
    36962531        MUTATE_START( node );
     
    37132548
    37142549template< typename pass_type >
    3715 void PassVisitor< pass_type >::visit( const SingleInit * node ) {
    3716         VISIT_START( node );
    3717 
    3718         visitExpression( node->value );
    3719 
    3720         VISIT_END( node );
    3721 }
    3722 
    3723 template< typename pass_type >
    37242550Initializer * PassVisitor< pass_type >::mutate( SingleInit * node ) {
    37252551        MUTATE_START( node );
     
    37342560template< typename pass_type >
    37352561void PassVisitor< pass_type >::visit( ListInit * node ) {
    3736         VISIT_START( node );
    3737 
    3738         maybeAccept_impl( node->designations, *this );
    3739         maybeAccept_impl( node->initializers, *this );
    3740 
    3741         VISIT_END( node );
    3742 }
    3743 
    3744 template< typename pass_type >
    3745 void PassVisitor< pass_type >::visit( const ListInit * node ) {
    37462562        VISIT_START( node );
    37472563
     
    37762592
    37772593template< typename pass_type >
    3778 void PassVisitor< pass_type >::visit( const ConstructorInit * node ) {
    3779         VISIT_START( node );
    3780 
    3781         maybeAccept_impl( node->ctor, *this );
    3782         maybeAccept_impl( node->dtor, *this );
    3783         maybeAccept_impl( node->init, *this );
    3784 
    3785         VISIT_END( node );
    3786 }
    3787 
    3788 template< typename pass_type >
    37892594Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
    37902595        MUTATE_START( node );
     
    37982603
    37992604//--------------------------------------------------------------------------
     2605// Subrange
     2606template< typename pass_type >
     2607void PassVisitor< pass_type >::visit( Subrange * node ) {
     2608        VISIT_START( node );
     2609
     2610        VISIT_END( node );
     2611}
     2612
     2613template< typename pass_type >
     2614Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
     2615        MUTATE_START( node );
     2616
     2617        MUTATE_END( Subrange, node );
     2618}
     2619
     2620//--------------------------------------------------------------------------
    38002621// Attribute
    38012622template< typename pass_type >
     
    38072628
    38082629template< typename pass_type >
    3809 void PassVisitor< pass_type >::visit( const Constant * node ) {
    3810         VISIT_START( node );
    3811 
    3812         VISIT_END( node );
    3813 }
    3814 
    3815 template< typename pass_type >
    38162630Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
    38172631        MUTATE_START( node );
     
    38242638template< typename pass_type >
    38252639void PassVisitor< pass_type >::visit( Attribute * node ) {
    3826         VISIT_START( node );
    3827 
    3828         maybeAccept_impl( node->parameters, *this );
    3829 
    3830         VISIT_END( node );
    3831 }
    3832 
    3833 template< typename pass_type >
    3834 void PassVisitor< pass_type >::visit( const Attribute * node ) {
    38352640        VISIT_START( node );
    38362641
     
    38642669        MUTATE_END( TypeSubstitution, node );
    38652670}
    3866 
    3867 #undef VISIT_START
    3868 #undef VISIT_END
    3869 
    3870 #undef MUTATE_START
    3871 #undef MUTATE_END
  • src/Common/PassVisitor.proto.h

    rb067d9b r7951100  
    118118static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
    119119
    120 template<typename pass_type, typename node_type>
    121 static inline auto previsit_impl( pass_type& pass, const node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.previsit( node ), void() ) {
    122         pass.previsit( node );
    123 }
    124 
    125 template<typename pass_type, typename node_type>
    126 static inline void previsit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
    127 
    128 
    129 template<typename pass_type, typename node_type>
    130 static inline auto postvisit_impl( pass_type& pass, const node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.postvisit( node ), void() ) {
    131         pass.postvisit( node );
    132 }
    133 
    134 template<typename pass_type, typename node_type>
    135 static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
    136 
    137120//---------------------------------------------------------
    138121// Mutate
     
    182165static inline type * name##_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) { return nullptr;}    \
    183166
    184 FIELD_PTR( const TypeSubstitution *, env )
     167FIELD_PTR( TypeSubstitution *, env )
    185168FIELD_PTR( std::list< Statement* >, stmtsToAddBefore )
    186169FIELD_PTR( std::list< Statement* >, stmtsToAddAfter  )
     
    191174FIELD_PTR( PassVisitor<pass_type> * const, visitor )
    192175
    193 #undef FIELD_PTR
    194 
    195176//---------------------------------------------------------
    196177// Indexer
     
    217198        pass.indexer.func( arg );                                                                                                \
    218199}                                                                                                                              \
    219 template<typename pass_type>                                                                                                   \
    220 static inline void indexer_impl_##func ( pass_type &, long, type ) { }
     200                                                                                                                               \
     201template<typename pass_type>                                                                                                   \
     202static inline void indexer_impl_##func ( pass_type &, long, type ) { }                                                          \
    221203
    222204#define INDEXER_FUNC2( func, type1, type2 )                                                                                             \
     
    225207        pass.indexer.func( arg1, arg2 );                                                                                                \
    226208}                                                                                                                              \
     209                                                                                                                               \
    227210template<typename pass_type>                                                                                                   \
    228211static inline void indexer_impl_##func ( pass_type &, long, type1, type2 ) { }
    229212
    230213
    231 INDEXER_FUNC1( addId     , const DeclarationWithType *       );
    232 INDEXER_FUNC1( addType   , const NamedTypeDecl *             );
    233 INDEXER_FUNC1( addStruct , const StructDecl *                );
    234 INDEXER_FUNC1( addEnum   , const EnumDecl *                  );
    235 INDEXER_FUNC1( addUnion  , const UnionDecl *                 );
    236 INDEXER_FUNC1( addTrait  , const TraitDecl *                 );
    237 INDEXER_FUNC2( addWith   , const std::list< Expression * > &, const Declaration * );
    238 
    239 #undef INDEXER_FUNC1
    240 #undef INDEXER_FUNC2
    241 
    242 template<typename pass_type>
    243 static inline auto indexer_impl_addStructFwd( pass_type & pass, int, const StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
     214INDEXER_FUNC1( addId     , DeclarationWithType *       );
     215INDEXER_FUNC1( addType   , NamedTypeDecl *             );
     216INDEXER_FUNC1( addStruct , StructDecl *                );
     217INDEXER_FUNC1( addEnum   , EnumDecl *                  );
     218INDEXER_FUNC1( addUnion  , UnionDecl *                 );
     219INDEXER_FUNC1( addTrait  , TraitDecl *                 );
     220INDEXER_FUNC2( addWith   , std::list< Expression * > &, BaseSyntaxNode * );
     221
     222
     223template<typename pass_type>
     224static inline auto indexer_impl_addStructFwd( pass_type & pass, int, StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
    244225        StructDecl * fwd = new StructDecl( decl->name );
    245226        cloneAll( decl->parameters, fwd->parameters );
     
    248229
    249230template<typename pass_type>
    250 static inline auto indexer_impl_addStructFwd( pass_type &, long, const StructDecl * ) {}
    251 
    252 template<typename pass_type>
    253 static inline auto indexer_impl_addUnionFwd( pass_type & pass, int, const UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
     231static inline auto indexer_impl_addStructFwd( pass_type &, long, StructDecl * ) {}
     232
     233template<typename pass_type>
     234static inline auto indexer_impl_addUnionFwd( pass_type & pass, int, UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
    254235        UnionDecl * fwd = new UnionDecl( decl->name );
    255236        cloneAll( decl->parameters, fwd->parameters );
     
    258239
    259240template<typename pass_type>
    260 static inline auto indexer_impl_addUnionFwd( pass_type &, long, const UnionDecl * ) {}
     241static inline auto indexer_impl_addUnionFwd( pass_type &, long, UnionDecl * ) {}
    261242
    262243template<typename pass_type>
  • src/Common/ScopedMap.h

    rb067d9b r7951100  
    2222#include <vector>
    2323
    24 /// Default (empty) ScopedMap note type
    25 struct EmptyNote {};
    26 
    2724/// A map where the items are placed into nested scopes;
    28 /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward.
    29 /// Scopes may be annotated with a value; the annotation defaults to empty
    30 template<typename Key, typename Value, typename Note = EmptyNote>
     25/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
     26template<typename Key, typename Value>
    3127class ScopedMap {
    32         typedef std::map< Key, Value > MapType;
    33         struct Scope {
    34                 MapType map;
    35                 Note note;
    36 
    37                 template<typename N>
    38                 Scope(N&& n) : map(), note(std::forward<N>(n)) {}
    39                
    40                 Scope() = default;
    41                 Scope(const Scope&) = default;
    42                 Scope(Scope&&) = default;
    43                 Scope& operator= (const Scope&) = default;
    44                 Scope& operator= (Scope&&) = default;
    45         };
     28        typedef std::map< Key, Value > Scope;
    4629        typedef std::vector< Scope > ScopeList;
    4730
    4831        ScopeList scopes; ///< scoped list of maps
    4932public:
    50         typedef typename MapType::key_type key_type;
    51         typedef typename MapType::mapped_type mapped_type;
    52         typedef typename MapType::value_type value_type;
     33        typedef typename Scope::key_type key_type;
     34        typedef typename Scope::mapped_type mapped_type;
     35        typedef typename Scope::value_type value_type;
    5336        typedef typename ScopeList::size_type size_type;
    5437        typedef typename ScopeList::difference_type difference_type;
    55         typedef typename MapType::reference reference;
    56         typedef typename MapType::const_reference const_reference;
    57         typedef typename MapType::pointer pointer;
    58         typedef typename MapType::const_pointer const_pointer;
     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;
    5942
    6043        class iterator : public std::iterator< std::bidirectional_iterator_tag,
     
    6245        friend class ScopedMap;
    6346        friend class const_iterator;
    64                 typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    65                 typedef typename ScopedMap::ScopeList scope_list;
     47                typedef typename std::map< Key, Value >::iterator wrapped_iterator;
     48                typedef typename std::vector< std::map< Key, Value > > scope_list;
    6649                typedef typename scope_list::size_type size_type;
    6750
    6851                /// Checks if this iterator points to a valid item
    6952                bool is_valid() const {
    70                         return it != (*scopes)[level].map.end();
     53                        return it != (*scopes)[level].end();
    7154                }
    7255
     
    9679
    9780                iterator& operator++ () {
    98                         if ( it == (*scopes)[level].map.end() ) {
     81                        if ( it == (*scopes)[level].end() ) {
    9982                                if ( level == 0 ) return *this;
    10083                                --level;
    101                                 it = (*scopes)[level].map.begin();
     84                                it = (*scopes)[level].begin();
    10285                        } else {
    10386                                ++it;
     
    10992                iterator& operator-- () {
    11093                        // may fail if this is the begin iterator; allowed by STL spec
    111                         if ( it == (*scopes)[level].map.begin() ) {
     94                        if ( it == (*scopes)[level].begin() ) {
    11295                                ++level;
    113                                 it = (*scopes)[level].map.end();
     96                                it = (*scopes)[level].end();
    11497                        }
    11598                        --it;
     
    124107
    125108                size_type get_level() const { return level; }
    126 
    127                 Note& get_note() { return (*scopes)[level].note; }
    128                 const Note& get_note() const { return (*scopes)[level].note; }
    129109
    130110        private:
     
    137117                                                     value_type > {
    138118        friend class ScopedMap;
    139                 typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    140                 typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
    141                 typedef typename ScopedMap::ScopeList scope_list;
     119                typedef typename std::map< Key, Value >::iterator wrapped_iterator;
     120                typedef typename std::map< Key, Value >::const_iterator wrapped_const_iterator;
     121                typedef typename std::vector< std::map< Key, Value > > scope_list;
    142122                typedef typename scope_list::size_type size_type;
    143123
    144124                /// Checks if this iterator points to a valid item
    145125                bool is_valid() const {
    146                         return it != (*scopes)[level].map.end();
     126                        return it != (*scopes)[level].end();
    147127                }
    148128
     
    177157
    178158                const_iterator& operator++ () {
    179                         if ( it == (*scopes)[level].map.end() ) {
     159                        if ( it == (*scopes)[level].end() ) {
    180160                                if ( level == 0 ) return *this;
    181161                                --level;
    182                                 it = (*scopes)[level].map.begin();
     162                                it = (*scopes)[level].begin();
    183163                        } else {
    184164                                ++it;
     
    190170                const_iterator& operator-- () {
    191171                        // may fail if this is the begin iterator; allowed by STL spec
    192                         if ( it == (*scopes)[level].map.begin() ) {
     172                        if ( it == (*scopes)[level].begin() ) {
    193173                                ++level;
    194                                 it = (*scopes)[level].map.end();
     174                                it = (*scopes)[level].end();
    195175                        }
    196176                        --it;
     
    205185
    206186                size_type get_level() const { return level; }
    207 
    208                 const Note& get_note() const { return (*scopes)[level].note; }
    209187
    210188        private:
     
    219197        }
    220198
    221         // Starts a new scope with the given note
    222         template<typename N>
    223         void beginScope( N&& n ) {
    224                 scopes.emplace_back( std::forward<N>(n) );
    225         }
    226 
    227199        /// Ends a scope; invalidates any iterators pointing to elements of that scope
    228200        void endScope() {
     
    232204
    233205        /// Default constructor initializes with one scope
    234         ScopedMap() : scopes() { beginScope(); }
    235 
    236         /// Constructs with a given note on the outermost scope
    237         template<typename N>
    238         ScopedMap( N&& n ) : scopes() { beginScope(std::forward<N>(n)); }
    239 
    240         iterator begin() { return iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
    241         const_iterator begin() const { return const_iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
    242         const_iterator cbegin() const { return const_iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
    243         iterator end() { return iterator(scopes, scopes[0].map.end(), 0); }
    244         const_iterator end() const { return const_iterator(scopes, scopes[0].map.end(), 0); }
    245         const_iterator cend() const { return const_iterator(scopes, scopes[0].map.end(), 0); }
     206        ScopedMap() { beginScope(); }
     207
     208        iterator begin() { return iterator(scopes, scopes.back().begin(), currentScope()).next_valid(); }
     209        const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), currentScope()).next_valid(); }
     210        const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), currentScope()).next_valid(); }
     211        iterator end() { return iterator(scopes, scopes[0].end(), 0); }
     212        const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
     213        const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
    246214
    247215        /// Gets the index of the current scope (counted from 1)
    248216        size_type currentScope() const { return scopes.size() - 1; }
    249 
    250         /// Gets the note at the given scope
    251         Note& getNote( size_type i ) { return scopes[i].note; }
    252         const Note& getNote( size_type i ) const { return scopes[i].note; }
    253217
    254218        /// Finds the given key in the outermost scope it occurs; returns end() for none such
    255219        iterator find( const Key &key ) {
    256220                for ( size_type i = scopes.size() - 1; ; --i ) {
    257                         typename MapType::iterator val = scopes[i].map.find( key );
    258                         if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
     221                        typename Scope::iterator val = scopes[i].find( key );
     222                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    259223                        if ( i == 0 ) break;
    260224                }
     
    262226        }
    263227        const_iterator find( const Key &key ) const {
    264                         return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->find( key ) );
     228                        return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->find( key ) );
    265229        }
    266230
    267231        /// Finds the given key in the provided scope; returns end() for none such
    268232        iterator findAt( size_type scope, const Key& key ) {
    269                 typename MapType::iterator val = scopes[scope].map.find( key );
    270                 if ( val != scopes[scope].map.end() ) return iterator( scopes, val, scope );
     233                typename Scope::iterator val = scopes[scope].find( key );
     234                if ( val != scopes[scope].end() ) return iterator( scopes, val, scope );
    271235                return end();
    272236        }
    273237        const_iterator findAt( size_type scope, const Key& key ) const {
    274                 return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findAt( scope, key ) );
     238                return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findAt( scope, key ) );
    275239        }
    276240
     
    279243                if ( it.level == 0 ) return end();
    280244                for ( size_type i = it.level - 1; ; --i ) {
    281                         typename MapType::iterator val = scopes[i].map.find( key );
    282                         if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
     245                        typename Scope::iterator val = scopes[i].find( key );
     246                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    283247                        if ( i == 0 ) break;
    284248                }
     
    286250        }
    287251        const_iterator findNext( const_iterator &it, const Key &key ) const {
    288                         return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findNext( it, key ) );
     252                        return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findNext( it, key ) );
    289253        }
    290254
     
    292256        template< typename value_type_t >
    293257        std::pair< iterator, bool > insert( value_type_t&& value ) {
    294                 std::pair< typename MapType::iterator, bool > res = scopes.back().map.insert( std::forward<value_type_t>( value ) );
     258                std::pair< typename Scope::iterator, bool > res = scopes.back().insert( std::forward<value_type_t>( value ) );
    295259                return std::make_pair( iterator(scopes, std::move( res.first ), scopes.size()-1), std::move( res.second ) );
    296260        }
     
    298262        template< typename value_type_t >
    299263        std::pair< iterator, bool > insert( iterator at, value_type_t&& value ) {
    300                 MapType& scope = (*at.scopes)[ at.level ].map;
    301                 std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
     264                Scope& scope = (*at.scopes) [ at.level ];
     265                std::pair< typename Scope::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
    302266                return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
    303267        }
     
    308272        template< typename value_type_t >
    309273        std::pair< iterator, bool > insertAt( size_type scope, value_type_t&& value ) {
    310                 std::pair< typename MapType::iterator, bool > res = scopes.at(scope).map.insert( std::forward<value_type_t>( value ) );
     274                std::pair< typename Scope::iterator, bool > res = scopes.at(scope).insert( std::forward<value_type_t>( value ) );
    311275                return std::make_pair( iterator(scopes, std::move( res.first ), scope), std::move( res.second ) );
    312276        }
     
    324288
    325289        iterator erase( iterator pos ) {
    326                 MapType& scope = (*pos.scopes)[ pos.level ].map;
     290                Scope& scope = (*pos.scopes) [ pos.level ];
    327291                const typename iterator::wrapped_iterator& new_it = scope.erase( pos.it );
    328292                iterator it( *pos.scopes, new_it, pos.level );
  • src/Common/SemanticError.h

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 19 10:09:17 2018
    13 // Update Count     : 31
     12// Last Modified On : Wed May 16 15:01:23 2018
     13// Update Count     : 30
    1414//
    1515
     
    1717
    1818#include "ErrorObjects.h"
    19 #include "AST/Node.hpp"
    2019#include <cstring>
    2120
     
    5756        {"reference-conversion"   , "rvalue to reference conversion of rvalue: %s" , Severity::Warn},
    5857        {"qualifiers-zero_t-one_t", "questionable use of type qualifier %s with %s", Severity::Warn},
    59         {"aggregate-forward-decl" , "forward declaration of nested aggregate: %s"  , Severity::Warn},
    60         {"superfluous-decl"       , "declaration does not allocate storage: %s"    , Severity::Warn},
    61         {"gcc-attributes"         , "invalid attribute: %s"                        , Severity::Warn},
    6258};
    6359
     
    6662        RvalueToReferenceConversion,
    6763        BadQualifiersZeroOne,
    68         AggrForwardDecl,
    69         SuperfluousDecl,
    70         GccAttributes,
    71         NUMBER_OF_WARNINGS, // This MUST be the last warning
     64        NUMBER_OF_WARNINGS, //This MUST be the last warning
    7265};
    7366
  • src/Common/module.mk

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 SRC_COMMON = \
    18       Common/Assert.cc \
    19       Common/Eval.cc \
    20       Common/PassVisitor.cc \
    21       Common/SemanticError.cc \
    22       Common/Stats/Counter.cc \
    23       Common/Stats/Heap.cc \
    24       Common/Stats/Stats.cc \
    25       Common/Stats/Time.cc \
    26       Common/UniqueName.cc
    27 
    28 SRC += $(SRC_COMMON) Common/DebugMalloc.cc
    29 SRCDEMANGLE += $(SRC_COMMON)
     17SRC += Common/SemanticError.cc \
     18       Common/UniqueName.cc \
     19       Common/DebugMalloc.cc \
     20       Common/Assert.cc \
     21       Common/Heap.cc
  • src/Common/utility.h

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 24 14:28:19 2019
    13 // Update Count     : 41
     12// Last Modified On : Sun May  6 22:24:16 2018
     13// Update Count     : 40
    1414//
    1515
    1616#pragma once
    1717
    18 #include <cassert>
    1918#include <cctype>
    2019#include <algorithm>
     
    2726#include <string>
    2827#include <type_traits>
    29 #include <utility>
    30 #include <vector>
     28
     29#include <cassert>
    3130
    3231#include "Common/Indenter.h"
    33 
    34 class Expression;
    35 
    36 /// bring std::move into global scope
    37 using std::move;
    38 
    39 /// partner to move that copies any copyable type
    40 template<typename T>
    41 T copy( const T & x ) { return x; }
    4232
    4333template< typename T >
     
    8171
    8272template< typename Container >
    83 void deleteAll( const Container &container ) {
    84         for ( const auto &i : container ) {
    85                 delete i;
     73void deleteAll( Container &container ) {
     74        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
     75                delete *i;
    8676        } // for
    8777}
     
    152142                return ret;
    153143        } // switch
    154 }
    155 
    156 /// Splice src onto the end of dst, clearing src
    157 template< typename T >
    158 void splice( std::vector< T > & dst, std::vector< T > & src ) {
    159         dst.reserve( dst.size() + src.size() );
    160         for ( T & x : src ) { dst.emplace_back( std::move( x ) ); }
    161         src.clear();
    162 }
    163 
    164 /// Splice src onto the begining of dst, clearing src
    165 template< typename T >
    166 void spliceBegin( std::vector< T > & dst, std::vector< T > & src ) {
    167         splice( src, dst );
    168         dst.swap( src );
    169144}
    170145
     
    481456} // ilog2
    482457
    483 // -----------------------------------------------------------------------------
    484 /// evaluates expr as a long long int. If second is false, expr could not be evaluated
    485 std::pair<long long int, bool> eval(const Expression * expr);
    486 
    487 namespace ast {
    488         class Expr;
    489 }
    490 
    491 std::pair<long long int, bool> eval(const ast::Expr * expr);
    492 
    493 // -----------------------------------------------------------------------------
    494 /// Reorders the input range in-place so that the minimal-value elements according to the
    495 /// comparator are in front;
    496 /// returns the iterator after the last minimal-value element.
    497 template<typename Iter, typename Compare>
    498 Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
    499         if ( begin == end ) return end;
    500 
    501         Iter min_pos = begin;
    502         for ( Iter i = begin + 1; i != end; ++i ) {
    503                 if ( lt( *i, *min_pos ) ) {
    504                         // new minimum cost; swap into first position
    505                         min_pos = begin;
    506                         std::iter_swap( min_pos, i );
    507                 } else if ( ! lt( *min_pos, *i ) ) {
    508                         // duplicate minimum cost; swap into next minimum position
    509                         ++min_pos;
    510                         std::iter_swap( min_pos, i );
    511                 }
    512         }
    513         return ++min_pos;
    514 }
    515 
    516 template<typename Iter, typename Compare>
    517 inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {
    518         return sort_mins( begin, end, lt );
    519 }
    520 
    521 /// sort_mins defaulted to use std::less
    522 template<typename Iter>
    523 inline Iter sort_mins( Iter begin, Iter end ) {
    524         return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
    525 }
    526458
    527459// Local Variables: //
  • src/Concurrency/Keywords.cc

    rb067d9b r7951100  
    9797                        "__thrd",
    9898                        "get_thread",
    99                         "thread keyword requires threads to be in scope, add #include <thread.hfa>",
     99                        "thread keyword requires threads to be in scope, add #include <thread>",
    100100                        true,
    101101                        KeywordCastExpr::Thread
     
    129129                        "__cor",
    130130                        "get_coroutine",
    131                         "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>",
     131                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine>",
    132132                        true,
    133133                        KeywordCastExpr::Coroutine
     
    161161                        "__mon",
    162162                        "get_monitor",
    163                         "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>",
     163                        "monitor keyword requires monitors to be in scope, add #include <monitor>",
    164164                        false,
    165165                        KeywordCastExpr::Monitor
     
    488488                // Do we have the required headers
    489489                if( !monitor_decl || !guard_decl || !dtor_guard_decl )
    490                         SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor.hfa>\n" );
     490                        SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>\n" );
    491491
    492492                // Instrument the body
     
    501501        void MutexKeyword::postvisit(StructDecl* decl) {
    502502
    503                 if( decl->name == "monitor_desc" && decl->body ) {
     503                if( decl->name == "monitor_desc" ) {
    504504                        assert( !monitor_decl );
    505505                        monitor_decl = decl;
    506506                }
    507                 else if( decl->name == "monitor_guard_t" && decl->body ) {
     507                else if( decl->name == "monitor_guard_t" ) {
    508508                        assert( !guard_decl );
    509509                        guard_decl = decl;
    510510                }
    511                 else if( decl->name == "monitor_dtor_guard_t" && decl->body ) {
     511                else if( decl->name == "monitor_dtor_guard_t" ) {
    512512                        assert( !dtor_guard_decl );
    513513                        dtor_guard_decl = decl;
     
    575575
    576576                //in reverse order :
    577                 // monitor_dtor_guard_t __guard = { __monitors, func };
     577                // monitor_guard_t __guard = { __monitors, #, func };
    578578                body->push_front(
    579579                        new DeclStmt( new ObjectDecl(
     
    634634                assert(generic_func);
    635635
    636                 // in reverse order :
     636                //in reverse order :
    637637                // monitor_guard_t __guard = { __monitors, #, func };
    638638                body->push_front(
     
    685685                if( type && type->get_baseStruct()->is_thread() ) {
    686686                        if( !thread_decl || !thread_ctor_seen ) {
    687                                 SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread.hfa>");
     687                                SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread>");
    688688                        }
    689689
  • src/Concurrency/Waitfor.cc

    rb067d9b r7951100  
    1111// Last Modified By :
    1212// Last Modified On :
    13 // Update Count     : 7
     13// Update Count     : 5
    1414//
    1515
     
    6666void foo() {
    6767        while( true ) {
    68                 {
    69                         acceptable_t acceptables[3];
    70                         if( a < 1 ) {
    71                                 acceptables[0].func = f;
    72                                 acceptables[0].mon = a;
     68
     69                acceptable_t acceptables[3];
     70                if( a < 1 ) {
     71                        acceptables[0].func = f;
     72                        acceptables[0].mon = a;
     73                }
     74                acceptables[1].func = g;
     75                acceptables[1].mon = a;
     76
     77                acceptables[2].func = f;
     78                acceptables[2].mon = a;
     79                acceptables[2].is_dtor = true;
     80
     81                int ret = waitfor_internal( acceptables, swagl() );
     82
     83                switch( ret ) {
     84                        case 0:
     85                        {
     86                                bar();
    7387                        }
    74                         acceptables[1].func = g;
    75                         acceptables[1].mon = a;
    76 
    77                         acceptables[2].func = f;
    78                         acceptables[2].mon = a;
    79                         acceptables[2].is_dtor = true;
    80 
    81                         int ret = waitfor_internal( acceptables, swagl() );
    82 
    83                         switch( ret ) {
    84                                 case 0:
     88                        case 1:
     89                        {
     90                                baz();
     91                        }
     92                        case 2:
     93                                signal(a);
    8594                                {
    86                                         bar();
     95                                        break;
    8796                                }
    88                                 case 1:
    89                                 {
    90                                         baz();
    91                                 }
    92                                 case 2:
    93                                         signal(a);
    94                                         {
    95                                                 break;
    96                                         }
    97                         }
    9897                }
    9998        }
     
    251250        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
    252251                if( !decl_monitor || !decl_acceptable || !decl_mask )
    253                         SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor.hfa>" );
     252                        SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
    254253
    255254                CompoundStmt * stmt = new CompoundStmt();
     
    556555                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
    557556                                        {
    558                                                 new CompoundStmt({
    559                                                         clause.statement,
    560                                                         new BranchStmt(
    561                                                                 "",
    562                                                                 BranchStmt::Break
    563                                                         )
    564                                                 })
     557                                                clause.statement,
     558                                                new BranchStmt(
     559                                                        "",
     560                                                        BranchStmt::Break
     561                                                )
    565562                                        }
    566563                                )
     
    573570                                        new ConstantExpr( Constant::from_int( -2 ) ),
    574571                                        {
    575                                                 new CompoundStmt({
    576                                                         waitfor->timeout.statement,
    577                                                         new BranchStmt(
    578                                                                 "",
    579                                                                 BranchStmt::Break
    580                                                         )
    581                                                 })
     572                                                waitfor->timeout.statement,
     573                                                new BranchStmt(
     574                                                        "",
     575                                                        BranchStmt::Break
     576                                                )
    582577                                        }
    583578                                )
     
    590585                                        new ConstantExpr( Constant::from_int( -1 ) ),
    591586                                        {
    592                                                 new CompoundStmt({
    593                                                         waitfor->orelse.statement,
    594                                                         new BranchStmt(
    595                                                                 "",
    596                                                                 BranchStmt::Break
    597                                                         )
    598                                                 })
     587                                                waitfor->orelse.statement,
     588                                                new BranchStmt(
     589                                                        "",
     590                                                        BranchStmt::Break
     591                                                )
    599592                                        }
    600593                                )
  • src/Concurrency/module.mk

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 SRC += Concurrency/Keywords.cc Concurrency/Waitfor.cc
    18 SRCDEMANGLE += Concurrency/Keywords.cc
     17SRC += Concurrency/Keywords.cc \
     18       Concurrency/Waitfor.cc
    1919
  • src/ControlStruct/ExceptTranslate.cc

    rb067d9b r7951100  
    99// Author           : Andrew Beach
    1010// Created On       : Wed Jun 14 16:49:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 13 18:15:29 2019
    13 // Update Count     : 11
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Aug 17 17:19:00 2017
     13// Update Count     : 9
    1414//
    1515
     
    319319                        }
    320320
    321                         block->push_back( handler->body );
    322                         handler->body = nullptr;
     321                        block->push_back( handler->get_body() );
     322                        handler->set_body( nullptr );
    323323
    324324                        std::list<Statement *> caseBody
     
    617617                                return create_terminate_rethrow( throwStmt );
    618618                        } else {
    619                                 abort("Invalid throw in %s at %i\n",
     619                                assertf(false, "Invalid throw in %s at %i\n",
    620620                                        throwStmt->location.filename.c_str(),
    621621                                        throwStmt->location.first_line);
     622                                return nullptr;
    622623                        }
    623624                } else {
     
    627628                                return create_resume_rethrow( throwStmt );
    628629                        } else {
    629                                 abort("Invalid throwResume in %s at %i\n",
     630                                assertf(false, "Invalid throwResume in %s at %i\n",
    630631                                        throwStmt->location.filename.c_str(),
    631632                                        throwStmt->location.first_line);
     633                                return nullptr;
    632634                        }
    633635                }
  • src/ControlStruct/ForExprMutator.cc

    rb067d9b r7951100  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 11 22:26:52 2019
    13 // Update Count     : 14
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Aug 18 10:22:00 2017
     13// Update Count     : 12
    1414//
    1515
     
    2121
    2222namespace ControlStruct {
    23         Statement * hoist( Statement * originalStmt, std::list<Statement *> & init ) {
     23        Statement *hoist( Statement *originalStmt, std::list<Statement *> &init ) {
    2424                // If no hoisting is needed, skip:
    2525                if ( 0 == init.size() ) {
     
    2929                // Create compound statement, move initializers outside,
    3030                // the resut of the original stays as is.
    31                 CompoundStmt * block = new CompoundStmt();
    32                 std::list<Statement *> & stmts = block->get_kids();
     31                CompoundStmt *block = new CompoundStmt();
     32                std::list<Statement *> &stmts = block->get_kids();
    3333                stmts.splice( stmts.end(), init );
    3434
     
    3838        }
    3939
    40         Statement * ForExprMutator::postmutate( IfStmt * ifStmt ) {
     40        Statement *ForExprMutator::postmutate( IfStmt *ifStmt ) {
    4141                return hoist( ifStmt, ifStmt->initialization );
    4242        }
    43         Statement * ForExprMutator::postmutate( ForStmt * forStmt ) {
     43        Statement *ForExprMutator::postmutate( ForStmt *forStmt ) {
    4444                // hoist any initializer declarations to make them C89 (rather than C99)
    4545                return hoist( forStmt, forStmt->initialization );
    4646        }
    47         Statement * ForExprMutator::postmutate( WhileStmt * whileStmt ) {
     47        Statement *ForExprMutator::postmutate( WhileStmt *whileStmt ) {
    4848                return hoist( whileStmt, whileStmt->initialization );
    4949        }
  • src/ControlStruct/LabelFixer.cc

    rb067d9b r7951100  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 11 22:26:02 2019
    13 // Update Count     : 159
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Tue Jul 28 13:32:43 2015
     13// Update Count     : 156
    1414//
    1515
     
    3232        }
    3333
    34         LabelFixer::LabelFixer( LabelGenerator * gen ) : generator ( gen ) {
     34        LabelFixer::LabelFixer( LabelGenerator *gen ) : generator ( gen ) {
    3535                if ( generator == 0 )
    3636                        generator = LabelGenerator::getGenerator();
     
    4949
    5050        // prune to at most one label definition for each statement
    51         void LabelFixer::previsit( Statement * stmt ) {
     51        void LabelFixer::previsit( Statement *stmt ) {
    5252                std::list< Label > &labels = stmt->get_labels();
    5353
     
    5858        }
    5959
    60         void LabelFixer::previsit( BranchStmt * branchStmt ) {
     60        void LabelFixer::previsit( BranchStmt *branchStmt ) {
    6161                previsit( ( Statement *)branchStmt );
    6262
     
    7575
    7676
    77         // sets the definition of the labelTable entry to be the provided statement for every label in the list
    78         // parameter. Happens for every kind of statement
    79         Label LabelFixer::setLabelsDef( std::list< Label > & llabel, Statement * definition ) {
     77        // sets the definition of the labelTable entry to be the provided
     78        // statement for every label in the list parameter. Happens for every kind of statement
     79        Label LabelFixer::setLabelsDef( std::list< Label > &llabel, Statement *definition ) {
    8080                assert( definition != 0 );
    8181                assert( llabel.size() > 0 );
     
    100100                } // for
    101101
    102                 // produce one of the labels attached to this statement to be temporarily used as the canonical label
     102                // produce one of the labels attached to this statement to be
     103                // temporarily used as the canonical label
    103104                return labelTable[ llabel.front() ]->get_label();
    104105        }
     
    116117
    117118        // Builds a table that maps a label to its defining statement.
    118         std::map<Label, Statement * > * LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
     119        std::map<Label, Statement * > *LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
    119120                std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
    120121                for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
  • src/ControlStruct/LabelGenerator.cc

    rb067d9b r7951100  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 11 22:23:20 2019
    13 // Update Count     : 15
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Aug 14 14:14:00 2015
     13// Update Count     : 14
    1414//
    1515
     
    2424
    2525namespace ControlStruct {
    26         LabelGenerator * LabelGenerator::labelGenerator = 0;
     26        LabelGenerator *LabelGenerator::labelGenerator = 0;
    2727
    28         LabelGenerator * LabelGenerator::getGenerator() {
     28        LabelGenerator *LabelGenerator::getGenerator() {
    2929                if ( LabelGenerator::labelGenerator == 0 )
    3030                        LabelGenerator::labelGenerator = new LabelGenerator();
     31
    3132                return labelGenerator;
    3233        }
     
    3738                if ( stmt && ! stmt->get_labels().empty() ) {
    3839                        os << "_" << stmt->get_labels().front() << "__";
    39                 } // if
     40                }
    4041                std::string ret = os.str();
    4142                Label l( ret );
  • src/ControlStruct/MLEMutator.cc

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct 22 17:22:44 2019
    13 // Update Count     : 220
     12// Last Modified On : Thu Mar  8 17:08:25 2018
     13// Update Count     : 219
    1414//
    1515
     
    313313        }
    314314
    315         void MLEMutator::premutate( TryStmt * tryStmt ) {
    316                 // generate a label for breaking out of a labeled if
    317                 bool labeledBlock = !(tryStmt->get_labels().empty());
    318                 if ( labeledBlock ) {
    319                         Label brkLabel = generator->newLabel("blockBreak", tryStmt);
    320                         enclosingControlStructures.push_back( Entry( tryStmt, brkLabel ) );
    321                         GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
    322                 } // if
    323         }
    324 
    325         Statement * MLEMutator::postmutate( TryStmt * tryStmt ) {
    326                 bool labeledBlock = !(tryStmt->get_labels().empty());
    327                 if ( labeledBlock ) {
    328                         if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
    329                                 set_breakLabel( enclosingControlStructures.back().useBreakExit() );
    330                         } // if
    331                 } // if
    332                 return tryStmt;
    333         }
    334 
    335315        void MLEMutator::premutate( CaseStmt *caseStmt ) {
    336316                visit_children = false;
  • src/ControlStruct/MLEMutator.h

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct 22 17:22:47 2019
    13 // Update Count     : 45
     12// Last Modified On : Thu Mar  8 16:42:32 2018
     13// Update Count     : 41
    1414//
    1515
     
    4747                void premutate( SwitchStmt *switchStmt );
    4848                Statement * postmutate( SwitchStmt *switchStmt );
    49                 void premutate( TryStmt *tryStmt );
    50                 Statement * postmutate( TryStmt *tryStmt );
    5149
    5250                Statement *mutateLoop( Statement *bodyLoop, Entry &e );
     
    7573                        explicit Entry( SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) :
    7674                                stmt( stmt ), breakExit( breakExit ), fallDefaultExit( fallDefaultExit ) {}
    77 
    78                         explicit Entry( TryStmt *stmt, Label breakExit ) :
    79                                 stmt( stmt ), breakExit( breakExit ) {}
    8075
    8176                        bool operator==( const Statement *other ) { return stmt == other; }
  • src/ControlStruct/module.mk

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 SRC_CONTROLSTRUCT = \
     17SRC +=  ControlStruct/LabelGenerator.cc \
     18        ControlStruct/LabelFixer.cc \
     19        ControlStruct/MLEMutator.cc \
     20        ControlStruct/Mutate.cc \
    1821        ControlStruct/ForExprMutator.cc \
    19         ControlStruct/LabelFixer.cc \
    20         ControlStruct/LabelGenerator.cc \
    21         ControlStruct/MLEMutator.cc \
    22         ControlStruct/Mutate.cc
    23 
    24 SRC += $(SRC_CONTROLSTRUCT) ControlStruct/ExceptTranslate.cc
    25 SRCDEMANGLE += $(SRC_CONTROLSTRUCT)
    26 
     22        ControlStruct/ExceptTranslate.cc
  • src/GenPoly/Box.cc

    rb067d9b r7951100  
    7676
    7777                /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
    78                 class Pass1 final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
     78                class Pass1 final : public BoxPass, public WithTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
    7979                  public:
    8080                        Pass1();
     
    150150                /// * Calculates polymorphic offsetof expressions from offset array
    151151                /// * Inserts dynamic calculation of polymorphic type layouts where needed
    152                 class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithConstTypeSubstitution {
     152                class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithTypeSubstitution {
    153153                public:
    154154                        PolyGenericCalculator();
     
    657657                                paramExpr = new AddressExpr( paramExpr );
    658658                        } // if
    659                         arg = appExpr->args.insert( arg, paramExpr ); // add argument to function call
     659                        arg = appExpr->get_args().insert( arg, paramExpr ); // add argument to function call
    660660                        arg++;
    661661                        // Build a comma expression to call the function and emulate a normal return.
    662662                        CommaExpr *commaExpr = new CommaExpr( appExpr, retExpr );
    663                         commaExpr->env = appExpr->env;
    664                         appExpr->env = nullptr;
     663                        commaExpr->set_env( appExpr->get_env() );
     664                        appExpr->set_env( 0 );
    665665                        return commaExpr;
    666666                }
     
    708708//                      if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
    709709                        if ( isDynRet( function, tyVars ) ) {
    710                                 ret = addRetParam( appExpr, function->returnVals.front()->get_type(), arg );
     710                                ret = addRetParam( appExpr, function->get_returnVals().front()->get_type(), arg );
    711711                        } // if
    712712                        std::string mangleName = mangleAdapterName( function, tyVars );
     
    715715                        // cast adaptee to void (*)(), since it may have any type inside a polymorphic function
    716716                        Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
    717                         appExpr->get_args().push_front( new CastExpr( appExpr->function, adapteeType ) );
     717                        appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
    718718                        appExpr->set_function( new NameExpr( adapterName ) ); // xxx - result is never set on NameExpr
    719719
     
    725725                        if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
    726726
    727                         if ( arg->get_lvalue() ) {
     727                        if ( arg->result->get_lvalue() ) {
    728728                                // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
    729729                                // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
     
    798798                        for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
    799799                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) {
    800                                         InferredParams::const_iterator inferParam = appExpr->inferParams.find( (*assert)->get_uniqueId() );
    801                                         assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );
     800                                        InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
     801                                        assertf( inferParam != appExpr->get_inferParams().end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );
    802802                                        Expression *newExpr = inferParam->second.expr->clone();
    803803                                        addCast( newExpr, (*assert)->get_type(), tyVars );
     
    837837                                        deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
    838838                                        deref->result = arg->get_type()->clone();
     839                                        deref->result->set_lvalue( true );
    839840                                        return deref;
    840841                                } // if
     
    17631764
    17641765                Expression *PolyGenericCalculator::postmutate( SizeofExpr *sizeofExpr ) {
    1765                         Type *ty = sizeofExpr->get_isType() ?
     1766                        Type *ty = sizeofExpr->get_isType() ? 
    17661767                                sizeofExpr->get_type() : sizeofExpr->get_expr()->get_result();
    1767 
     1768                       
    17681769                        Expression * gen = genSizeof( ty );
    17691770                        if ( gen ) {
  • src/GenPoly/GenPoly.cc

    rb067d9b r7951100  
    2424#include <vector>                       // for vector
    2525
    26 #include "AST/Type.hpp"
    2726#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2827#include "ResolvExpr/typeops.h"         // for flatten
     
    263262                } else {
    264263                        return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
    265                 }
    266         }
    267 
    268         const ast::FunctionType * getFunctionType( const ast::Type * ty ) {
    269                 if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) {
    270                         return pty->base.as< ast::FunctionType >();
    271                 } else {
    272                         return dynamic_cast< const ast::FunctionType * >( ty );
    273264                }
    274265        }
     
    449440        }
    450441
    451         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
     442        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env ) {
    452443                // is parameter is not polymorphic, don't need to box
    453444                if ( ! isPolyType( param, exprTyVars ) ) return false;
     
    459450        }
    460451
    461         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
     452        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env ) {
    462453                FunctionType * function = getFunctionType( appExpr->function->result );
    463454                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
     
    468459
    469460        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    470                 tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );
     461                // xxx - should this actually be insert?
     462                tyVarMap[ tyVar->get_name() ] = TypeDecl::Data{ tyVar };
    471463        }
    472464
  • src/GenPoly/GenPoly.h

    rb067d9b r7951100  
    2020
    2121#include "ErasableScopedMap.h"    // for ErasableScopedMap
    22 #include "AST/Fwd.hpp"
    2322#include "SymTab/Mangler.h"       // for Mangler
    2423#include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
     
    7372        /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
    7473        FunctionType *getFunctionType( Type *ty );
    75         const ast::FunctionType * getFunctionType( const ast::Type * ty );
    7674
    7775        /// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;
     
    8381
    8482        /// true if arg requires boxing given exprTyVars
    85         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );
     83        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env );
    8684
    8785        /// true if arg requires boxing in the call to appExpr
    88         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );
     86        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env );
    8987
    9088        /// Adds the type variable `tyVar` to `tyVarMap`
  • src/GenPoly/InstantiateGeneric.cc

    rb067d9b r7951100  
    168168
    169169        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
    170         struct GenericInstantiator final : public WithConstTypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards {
     170        struct GenericInstantiator final : public WithTypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards {
    171171                /// Map of (generic type, parameter list) pairs to concrete type instantiations
    172172                InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
  • src/GenPoly/Lvalue.cc

    rb067d9b r7951100  
    2121#include "Lvalue.h"
    2222
    23 #include "InitTweak/InitTweak.h"
    2423#include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
    2524#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2625#include "ResolvExpr/Unify.h"            // for unify
    2726#include "ResolvExpr/typeops.h"
     27#include "SymTab/Autogen.h"
    2828#include "SymTab/Indexer.h"              // for Indexer
    2929#include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
     
    3333#include "SynTree/Type.h"                // for PointerType, Type, FunctionType
    3434#include "SynTree/Visitor.h"             // for Visitor, acceptAll
    35 #include "Validate/FindSpecialDecls.h"   // for dereferenceOperator
    3635
    3736#if 0
     
    4544                // TODO: fold this into the general createDeref function??
    4645                Expression * mkDeref( Expression * arg ) {
    47                         if ( Validate::dereferenceOperator ) {
     46                        if ( SymTab::dereferenceOperator ) {
    4847                                // note: reference depth can be arbitrarily deep here, so peel off the outermost pointer/reference, not just pointer because they are effecitvely equivalent in this pass
    49                                 VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator );
     48                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
    5049                                deref->result = new PointerType( Type::Qualifiers(), deref->result );
    5150                                Type * base = InitTweak::getPointerBase( arg->result );
     
    5453                                delete ret->result;
    5554                                ret->result = base->clone();
     55                                ret->result->set_lvalue( true );
    5656                                return ret;
    5757                        } else {
     
    146146
    147147        namespace {
    148                 // true for intrinsic function calls that return an lvalue in C
     148                // true for intrinsic function calls that return a reference
    149149                bool isIntrinsicReference( Expression * expr ) {
    150                         // known intrinsic-reference prelude functions
    151                         static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    152150                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    153151                                std::string fname = InitTweak::getFunctionName( untyped );
    154                                 return lvalueFunctions.count(fname);
     152                                // known intrinsic-reference prelude functions
     153                                return fname == "*?" || fname == "?[?]";
    155154                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    156155                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    157                                         return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
     156                                        // use type of return variable rather than expr result type, since it may have been changed to a pointer type
     157                                        FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
     158                                        Type * ret = ftype->returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type();
     159                                        return func->linkage == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
    158160                                }
    159161                        }
     
    166168                                ReferenceType * result = strict_dynamic_cast< ReferenceType * >( appExpr->result );
    167169                                appExpr->result = result->base->clone();
     170                                appExpr->result->set_lvalue( true );
    168171                                if ( ! inIntrinsic ) {
    169172                                        // when not in an intrinsic function, add a cast to
     
    194197                                unsigned int i = 0;
    195198                                const unsigned int end = ftype->parameters.size();
    196 
    197                                 /// The for loop may eagerly dereference the iterators and fail on empty lists
    198                                 if(i == end) { return appExpr; }
    199199                                for ( auto p : unsafe_group_iterate( appExpr->args, ftype->parameters ) ) {
     200                                        if (i == end) break;
    200201                                        Expression *& arg = std::get<0>( p );
    201202                                        Type * formal = std::get<1>( p )->get_type();
     
    211212                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
    212213
    213                                                 if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
     214                                                if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    214215                                                        // needed for definition of prelude functions, etc.
    215216                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     
    227228                                                        arg = new AddressExpr( arg );
    228229                                                // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
    229                                                 } else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
     230                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    230231                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
    231232                                                        PRINT(
     
    242243                                        }
    243244                                        ++i;
    244                                         if (i == end) break;
    245245                                }
    246246                        }
     
    355355                        Type * destType = castExpr->result;
    356356                        Type * srcType = castExpr->arg->result;
    357                         assertf( destType, "Cast to no type in: %s", toCString( castExpr ) );
    358                         assertf( srcType, "Cast from no type in: %s", toCString( castExpr ) );
    359357                        int depth1 = destType->referenceDepth();
    360358                        int depth2 = srcType->referenceDepth();
    361359                        int diff = depth1 - depth2;
    362360
    363                         if ( diff > 0 && ! castExpr->arg->get_lvalue() ) {
     361                        if ( diff > 0 && ! srcType->get_lvalue() ) {
    364362                                // rvalue to reference conversion -- introduce temporary
    365363                                // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g.
     
    405403                                        ret = new AddressExpr( ret );
    406404                                }
    407                                 if ( castExpr->arg->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
     405                                if ( srcType->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
    408406                                        // must keep cast if cast-to type is different from the actual type
    409407                                        castExpr->arg = ret;
     
    434432                                delete ret->result;
    435433                                ret->result = castExpr->result;
    436                                 assert( ret->get_lvalue() ); // ensure result is lvalue
     434                                ret->result->set_lvalue( true ); // ensure result is lvalue
    437435                                castExpr->env = nullptr;
    438436                                castExpr->arg = nullptr;
  • src/GenPoly/ScopedSet.h

    rb067d9b r7951100  
    3838                typedef typename Scope::pointer pointer;
    3939                typedef typename Scope::const_pointer const_pointer;
    40 
     40               
    4141                class iterator : public std::iterator< std::bidirectional_iterator_tag,
    4242                                                       value_type > {
     
    7272                                return *this;
    7373                        }
    74 
     74                       
    7575                        reference operator* () { return *it; }
    7676                        pointer operator-> () { return it.operator->(); }
     
    104104                        bool operator!= (const iterator &that) { return !( *this == that ); }
    105105
    106                         size_type get_level() const { return i; }
    107 
    108106                private:
    109107                        scope_list const *scopes;
     
    182180                        bool operator!= (const const_iterator &that) { return !( *this == that ); }
    183181
    184                         size_type get_level() const { return i; }
    185 
    186182                private:
    187183                        scope_list const *scopes;
     
    189185                        size_type i;
    190186                };
    191 
     187               
    192188                /// Starts a new scope
    193189                void beginScope() {
     
    226222                        return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
    227223                }
    228 
     224               
    229225                /// Finds the given key in the outermost scope inside the given scope where it occurs
    230226                iterator findNext( const_iterator &it, const Value &key ) {
     
    246242                        return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
    247243                }
    248 
     244               
    249245        };
    250246} // namespace GenPoly
  • src/GenPoly/ScrubTyVars.cc

    rb067d9b r7951100  
    5050                                delete typeInst;
    5151                                return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
    52                           default:
    53                                 assertf(false, "Unhandled tyvar kind: %d", tyVar->second.kind);
    5452                        } // switch
    5553                } // if
  • src/GenPoly/Specialize.cc

    rb067d9b r7951100  
    4242
    4343namespace GenPoly {
    44         struct Specialize final : public WithConstTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
     44        struct Specialize final : public WithTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
    4545                Expression * postmutate( ApplicationExpr *applicationExpr );
    4646                Expression * postmutate( CastExpr *castExpr );
     
    5454
    5555        /// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type.
    56         bool needsPolySpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) {
     56        bool needsPolySpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    5757                if ( env ) {
    5858                        using namespace ResolvExpr;
     
    145145        }
    146146
    147         bool needsSpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) {
     147        bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    148148                return needsPolySpecialization( formalType, actualType, env ) || needsTupleSpecialization( formalType, actualType );
    149149        }
     
    245245                appExpr->env = TypeSubstitution::newFromExpr( appExpr, env );
    246246                if ( inferParams ) {
    247                         appExpr->inferParams = *inferParams;
     247                        appExpr->get_inferParams() = *inferParams;
    248248                } // if
    249249
     
    284284                std::list< Expression* >::iterator actual;
    285285                for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) {
    286                         *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->inferParams );
     286                        *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->get_inferParams() );
    287287                }
    288288        }
     
    295295                        // alternatively, if order starts to matter then copy appExpr's inferParams and pass them to handleExplicitParams.
    296296                        handleExplicitParams( appExpr );
    297                         for ( InferredParams::iterator inferParam = appExpr->inferParams.begin(); inferParam != appExpr->inferParams.end(); ++inferParam ) {
    298                                 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &inferParam->second.expr->inferParams );
     297                        for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
     298                                inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, inferParam->second.inferParams.get() );
    299299                        }
    300300                }
  • src/GenPoly/module.mk

    rb067d9b r7951100  
    2222       GenPoly/FindFunction.cc \
    2323       GenPoly/InstantiateGeneric.cc
    24 
    25 SRCDEMANGLE += GenPoly/GenPoly.cc GenPoly/Lvalue.cc
    26 
  • src/InitTweak/FixGlobalInit.cc

    rb067d9b r7951100  
    3737        class GlobalFixer : public WithShortCircuiting {
    3838          public:
    39                 GlobalFixer( bool inLibrary );
     39                GlobalFixer( const std::string & name, bool inLibrary );
    4040
    4141                void previsit( ObjectDecl *objDecl );
     
    5252        };
    5353
    54         void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ) {
    55                 PassVisitor<GlobalFixer> visitor( inLibrary );
     54        void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
     55                PassVisitor<GlobalFixer> visitor( name, inLibrary );
    5656                acceptAll( translationUnit, visitor );
    5757                GlobalFixer & fixer = visitor.pass;
     
    7070        }
    7171
    72         GlobalFixer::GlobalFixer( bool inLibrary ) : tempNamer( "_global_init" ) {
     72  std::string globalFunctionName( const std::string & name ) {
     73        // get basename
     74        std::string ret = name.substr( 0, name.find( '.' ) );
     75        // replace invalid characters with _
     76                static std::string invalid = "/-";
     77        replace_if( ret.begin(), ret.end(), []( char c ) { return invalid.find(c) != std::string::npos; }, '_' );
     78        return ret;
     79  }
     80
     81        GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) {
     82                std::string fixedName = globalFunctionName( name );
    7383                std::list< Expression * > ctorParameters;
    7484                std::list< Expression * > dtorParameters;
     
    8090                        // for library code are run before constructors and destructors for user code,
    8191                        // specify a priority when building the library. Priorities 0-100 are reserved by gcc.
    82                         // Priorities 101-200 are reserved by cfa, so use priority 200 for CFA library globals,
    83                         // allowing room for overriding with a higher priority.
    84                         ctorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
    85                         dtorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
     92                        ctorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) );
     93                        dtorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) );
    8694                }
    87                 initFunction = new FunctionDecl( "__global_init__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     95                initFunction = new FunctionDecl( "_init_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    8896                initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
    89                 destroyFunction = new FunctionDecl( "__global_destroy__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     97                destroyFunction = new FunctionDecl( "_destroy_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    9098                destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
    9199        }
     
    102110                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    103111                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    104                         assert( ! ctorInit->ctor || ! ctorInit->init );
     112                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    105113
    106                         Statement * dtor = ctorInit->dtor;
     114                        Statement * dtor = ctorInit->get_dtor();
    107115                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    108116                                // don't need to call intrinsic dtor, because it does nothing, but
    109117                                // non-intrinsic dtors must be called
    110118                                destroyStatements.push_front( dtor );
    111                                 ctorInit->dtor = nullptr;
     119                                ctorInit->set_dtor( NULL );
    112120                        } // if
    113                         if ( Statement * ctor = ctorInit->ctor ) {
     121                        if ( Statement * ctor = ctorInit->get_ctor() ) {
    114122                                initStatements.push_back( ctor );
    115                                 objDecl->init = nullptr;
    116                                 ctorInit->ctor = nullptr;
    117                         } else if ( Initializer * init = ctorInit->init ) {
    118                                 objDecl->init = init;
    119                                 ctorInit->init = nullptr;
     123                                objDecl->set_init( NULL );
     124                                ctorInit->set_ctor( NULL );
     125                        } else if ( Initializer * init = ctorInit->get_init() ) {
     126                                objDecl->set_init( init );
     127                                ctorInit->set_init( NULL );
    120128                        } else {
    121129                                // no constructor and no initializer, which is okay
    122                                 objDecl->init = nullptr;
     130                                objDecl->set_init( NULL );
    123131                        } // if
    124132                        delete ctorInit;
  • src/InitTweak/FixGlobalInit.h

    rb067d9b r7951100  
    2222
    2323namespace InitTweak {
    24         /// Moves global initialization into an _init function that is unique to the translation unit.
    25         /// Sets the priority of the initialization function depending on whether the initialization
    26         /// function is for library code.
    27         void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary );
     24  /// Moves global initialization into an _init function that is unique to the translation unit.
     25  /// Sets the priority of the initialization function depending on whether the initialization
     26  /// function is for library code.
     27  void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
     28
     29  /// Apply transformations to a file name to get a valid C identifier which will be used as
     30  /// the name of the generated initializer function.
     31  std::string globalFunctionName( const std::string & name );
    2832} // namespace
    2933
  • src/InitTweak/FixInit.cc

    rb067d9b r7951100  
    1010// Created On       : Wed Jan 13 16:29:30 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 13 18:15:56 2019
    13 // Update Count     : 76
     12// Last Modified On : Wed Jun 21 17:35:05 2017
     13// Update Count     : 74
    1414//
    1515#include "FixInit.h"
     
    5454#include "SynTree/Type.h"              // for Type, Type::StorageClasses
    5555#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    56 #include "SynTree/DeclReplacer.h"      // for DeclReplacer
    5756#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    58 #include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy
    5957
    6058bool ctordtorp = false; // print all debug
     
    6866namespace InitTweak {
    6967        namespace {
     68                typedef std::unordered_map< int, int > UnqCount;
     69
    7070                struct SelfAssignChecker {
    7171                        void previsit( ApplicationExpr * appExpr );
    7272                };
    7373
    74                 struct StmtExprResult {
    75                         static void link( std::list< Declaration * > & translationUnit );
    76 
    77                         void previsit( StmtExpr * stmtExpr );
    78                 };
    79 
    80                 struct InsertImplicitCalls : public WithConstTypeSubstitution {
     74                struct InsertImplicitCalls : public WithTypeSubstitution {
    8175                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
    8276                        /// function calls need their parameters to be copy constructed
     
    8680                };
    8781
    88                 struct ResolveCopyCtors final : public WithStmtsToAdd, public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution, public WithVisitorRef<ResolveCopyCtors> {
     82                struct ResolveCopyCtors final : public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution {
    8983                        /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
    9084                        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
    9185                        /// arguments and return value temporaries
    92                         static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
    93 
    94                         Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
    95                         void premutate( StmtExpr * stmtExpr );
    96                         void premutate( UniqueExpr * unqExpr );
     86                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount );
     87
     88                        ResolveCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ) {}
     89
     90                        void postvisit( ImplicitCopyCtorExpr * impCpCtorExpr );
     91                        void postvisit( StmtExpr * stmtExpr );
     92                        void previsit( UniqueExpr * unqExpr );
     93                        void postvisit( UniqueExpr * unqExpr );
    9794
    9895                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
     
    10198                        bool skipCopyConstruct( Type * type );
    10299                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
    103                         void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr, Expression *& arg );
     100                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
     101
     102                        UnqCount & unqCount; // count the number of times each unique expr ID appears
     103                        std::unordered_set< int > vars;
    104104                };
    105105
     
    162162                        using Parent::previsit;
    163163
     164                        void previsit( ObjectDecl * objDecl );
    164165                        void previsit( FunctionDecl * funcDecl );
    165166
     167                        void previsit( CompoundStmt * compoundStmt );
     168                        void postvisit( CompoundStmt * compoundStmt );
     169                        void previsit( ReturnStmt * returnStmt );
    166170                        void previsit( BranchStmt * stmt );
    167171                private:
     
    181185
    182186                        std::list< Declaration * > staticDtorDecls;
     187                };
     188
     189                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution {
     190                  public:
     191                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     192                        /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression,
     193                        /// and destructors
     194                        static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
     195
     196                        Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     197                        void premutate( StmtExpr * stmtExpr );
     198                        void premutate( UniqueExpr * unqExpr );
     199
     200                        UnqCount & unqCount;
    183201                };
    184202
     
    218236                        Expression * postmutate( ConstructorExpr * ctorExpr );
    219237                };
    220 
    221                 struct SplitExpressions : public WithShortCircuiting, public WithTypeSubstitution, public WithStmtsToAdd {
    222                         /// add CompoundStmts around top-level expressions so that temporaries are destroyed in the correct places.
    223                         static void split( std::list< Declaration * > &translationUnit );
    224 
    225                         Statement * postmutate( ExprStmt * stmt );
    226                         void premutate( TupleAssignExpr * expr );
    227                 };
    228238        } // namespace
    229239
    230         void fix( std::list< Declaration * > & translationUnit, bool inLibrary ) {
     240        void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
    231241                PassVisitor<SelfAssignChecker> checker;
    232242                acceptAll( translationUnit, checker );
    233243
    234                 // fixes StmtExpr to properly link to their resulting expression
    235                 StmtExprResult::link( translationUnit );
    236 
    237244                // fixes ConstructorInit for global variables. should happen before fixInitializers.
    238                 InitTweak::fixGlobalInit( translationUnit, inLibrary );
    239 
    240                 // must happen before ResolveCopyCtors because temporaries have to be inserted into the correct scope
    241                 SplitExpressions::split( translationUnit );
     245                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     246
     247                UnqCount unqCount;
    242248
    243249                InsertImplicitCalls::insert( translationUnit );
    244 
    245                 // Needs to happen before ResolveCopyCtors, because argument/return temporaries should not be considered in
    246                 // error checking branch statements
     250                ResolveCopyCtors::resolveImplicitCalls( translationUnit, unqCount );
    247251                InsertDtors::insert( translationUnit );
    248 
    249                 ResolveCopyCtors::resolveImplicitCalls( translationUnit );
    250252                FixInit::fixInitializers( translationUnit );
     253
     254                // FixCopyCtors must happen after FixInit, so that destructors are placed correctly
     255                FixCopyCtors::fixCopyCtors( translationUnit, unqCount );
     256
    251257                GenStructMemberCalls::generate( translationUnit );
    252258
    253                 // Needs to happen after GenStructMemberCalls, since otherwise member constructors exprs
    254                 // don't have the correct form, and a member can be constructed more than once.
     259                // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a
     260                // hack in the way untyped assignments are generated, where the first argument cannot have
     261                // its address taken because of the way codegeneration handles UntypedExpr vs. ApplicationExpr.
     262                // Thus such assignment exprs must never pushed through expression resolution (and thus should
     263                // not go through the FixCopyCtors pass), otherwise they will fail -- guaranteed.
     264                // Also needs to happen after GenStructMemberCalls, since otherwise member constructors exprs
     265                // don't look right, and a member can be constructed more than once.
    255266                FixCtorExprs::fix( translationUnit );
    256267        }
    257268
    258269        namespace {
    259                 /// find and return the destructor used in `input`. If `input` is not a simple destructor call, generate a thunk
    260                 /// that wraps the destructor, insert it into `stmtsToAdd` and return the new function declaration
    261                 DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * input, std::list< Statement * > & stmtsToAdd ) {
    262                         // unwrap implicit statement wrapper
    263                         Statement * dtor = input;
    264                         assert( dtor );
    265                         std::list< Expression * > matches;
    266                         collectCtorDtorCalls( dtor, matches );
    267 
    268                         if ( dynamic_cast< ExprStmt * >( dtor ) ) {
    269                                 // only one destructor call in the expression
    270                                 if ( matches.size() == 1 ) {
    271                                         DeclarationWithType * func = getFunction( matches.front() );
    272                                         assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );
    273 
    274                                         // cleanup argument must be a function, not an object (including function pointer)
    275                                         if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) {
    276                                                 if ( dtorFunc->type->forall.empty() ) {
    277                                                         // simple case where the destructor is a monomorphic function call - can simply
    278                                                         // use that function as the cleanup function.
    279                                                         delete dtor;
    280                                                         return func;
    281                                                 }
    282                                         }
    283                                 }
    284                         }
    285 
    286                         // otherwise the cleanup is more complicated - need to build a single argument cleanup function that
    287                         // wraps the more complicated code.
    288                         static UniqueName dtorNamer( "__cleanup_dtor" );
    289                         std::string name = dtorNamer.newName();
    290                         FunctionDecl * dtorFunc = FunctionDecl::newFunction( name, SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() );
    291                         stmtsToAdd.push_back( new DeclStmt( dtorFunc ) );
    292 
    293                         // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter.
    294                         ObjectDecl * thisParam = getParamThis( dtorFunc->type );
    295                         Expression * replacement = new VariableExpr( thisParam );
    296 
    297                         Type * base = replacement->result->stripReferences();
    298                         if ( dynamic_cast< ArrayType * >( base ) || dynamic_cast< TupleType * > ( base ) ) {
    299                                 // need to cast away reference for array types, since the destructor is generated without the reference type,
    300                                 // and for tuple types since tuple indexing does not work directly on a reference
    301                                 replacement = new CastExpr( replacement, base->clone() );
    302                         }
    303                         DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
    304                         dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) );
    305 
    306                         return dtorFunc;
    307                 }
    308 
    309                 void StmtExprResult::link( std::list< Declaration * > & translationUnit ) {
    310                         PassVisitor<StmtExprResult> linker;
    311                         acceptAll( translationUnit, linker );
    312                 }
    313 
    314                 void SplitExpressions::split( std::list< Declaration * > & translationUnit ) {
    315                         PassVisitor<SplitExpressions> splitter;
    316                         mutateAll( translationUnit, splitter );
    317                 }
    318 
    319270                void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {
    320271                        PassVisitor<InsertImplicitCalls> inserter;
     
    322273                }
    323274
    324                 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) {
    325                         PassVisitor<ResolveCopyCtors> resolver;
    326                         mutateAll( translationUnit, resolver );
     275                void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
     276                        PassVisitor<ResolveCopyCtors> resolver( unqCount );
     277                        acceptAll( translationUnit, resolver );
    327278                }
    328279
     
    352303                }
    353304
     305                void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
     306                        PassVisitor<FixCopyCtors> fixer( unqCount );
     307                        mutateAll( translationUnit, fixer );
     308                }
     309
    354310                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    355311                        PassVisitor<GenStructMemberCalls> warner;
     
    362318                }
    363319
    364                 void StmtExprResult::previsit( StmtExpr * stmtExpr ) {
    365                         // we might loose the result expression here so add a pointer to trace back
    366                         assert( stmtExpr->result );
    367                         Type * result = stmtExpr->result;
    368                         if ( ! result->isVoid() ) {
    369                                 CompoundStmt * body = stmtExpr->statements;
    370                                 assert( ! body->kids.empty() );
    371                                 stmtExpr->resultExpr = strict_dynamic_cast< ExprStmt * >( body->kids.back() );
    372                         }
    373                 }
    374 
    375                 Statement * SplitExpressions::postmutate( ExprStmt * stmt ) {
    376                         // wrap each top-level ExprStmt in a block so that destructors for argument and return temporaries are destroyed
    377                         // in the correct places
    378                         CompoundStmt * ret = new CompoundStmt( { stmt } );
    379                         return ret;
    380                 }
    381 
    382                 void SplitExpressions::premutate( TupleAssignExpr * ) {
    383                         // don't do this within TupleAssignExpr, since it is already broken up into multiple expressions
    384                         visit_children = false;
    385                 }
    386 
    387                 // Relatively simple structural comparison for expressions, needed to determine
    388                 // if two expressions are "the same" (used to determine if self assignment occurs)
    389                 struct StructuralChecker {
    390                         Expression * stripCasts( Expression * expr ) {
    391                                 // this might be too permissive. It's possible that only particular casts are relevant.
    392                                 while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) {
    393                                         expr = cast->arg;
    394                                 }
    395                                 return expr;
    396                         }
    397 
    398                         void previsit( Expression * ) {
    399                                 // anything else does not qualify
    400                                 isSimilar = false;
    401                         }
    402 
    403                         template<typename T>
    404                         T * cast( Expression * node ) {
    405                                 // all expressions need to ignore casts, so this bit has been factored out
    406                                 return dynamic_cast< T * >( stripCasts( node ) );
    407                         }
    408 
    409                         // ignore casts
    410                         void previsit( CastExpr * ) {}
    411 
    412                         void previsit( MemberExpr * memExpr ) {
    413                                 if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) {
    414                                         if ( otherMember->member == memExpr->member ) {
    415                                                 other = otherMember->aggregate;
     320                namespace {
     321                        // Relatively simple structural comparison for expressions, needed to determine
     322                        // if two expressions are "the same" (used to determine if self assignment occurs)
     323                        struct StructuralChecker {
     324                                Expression * stripCasts( Expression * expr ) {
     325                                        // this might be too permissive. It's possible that only particular casts are relevant.
     326                                        while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) {
     327                                                expr = cast->arg;
     328                                        }
     329                                        return expr;
     330                                }
     331
     332                                void previsit( Expression * ) {
     333                                        // anything else does not qualify
     334                                        isSimilar = false;
     335                                }
     336
     337                                template<typename T>
     338                                T * cast( Expression * node ) {
     339                                        // all expressions need to ignore casts, so this bit has been factored out
     340                                        return dynamic_cast< T * >( stripCasts( node ) );
     341                                }
     342
     343                                // ignore casts
     344                                void previsit( CastExpr * ) {}
     345
     346                                void previsit( MemberExpr * memExpr ) {
     347                                        if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) {
     348                                                if ( otherMember->member == memExpr->member ) {
     349                                                        other = otherMember->aggregate;
     350                                                        return;
     351                                                }
     352                                        }
     353                                        isSimilar = false;
     354                                }
     355
     356                                void previsit( VariableExpr * varExpr ) {
     357                                        if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) {
     358                                                if ( otherVar->var == varExpr->var ) {
     359                                                        return;
     360                                                }
     361                                        }
     362                                        isSimilar = false;
     363                                }
     364
     365                                void previsit( AddressExpr * ) {
     366                                        if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) {
     367                                                other = addrExpr->arg;
    416368                                                return;
    417369                                        }
    418                                 }
    419                                 isSimilar = false;
    420                         }
    421 
    422                         void previsit( VariableExpr * varExpr ) {
    423                                 if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) {
    424                                         if ( otherVar->var == varExpr->var ) {
    425                                                 return;
    426                                         }
    427                                 }
    428                                 isSimilar = false;
    429                         }
    430 
    431                         void previsit( AddressExpr * ) {
    432                                 if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) {
    433                                         other = addrExpr->arg;
    434                                         return;
    435                                 }
    436                                 isSimilar = false;
    437                         }
    438 
    439                         Expression * other = nullptr;
    440                         bool isSimilar = true;
    441                 };
    442 
    443                 bool structurallySimilar( Expression * e1, Expression * e2 ) {
    444                         PassVisitor<StructuralChecker> checker;
    445                         checker.pass.other = e2;
    446                         e1->accept( checker );
    447                         return checker.pass.isSimilar;
     370                                        isSimilar = false;
     371                                }
     372
     373                                Expression * other = nullptr;
     374                                bool isSimilar = true;
     375                        };
     376
     377                        bool structurallySimilar( Expression * e1, Expression * e2 ) {
     378                                PassVisitor<StructuralChecker> checker;
     379                                checker.pass.other = e2;
     380                                e1->accept( checker );
     381                                return checker.pass.isSimilar;
     382                        }
    448383                }
    449384
     
    522457                        if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) {
    523458                                // fix newly generated StmtExpr
    524                                 premutate( assign->stmtExpr );
     459                                postvisit( assign->stmtExpr );
    525460                        }
    526461                        return resolved;
     
    554489                                        // so that the object isn't changed inside of the polymorphic function
    555490                                        if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
    556                                         // xxx - leaking tmp
    557491                                }
    558492                        }
     
    562496
    563497                        // replace argument to function call with temporary
    564                         stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
    565                         arg = cpCtor;
    566                         destructRet( tmp, impCpCtorExpr, arg );
    567 
    568                         // impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
    569                 }
    570 
    571                 void ResolveCopyCtors::destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * /*impCpCtorExpr*/, Expression *& arg ) {
    572                         // TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places
    573                         // check for existing cleanup attribute before adding another(?)
    574                         // need to add __Destructor for _tmp_cp variables as well
    575 
    576                         assertf( Validate::dtorStruct && Validate::dtorStruct->members.size() == 2, "Destructor generation requires __Destructor definition." );
    577                         assertf( Validate::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );
    578 
    579                         // generate a __Destructor for ret that calls the destructor
    580                         Expression * dtor = makeCtorDtor( "^?{}", ret );
    581 
    582                         // if the chosen destructor is intrinsic, elide the generated dtor handler
    583                         if ( arg && isIntrinsicCallExpr( dtor ) ) {
    584                                 arg = new CommaExpr( arg, new VariableExpr( ret ) );
    585                                 return;
    586                         }
    587 
    588                         if ( ! dtor->env ) dtor->env = maybeClone( env );
    589                         DeclarationWithType * dtorFunc = getDtorFunc( ret, new ExprStmt( dtor ), stmtsToAddBefore );
    590 
    591                         StructInstType * dtorStructType = new StructInstType( Type::Qualifiers(), Validate::dtorStruct );
    592                         dtorStructType->parameters.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
    593 
    594                         // cast destructor pointer to void (*)(void *), to silence GCC incompatible pointer warnings
    595                         FunctionType * dtorFtype = new FunctionType( Type::Qualifiers(), false );
    596                         dtorFtype->parameters.push_back( ObjectDecl::newObject( "", new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), nullptr ) );
    597                         Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
    598 
    599                         static UniqueName namer( "_ret_dtor" );
    600                         ObjectDecl * retDtor = ObjectDecl::newObject( namer.newName(), dtorStructType, new ListInit( { new SingleInit( new ConstantExpr( Constant::null() ) ), new SingleInit( new CastExpr( new VariableExpr( dtorFunc ), dtorType ) ) } ) );
    601                         retDtor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( Validate::dtorStructDestroy ) } ) );
    602                         stmtsToAddBefore.push_back( new DeclStmt( retDtor ) );
    603 
    604                         if ( arg ) {
    605                                 Expression * member = new MemberExpr( strict_dynamic_cast<DeclarationWithType *>( Validate::dtorStruct->members.front() ), new VariableExpr( retDtor ) );
    606                                 Expression * object = new CastExpr( new AddressExpr( new VariableExpr( ret ) ), new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ) );
    607                                 Expression * assign = createBitwiseAssignment( member, object );
    608                                 arg = new CommaExpr( new CommaExpr( arg, assign ), new VariableExpr( ret ) );
    609                         }
    610 
    611                         // impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
    612                 }
    613 
    614                 Expression * ResolveCopyCtors::postmutate( ImplicitCopyCtorExpr *impCpCtorExpr ) {
     498                        arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
     499                        impCpCtorExpr->tempDecls.push_back( tmp );
     500                        impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
     501                }
     502
     503                void ResolveCopyCtors::destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     504                        impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
     505                }
     506
     507                void ResolveCopyCtors::postvisit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
    615508                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    616509
    617510                        ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
    618                         ObjectDecl * returnDecl = nullptr;
    619511
    620512                        // take each argument and attempt to copy construct it.
     
    625517                        for ( Expression * & arg : appExpr->args ) {
    626518                                Type * formal = nullptr;
    627                                 if ( iter != params.end() ) { // does not copy construct C-style variadic arguments
     519                                if ( iter != params.end() ) {
    628520                                        DeclarationWithType * param = *iter++;
    629521                                        formal = param->get_type();
     
    643535                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    644536                                ret->type->set_const( false );
    645                                 returnDecl = ret;
    646                                 stmtsToAddBefore.push_back( new DeclStmt( ret ) );
     537                                impCpCtorExpr->returnDecls.push_back( ret );
    647538                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
     539                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
     540                                        // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
     541                                        destructRet( ret, impCpCtorExpr );
     542                                }
    648543                        } // for
    649544                        CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
    650                         // ------------------------------------------------------
    651 
    652                         CP_CTOR_PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; )
    653 
    654                         // detach fields from wrapper node so that it can be deleted without deleting too much
    655                         impCpCtorExpr->callExpr = nullptr;
    656                         std::swap( impCpCtorExpr->env, appExpr->env );
    657                         assert( impCpCtorExpr->env == nullptr );
    658                         delete impCpCtorExpr;
    659 
    660                         if ( returnDecl ) {
    661                                 Expression * assign = createBitwiseAssignment( new VariableExpr( returnDecl ), appExpr );
    662                                 if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    663                                         // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    664                                         destructRet( returnDecl, impCpCtorExpr, assign );
    665                                 } else {
    666                                         assign = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    667                                 }
    668                                 // move env from appExpr to retExpr
    669                                 std::swap( assign->env, appExpr->env );
    670                                 return assign;
    671                         } else {
    672                                 return appExpr;
    673                         } // if
    674                 }
    675 
    676                 void ResolveCopyCtors::premutate( StmtExpr * stmtExpr ) {
    677                         // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    678                         // since temporaries can be shared across sub-expressions, e.g.
    679                         //   [A, A] f();       // decl
    680                         //   g([A] x, [A] y);  // decl
    681                         //   g(f());           // call
    682                         // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
    683                         // Explicitly mutating children instead of mutating the inner compound statement forces the temporaries to be added
    684                         // to the outer context, rather than inside of the statement expression.
    685                         visit_children = false;
    686 
     545                }
     546
     547                void ResolveCopyCtors::postvisit( StmtExpr * stmtExpr ) {
    687548                        assert( env );
    688 
    689                         indexer.enterScope();
    690                         // visit all statements
    691                         std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
    692                         for ( Statement *& stmt : stmts ) {
    693                                 stmt = stmt->acceptMutator( *visitor );
    694                         } // for
    695                         indexer.leaveScope();
    696 
    697                         assert( stmtExpr->result );
    698                         Type * result = stmtExpr->result;
     549                        assert( stmtExpr->get_result() );
     550                        Type * result = stmtExpr->get_result();
    699551                        if ( ! result->isVoid() ) {
    700552                                static UniqueName retNamer("_tmp_stmtexpr_ret");
     
    710562                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    711563                                ret->type->set_const( false );
    712                                 stmtsToAddBefore.push_back( new DeclStmt( ret ) );
    713 
    714                                 assertf(
    715                                         stmtExpr->resultExpr,
    716                                         "Statement-Expression should have a resulting expression at %s:%d",
    717                                         stmtExpr->location.filename.c_str(),
    718                                         stmtExpr->location.first_line
    719                                 );
    720 
    721                                 ExprStmt * last = stmtExpr->resultExpr;
    722                                 try {
    723                                         last->expr = makeCtorDtor( "?{}", ret, last->expr );
    724                                 } catch(...) {
    725                                         std::cerr << "*CFA internal error: ";
    726                                         std::cerr << "can't resolve implicit constructor";
    727                                         std::cerr << " at " << stmtExpr->location.filename;
    728                                         std::cerr << ":" << stmtExpr->location.first_line << std::endl;
    729 
    730                                         abort();
    731                                 }
    732 
    733                                 // add destructors after current statement
    734                                 stmtsToAddAfter.push_back( new ExprStmt( makeCtorDtor( "^?{}", ret ) ) );
     564                                stmtExpr->returnDecls.push_front( ret );
    735565
    736566                                // must have a non-empty body, otherwise it wouldn't have a result
    737                                 assert( ! stmts.empty() );
    738 
    739                                 // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
    740                                 stmts.push_back( new ExprStmt( new VariableExpr( ret ) ) );
     567                                CompoundStmt * body = stmtExpr->statements;
     568                                assert( ! body->get_kids().empty() );
     569                                // must be an ExprStmt, otherwise it wouldn't have a result
     570                                ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->get_kids().back() );
     571                                last->expr = makeCtorDtor( "?{}", ret, last->get_expr() );
     572
     573                                stmtExpr->dtors.push_front( makeCtorDtor( "^?{}", ret ) );
    741574                        } // if
    742 
    743                         assert( stmtExpr->returnDecls.empty() );
    744                         assert( stmtExpr->dtors.empty() );
     575                }
     576
     577                void ResolveCopyCtors::previsit( UniqueExpr * unqExpr ) {
     578                        unqCount[ unqExpr->get_id() ]++;  // count the number of unique expressions for each ID
     579                        if ( vars.count( unqExpr->get_id() ) ) {
     580                                // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
     581                                visit_children = false;
     582                        }
    745583                }
    746584
     
    759597                }
    760598
    761                 void ResolveCopyCtors::premutate( UniqueExpr * unqExpr ) {
     599                void ResolveCopyCtors::postvisit( UniqueExpr * unqExpr ) {
     600                        if ( vars.count( unqExpr->get_id() ) ) {
     601                                // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
     602                                return;
     603                        }
     604
     605                        // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
     606                        assert( unqExpr->get_result() );
     607                        if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) {
     608                                // note the variable used as the result from the call
     609                                assert( impCpCtorExpr->get_result() && impCpCtorExpr->get_returnDecls().size() == 1 );
     610                                unqExpr->set_var( new VariableExpr( impCpCtorExpr->get_returnDecls().front() ) );
     611                        } else {
     612                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
     613                                unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), makeInit( unqExpr->get_result() ) ) );
     614                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
     615                        }
     616                        vars.insert( unqExpr->get_id() );
     617                }
     618
     619                Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     620                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
     621
     622                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
     623                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     624                        std::list< Expression * > & dtors = impCpCtorExpr->get_dtors();
     625
     626                        // add all temporary declarations and their constructors
     627                        for ( ObjectDecl * obj : tempDecls ) {
     628                                stmtsToAddBefore.push_back( new DeclStmt( obj ) );
     629                        } // for
     630                        for ( ObjectDecl * obj : returnDecls ) {
     631                                stmtsToAddBefore.push_back( new DeclStmt( obj ) );
     632                        } // for
     633
     634                        // add destructors after current statement
     635                        for ( Expression * dtor : dtors ) {
     636                                // take relevant bindings from environment
     637                                assert( ! dtor->env );
     638                                dtor->env =  maybeClone( env );
     639                                stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
     640                        } // for
     641
     642                        ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
     643                        Expression * callExpr = impCpCtorExpr->get_callExpr();
     644
     645                        CP_CTOR_PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; )
     646
     647                        // detach fields from wrapper node so that it can be deleted without deleting too much
     648                        dtors.clear();
     649                        tempDecls.clear();
     650                        returnDecls.clear();
     651                        impCpCtorExpr->set_callExpr( nullptr );
     652                        std::swap( impCpCtorExpr->env, callExpr->env );
     653                        assert( impCpCtorExpr->env == nullptr );
     654                        delete impCpCtorExpr;
     655
     656                        if ( returnDecl ) {
     657                                ApplicationExpr * assign = createBitwiseAssignment( new VariableExpr( returnDecl ), callExpr );
     658                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
     659                                // move env from callExpr to retExpr
     660                                std::swap( retExpr->env, callExpr->env );
     661                                return retExpr;
     662                        } else {
     663                                return callExpr;
     664                        } // if
     665                }
     666
     667                void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
     668                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
     669                        // since temporaries can be shared across sub-expressions, e.g.
     670                        //   [A, A] f();
     671                        //   g([A] x, [A] y);
     672                        //   g(f());
     673                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
     674                        // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
     675                        // to the outer context, rather than inside of the statement expression.
    762676                        visit_children = false;
    763                         // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
     677                        std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
     678                        for ( Statement *& stmt : stmts ) {
     679                                stmt = stmt->acceptMutator( *visitor );
     680                        } // for
     681                        assert( stmtExpr->result );
     682                        Type * result = stmtExpr->result;
     683                        if ( ! result->isVoid() ) {
     684                                for ( ObjectDecl * obj : stmtExpr->returnDecls ) {
     685                                        stmtsToAddBefore.push_back( new DeclStmt( obj ) );
     686                                } // for
     687                                // add destructors after current statement
     688                                for ( Expression * dtor : stmtExpr->dtors ) {
     689                                        stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
     690                                } // for
     691                                // must have a non-empty body, otherwise it wouldn't have a result
     692                                assert( ! stmts.empty() );
     693                                assertf( ! stmtExpr->returnDecls.empty() || stmtExpr->dtors.empty(), "StmtExpr returns non-void, but no return decls: %s", toString( stmtExpr ).c_str() );
     694                                // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
     695                                if ( ! stmtExpr->returnDecls.empty() ) {
     696                                        stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->returnDecls.front() ) ) );
     697                                }
     698                                stmtExpr->returnDecls.clear();
     699                                stmtExpr->dtors.clear();
     700                        }
     701                        assert( stmtExpr->returnDecls.empty() );
     702                        assert( stmtExpr->dtors.empty() );
     703                }
     704
     705                void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
     706                        visit_children = false;
     707                        unqCount[ unqExpr->get_id() ]--;
     708                        static std::unordered_map< int, std::list< Statement * > > dtors;
    764709                        static std::unordered_map< int, UniqueExpr * > unqMap;
    765                         if ( ! unqMap.count( unqExpr->get_id() ) ) {
    766                                 // resolve expr and find its
    767 
    768                                 ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( unqExpr->expr );
    769                                 // PassVisitor<ResolveCopyCtors> fixer;
    770                                 unqExpr->expr = unqExpr->expr->acceptMutator( *visitor );
    771 
    772                                 // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
    773                                 assert( unqExpr->result );
    774                                 if ( impCpCtorExpr ) {
    775                                         CommaExpr * comma = strict_dynamic_cast< CommaExpr * >( unqExpr->expr );
    776                                         VariableExpr * var = strict_dynamic_cast<VariableExpr *>( comma->arg2 );
    777                                         // note the variable used as the result from the call
    778                                         unqExpr->var = var->clone();
    779                                 } else {
    780                                         // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    781                                         unqExpr->object = ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->result->clone(), makeInit( unqExpr->result ) );
    782                                         unqExpr->var = new VariableExpr( unqExpr->object );
    783                                 }
    784 
    785                                 // stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
    786                                 // stmtsToAddAfter.splice( stmtsToAddAfter.end(), fixer.pass.stmtsToAddAfter );
    787                                 unqMap[unqExpr->get_id()] = unqExpr;
    788                         } else {
     710                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
     711                        if ( unqMap.count( unqExpr->get_id() ) ) {
    789712                                // take data from other UniqueExpr to ensure consistency
    790713                                delete unqExpr->get_expr();
    791                                 unqExpr->expr = unqMap[unqExpr->get_id()]->expr->clone();
    792                                 delete unqExpr->result;
    793                                 unqExpr->result = maybeClone( unqExpr->expr->result );
    794                         }
     714                                unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() );
     715                                delete unqExpr->get_result();
     716                                unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) );
     717                                if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
     718                                        stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
     719                                }
     720                                return;
     721                        }
     722                        PassVisitor<FixCopyCtors> fixer( unqCount );
     723                        unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
     724                        stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
     725                        unqMap[unqExpr->get_id()] = unqExpr;
     726                        if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
     727                                stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
     728                        } else { // remember dtors for last instance of unique expr
     729                                dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
     730                        }
     731                        return;
    795732                }
    796733
     
    907844                                                        ctorInit->ctor = nullptr;
    908845                                                }
    909 
    910                                                 Statement * dtor = ctorInit->dtor;
    911                                                 if ( dtor ) {
    912                                                         ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor );
    913                                                         Statement * dtorStmt = implicit->callStmt;
    914 
    915                                                         // don't need to call intrinsic dtor, because it does nothing, but
    916                                                         // non-intrinsic dtors must be called
    917                                                         if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) {
    918                                                                 // set dtor location to the object's location for error messages
    919                                                                 DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
    920                                                                 objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) );
    921                                                                 ctorInit->dtor = nullptr;
    922                                                         } // if
    923                                                 }
    924846                                        } // if
    925847                                } else if ( Initializer * init = ctorInit->init ) {
     
    964886
    965887
     888                template<typename Iterator, typename OutputIterator>
     889                void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {
     890                        for ( Iterator it = begin ; it != end ; ++it ) {
     891                                // extract destructor statement from the object decl and insert it into the output. Note that this is
     892                                // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually
     893                                // calls an intrinsic dtor then the call must (and will) still be generated since the argument may
     894                                // contain side effects.
     895                                ObjectDecl * objDecl = *it;
     896                                ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() );
     897                                assert( ctorInit && ctorInit->get_dtor() );
     898                                *out++ = ctorInit->get_dtor()->clone();
     899                        } // for
     900                }
     901
     902                void InsertDtors::previsit( ObjectDecl * objDecl ) {
     903                        // remember non-static destructed objects so that their destructors can be inserted later
     904                        if ( ! objDecl->get_storageClasses().is_static ) {
     905                                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
     906                                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     907                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
     908                                        Statement * dtor = ctorInit->get_dtor();
     909                                        // don't need to call intrinsic dtor, because it does nothing, but
     910                                        // non-intrinsic dtors must be called
     911                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
     912                                                // set dtor location to the object's location for error messages
     913                                                ctorInit->dtor->location = objDecl->location;
     914                                                reverseDeclOrder.front().push_front( objDecl );
     915                                        } // if
     916                                } // if
     917                        } // if
     918                }
     919
    966920                void InsertDtors::previsit( FunctionDecl * funcDecl ) {
    967921                        // each function needs to have its own set of labels
     
    976930                }
    977931
     932                void InsertDtors::previsit( CompoundStmt * compoundStmt ) {
     933                        // visit statements - this will also populate reverseDeclOrder list.  don't want to dump all destructors
     934                        // when block is left, just the destructors associated with variables defined in this block, so push a new
     935                        // list to the top of the stack so that we can differentiate scopes
     936                        reverseDeclOrder.push_front( OrderedDecls() );
     937                        Parent::previsit( compoundStmt );
     938                }
     939
     940                void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {
     941                        // add destructors for the current scope that we're exiting, unless the last statement is a return, which
     942                        // causes unreachable code warnings
     943                        std::list< Statement * > & statements = compoundStmt->get_kids();
     944                        if ( ! statements.empty() && ! dynamic_cast< ReturnStmt * >( statements.back() ) ) {
     945                                insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( statements ) );
     946                        }
     947                        reverseDeclOrder.pop_front();
     948                }
     949
     950                void InsertDtors::previsit( ReturnStmt * ) {
     951                        // return exits all scopes, so dump destructors for all scopes
     952                        for ( OrderedDecls & od : reverseDeclOrder ) {
     953                                insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );
     954                        } // for
     955                }
     956
    978957                // Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
    979958                // BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
     
    994973                                std::cerr << "S_L = " << printSet( lvars ) << std::endl;
    995974                        )
    996 
    997 
    998                         // std::set_difference requires that the inputs be sorted.
    999                         lvars.sort();
    1000                         curVars.sort();
    1001975
    1002976                        ObjectSet diff;
     
    1008982                        if ( ! diff.empty() ) {
    1009983                                SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
     984                        } // if
     985                        // S_G-S_L results in set of objects that must be destructed
     986                        diff.clear();
     987                        std::set_difference( curVars.begin(), curVars.end(), lvars.begin(), lvars.end(), std::inserter( diff, diff.end() ) );
     988                        DTOR_PRINT(
     989                                std::cerr << "S_G-S_L = " << printSet( diff ) << std::endl;
     990                        )
     991                        if ( ! diff.empty() ) {
     992                                // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages.
     993                                std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() );
     994
     995                                // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor
     996                                OrderedDecls ordered;
     997                                for ( OrderedDecls & rdo : reverseDeclOrder ) {
     998                                        // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.
     999                                        copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );
     1000                                } // for
     1001                                insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );
    10101002                        } // if
    10111003                }
     
    11111103                                                arg2 = new MemberExpr( field, new VariableExpr( params.back() ) );
    11121104                                        }
    1113                                         InitExpander_old srcParam( arg2 );
     1105                                        InitExpander srcParam( arg2 );
    11141106                                        // cast away reference type and construct field.
    11151107                                        Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() );
     
    11241116                                                        callStmt->acceptMutator( *visitor );
    11251117                                                        if ( isCtor ) {
    1126                                                                 function->statements->push_front( callStmt );
    1127                                                         } else { // TODO: don't generate destructor function/object for intrinsic calls
     1118                                                                function->get_statements()->push_front( callStmt );
     1119                                                        } else {
    11281120                                                                // destructor statements should be added at the end
    1129                                                                 // function->get_statements()->push_back( callStmt );
    1130 
    1131                                                                 // Optimization: do not need to call intrinsic destructors on members
    1132                                                                 if ( isIntrinsicSingleArgCallStmt( callStmt ) ) continue;;
    1133 
    1134                                                                 // __Destructor _dtor0 = { (void *)&b.a1, (void (*)(void *)_destroy_A };
    1135                                                                 std::list< Statement * > stmtsToAdd;
    1136 
    1137                                                                 static UniqueName memberDtorNamer = { "__memberDtor" };
    1138                                                                 assertf( Validate::dtorStruct, "builtin __Destructor not found." );
    1139                                                                 assertf( Validate::dtorStructDestroy, "builtin __destroy_Destructor not found." );
    1140 
    1141                                                                 Expression * thisExpr = new CastExpr( new AddressExpr( new VariableExpr( thisParam ) ), new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ) );
    1142                                                                 Expression * dtorExpr = new VariableExpr( getDtorFunc( thisParam, callStmt, stmtsToAdd ) );
    1143 
    1144                                                                 // cast destructor pointer to void (*)(void *), to silence GCC incompatible pointer warnings
    1145                                                                 FunctionType * dtorFtype = new FunctionType( Type::Qualifiers(), false );
    1146                                                                 dtorFtype->parameters.push_back( ObjectDecl::newObject( "", new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), nullptr ) );
    1147                                                                 Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
    1148 
    1149                                                                 ObjectDecl * destructor = ObjectDecl::newObject( memberDtorNamer.newName(), new StructInstType( Type::Qualifiers(), Validate::dtorStruct ), new ListInit( { new SingleInit( thisExpr ), new SingleInit( new CastExpr( dtorExpr, dtorType ) ) } ) );
    1150                                                                 function->statements->push_front( new DeclStmt( destructor ) );
    1151                                                                 destructor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( Validate::dtorStructDestroy ) } ) );
    1152 
    1153                                                                 function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd );
     1121                                                                function->get_statements()->push_back( callStmt );
    11541122                                                        }
    11551123                                                } catch ( SemanticErrorException & error ) {
     
    11951163
    11961164                        std::string fname = getFunctionName( appExpr );
    1197                         if ( fname == function->name ) {
     1165                        if ( fname == function->get_name() ) {
    11981166                                // call to same kind of function
    1199                                 Expression * firstParam = appExpr->args.front();
     1167                                Expression * firstParam = appExpr->get_args().front();
    12001168
    12011169                                if ( isThisExpression( firstParam, thisParam ) ) {
     
    12061174                                        // if first parameter is a member expression on the this parameter,
    12071175                                        // then remove the member from unhandled set.
    1208                                         if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
    1209                                                 unhandled.erase( memberExpr->member );
     1176                                        if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1177                                                unhandled.erase( memberExpr->get_member() );
    12101178                                        }
    12111179                                }
  • src/InitTweak/FixInit.h

    rb067d9b r7951100  
    2424  /// replace constructor initializers with expression statements
    2525  /// and unwrap basic C-style initializers
    26         void fix( std::list< Declaration * > & translationUnit, bool inLibrary );
     26        void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
    2727} // namespace
    2828
  • src/InitTweak/GenInit.cc

    rb067d9b r7951100  
    1515#include "GenInit.h"
    1616
    17 #include <stddef.h>                    // for NULL
    18 #include <algorithm>                   // for any_of
    19 #include <cassert>                     // for assert, strict_dynamic_cast, assertf
    20 #include <deque>
    21 #include <iterator>                    // for back_inserter, inserter, back_inse...
    22 #include <list>                        // for _List_iterator, list
    23 
    24 #include "AST/Decl.hpp"
    25 #include "AST/Init.hpp"
    26 #include "AST/Node.hpp"
    27 #include "AST/Stmt.hpp"
     17#include <stddef.h>                // for NULL
     18#include <algorithm>               // for any_of
     19#include <cassert>                 // for assert, strict_dynamic_cast, assertf
     20#include <iterator>                // for back_inserter, inserter, back_inse...
     21#include <list>                    // for _List_iterator, list
     22
    2823#include "CodeGen/OperatorTable.h"
    29 #include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
    30 #include "Common/SemanticError.h"      // for SemanticError
    31 #include "Common/UniqueName.h"         // for UniqueName
    32 #include "Common/utility.h"            // for ValueGuard, maybeClone
    33 #include "GenPoly/GenPoly.h"           // for getFunctionType, isPolyType
    34 #include "GenPoly/ScopedSet.h"         // for ScopedSet, ScopedSet<>::const_iter...
    35 #include "InitTweak.h"                 // for isConstExpr, InitExpander, checkIn...
    36 #include "Parser/LinkageSpec.h"        // for isOverridable, C
     24#include "Common/PassVisitor.h"    // for PassVisitor, WithGuards, WithShort...
     25#include "Common/SemanticError.h"  // for SemanticError
     26#include "Common/UniqueName.h"     // for UniqueName
     27#include "Common/utility.h"        // for ValueGuard, maybeClone
     28#include "GenPoly/GenPoly.h"       // for getFunctionType, isPolyType
     29#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::const_iter...
     30#include "InitTweak.h"             // for isConstExpr, InitExpander, checkIn...
     31#include "Parser/LinkageSpec.h"    // for isOverridable, C
    3732#include "ResolvExpr/Resolver.h"
    38 #include "SymTab/Autogen.h"            // for genImplicitCall
    39 #include "SymTab/Mangler.h"            // for Mangler
    40 #include "SynTree/Declaration.h"       // for ObjectDecl, DeclarationWithType
    41 #include "SynTree/Expression.h"        // for VariableExpr, UntypedExpr, Address...
    42 #include "SynTree/Initializer.h"       // for ConstructorInit, SingleInit, Initi...
    43 #include "SynTree/Label.h"             // for Label
    44 #include "SynTree/Mutator.h"           // for mutateAll
    45 #include "SynTree/Statement.h"         // for CompoundStmt, ImplicitCtorDtorStmt
    46 #include "SynTree/Type.h"              // for Type, ArrayType, Type::Qualifiers
    47 #include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    48 #include "Tuples/Tuples.h"             // for maybeImpure
    49 #include "Validate/FindSpecialDecls.h" // for SizeType
     33#include "SymTab/Autogen.h"        // for genImplicitCall, SizeType
     34#include "SymTab/Mangler.h"        // for Mangler
     35#include "SynTree/Declaration.h"   // for ObjectDecl, DeclarationWithType
     36#include "SynTree/Expression.h"    // for VariableExpr, UntypedExpr, Address...
     37#include "SynTree/Initializer.h"   // for ConstructorInit, SingleInit, Initi...
     38#include "SynTree/Label.h"         // for Label
     39#include "SynTree/Mutator.h"       // for mutateAll
     40#include "SynTree/Statement.h"     // for CompoundStmt, ImplicitCtorDtorStmt
     41#include "SynTree/Type.h"          // for Type, ArrayType, Type::Qualifiers
     42#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
     43#include "Tuples/Tuples.h"         // for maybeImpure
    5044
    5145namespace InitTweak {
     
    192186
    193187                        // need to resolve array dimensions in order to accurately determine if constexpr
    194                         ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
     188                        ResolvExpr::findSingleExpression( arrayType->dimension, SymTab::SizeType->clone(), indexer );
    195189                        // array is variable-length when the dimension is not constexpr
    196190                        arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
     
    198192                        if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    199193
    200                         ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     194                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
    201195                        arrayDimension->get_type()->set_const( true );
    202196
     
    279273                assertf( objDecl, "genCtorDtor passed null objDecl" );
    280274                std::list< Statement * > stmts;
    281                 InitExpander_old srcParam( maybeClone( arg ) );
     275                InitExpander srcParam( maybeClone( arg ) );
    282276                SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), fname, back_inserter( stmts ), objDecl );
    283277                assert( stmts.size() <= 1 );
     
    291285                std::list< Statement * > dtor;
    292286
    293                 InitExpander_old srcParam( objDecl->get_init() );
    294                 InitExpander_old nullParam( (Initializer *)NULL );
     287                InitExpander srcParam( objDecl->get_init() );
     288                InitExpander nullParam( (Initializer *)NULL );
    295289                SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    296290                SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     
    358352                GuardScope( managedTypes );
    359353        }
    360 
    361 ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl ) {
    362         // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor for each
    363         // constructable object
    364         InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
    365        
    366         ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall(
    367                 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );
    368         ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall(
    369                 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,
    370                 SymTab::LoopBackward );
    371        
    372         // check that either both ctor and dtor are present, or neither
    373         assert( (bool)ctor == (bool)dtor );
    374 
    375         if ( ctor ) {
    376                 // need to remember init expression, in case no ctors exist. If ctor does exist, want to
    377                 // use ctor expression instead of init.
    378                 ctor.strict_as< ast::ImplicitCtorDtorStmt >();
    379                 dtor.strict_as< ast::ImplicitCtorDtorStmt >();
    380 
    381                 return new ast::ConstructorInit{ loc, ctor, dtor, objDecl->init };
    382         }
    383 
    384         return nullptr;
    385 }
    386 
    387354} // namespace InitTweak
    388355
  • src/InitTweak/GenInit.h

    rb067d9b r7951100  
    1919#include <string>              // for string
    2020
    21 #include "AST/Fwd.hpp"
    22 #include "Common/CodeLocation.h"
     21#include "SynTree/SynTree.h"   // for Visitor Nodes
     22
    2323#include "GenPoly/ScopedSet.h" // for ScopedSet
    24 #include "SynTree/SynTree.h"   // for Visitor Nodes
    2524
    2625namespace InitTweak {
     
    3635        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
    3736        ConstructorInit * genCtorInit( ObjectDecl * objDecl );
    38         ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl );
    3937
    4038        class ManagedTypes {
  • src/InitTweak/InitTweak.cc

    rb067d9b r7951100  
    1 //
    2 // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
    3 //
    4 // The contents of this file are covered under the licence agreement in the
    5 // file "LICENCE" distributed with Cforall.
    6 //
    7 // InitTweak.cc --
    8 //
    9 // Author           : Rob Schluntz
    10 // Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 25 22:21:48 2019
    13 // Update Count     : 7
    14 //
    15 
    161#include <algorithm>               // for find, all_of
    172#include <cassert>                 // for assertf, assert, strict_dynamic_cast
     
    194#include <iterator>                // for back_insert_iterator, back_inserter
    205#include <memory>                  // for __shared_ptr
    21 #include <vector>
    22 
    23 #include "AST/Expr.hpp"
    24 #include "AST/Init.hpp"
    25 #include "AST/Node.hpp"
    26 #include "AST/Pass.hpp"
    27 #include "AST/Stmt.hpp"
    28 #include "AST/Type.hpp"
     6
    297#include "Common/PassVisitor.h"
    308#include "Common/SemanticError.h"  // for SemanticError
     
    4826#include "Tuples/Tuples.h"         // for Tuples::isTtype
    4927
     28class UntypedValofExpr;
     29
    5030namespace InitTweak {
    5131        namespace {
     
    8767                };
    8868
    89                 struct InitFlattener_old : public WithShortCircuiting {
     69                struct InitFlattener : public WithShortCircuiting {
    9070                        void previsit( SingleInit * singleInit ) {
    9171                                visit_children = false;
     
    9575                };
    9676
    97                 struct InitFlattener_new : public ast::WithShortCircuiting {
    98                         std::vector< ast::ptr< ast::Expr > > argList;
    99 
    100                         void previsit( const ast::SingleInit * singleInit ) {
    101                                 visit_children = false;
    102                                 argList.emplace_back( singleInit->value );
    103                         }
    104                 };
    105 
    106         } // anonymous namespace
     77        }
    10778
    10879        std::list< Expression * > makeInitList( Initializer * init ) {
    109                 PassVisitor<InitFlattener_old> flattener;
     80                PassVisitor<InitFlattener> flattener;
    11081                maybeAccept( init, flattener );
    11182                return flattener.pass.argList;
     
    12495        }
    12596
    126 std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
    127         ast::Pass< InitFlattener_new > flattener;
    128         maybe_accept( init, flattener );
    129         return std::move( flattener.pass.argList );
    130 }
    131 
    132         class InitExpander_old::ExpanderImpl {
     97        class InitExpander::ExpanderImpl {
    13398        public:
    13499                virtual ~ExpanderImpl() = default;
     
    137102        };
    138103
    139         class InitImpl_old : public InitExpander_old::ExpanderImpl {
     104        class InitImpl : public InitExpander::ExpanderImpl {
    140105        public:
    141                 InitImpl_old( Initializer * init ) : init( init ) {}
    142                 virtual ~InitImpl_old() = default;
     106                InitImpl( Initializer * init ) : init( init ) {}
     107                virtual ~InitImpl() = default;
    143108
    144109                virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) {
     
    154119        };
    155120
    156         class ExprImpl_old : public InitExpander_old::ExpanderImpl {
     121        class ExprImpl : public InitExpander::ExpanderImpl {
    157122        public:
    158                 ExprImpl_old( Expression * expr ) : arg( expr ) {}
    159                 virtual ~ExprImpl_old() { delete arg; }
     123                ExprImpl( Expression * expr ) : arg( expr ) {}
     124                virtual ~ExprImpl() { delete arg; }
    160125
    161126                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     
    181146        };
    182147
    183         InitExpander_old::InitExpander_old( Initializer * init ) : expander( new InitImpl_old( init ) ) {}
    184 
    185         InitExpander_old::InitExpander_old( Expression * expr ) : expander( new ExprImpl_old( expr ) ) {}
    186 
    187         std::list< Expression * > InitExpander_old::operator*() {
     148        InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
     149
     150        InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
     151
     152        std::list< Expression * > InitExpander::operator*() {
    188153                return cur;
    189154        }
    190155
    191         InitExpander_old & InitExpander_old::operator++() {
     156        InitExpander & InitExpander::operator++() {
    192157                cur = expander->next( indices );
    193158                return *this;
     
    195160
    196161        // use array indices list to build switch statement
    197         void InitExpander_old::addArrayIndex( Expression * index, Expression * dimension ) {
     162        void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
    198163                indices.push_back( index );
    199164                indices.push_back( dimension );
    200165        }
    201166
    202         void InitExpander_old::clearArrayIndices() {
     167        void InitExpander::clearArrayIndices() {
    203168                deleteAll( indices );
    204169                indices.clear();
    205170        }
    206171
    207         bool InitExpander_old::addReference() {
     172        bool InitExpander::addReference() {
    208173                bool added = false;
    209174                for ( Expression *& expr : cur ) {
     
    236201
    237202                template< typename OutIterator >
    238                 void build( UntypedExpr * callExpr, InitExpander_old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
     203                void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
    239204                        if ( idx == idxEnd ) return;
    240205                        Expression * index = *idx++;
     
    293258        // remaining elements.
    294259        // To accomplish this, generate switch statement, consuming all of expander's elements
    295         Statement * InitImpl_old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     260        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    296261                if ( ! init ) return nullptr;
    297262                CompoundStmt * block = new CompoundStmt();
     
    306271        }
    307272
    308         Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
     273        Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
    309274                return nullptr;
    310275        }
    311276
    312         Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) {
     277        Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
    313278                return expander->buildListInit( dst, indices );
    314279        }
    315 
    316 class InitExpander_new::ExpanderImpl {
    317 public:
    318         virtual ~ExpanderImpl() = default;
    319         virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0;
    320         virtual ast::ptr< ast::Stmt > buildListInit(
    321                 ast::UntypedExpr * callExpr, IndexList & indices ) = 0;
    322 };
    323 
    324 namespace {
    325         template< typename Out >
    326         void buildCallExpr(
    327                 ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension,
    328                 const ast::Init * init, Out & out
    329         ) {
    330                 const CodeLocation & loc = init->location;
    331 
    332                 auto cond = new ast::UntypedExpr{
    333                         loc, new ast::NameExpr{ loc, "?<?" }, { index, dimension } };
    334 
    335                 std::vector< ast::ptr< ast::Expr > > args = makeInitList( init );
    336                 splice( callExpr->args, args );
    337 
    338                 out.emplace_back( new ast::IfStmt{ loc, cond, new ast::ExprStmt{ loc, callExpr } } );
    339 
    340                 out.emplace_back( new ast::ExprStmt{
    341                         loc, new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, "++?" }, { index } } } );
    342         }
    343 
    344         template< typename Out >
    345         void build(
    346                 ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices,
    347                 const ast::Init * init, Out & out
    348         ) {
    349                 if ( indices.empty() ) return;
    350 
    351                 unsigned idx = 0;
    352 
    353                 const ast::Expr * index = indices[idx++];
    354                 assert( idx != indices.size() );
    355                 const ast::Expr * dimension = indices[idx++];
    356 
    357                 if ( idx == indices.size() ) {
    358                         if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) {
    359                                 for ( const ast::Init * init : *listInit ) {
    360                                         buildCallExpr( callExpr, index, dimension, init, out );
    361                                 }
    362                         } else {
    363                                 buildCallExpr( callExpr, index, dimension, init, out );
    364                         }
    365                 } else {
    366                         const CodeLocation & loc = init->location;
    367 
    368                         unsigned long cond = 0;
    369                         auto listInit = dynamic_cast< const ast::ListInit * >( init );
    370                         if ( ! listInit ) { SemanticError( loc, "unbalanced list initializers" ); }
    371 
    372                         static UniqueName targetLabel( "L__autogen__" );
    373                         ast::Label switchLabel{
    374                                 loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } };
    375 
    376                         std::vector< ast::ptr< ast::Stmt > > branches;
    377                         for ( const ast::Init * init : *listInit ) {
    378                                 auto condition = ast::ConstantExpr::from_ulong( loc, cond );
    379                                 ++cond;
    380 
    381                                 std::vector< ast::ptr< ast::Stmt > > stmts;
    382                                 build( callExpr, indices, init, stmts );
    383                                 stmts.emplace_back(
    384                                         new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } );
    385                                 branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } );
    386                         }
    387                         out.emplace_back( new ast::SwitchStmt{ loc, index, std::move( branches ) } );
    388                         out.emplace_back( new ast::NullStmt{ loc, { switchLabel } } );
    389                 }
    390         }
    391 
    392         class InitImpl_new final : public InitExpander_new::ExpanderImpl {
    393                 ast::ptr< ast::Init > init;
    394         public:
    395                 InitImpl_new( const ast::Init * i ) : init( i ) {}
    396 
    397                 std::vector< ast::ptr< ast::Expr > > next( InitExpander_new::IndexList & ) override {
    398                         return makeInitList( init );
    399                 }
    400 
    401                 ast::ptr< ast::Stmt > buildListInit(
    402                         ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices
    403                 ) override {
    404                         // If array came with an initializer list, initialize each element. We may have more
    405                         // initializers than elements of the array; need to check at each index that we have
    406                         // not exceeded size. We may have fewer initializers than elements in the array; need
    407                         // to default-construct remaining elements. To accomplish this, generate switch
    408                         // statement consuming all of expander's elements
    409 
    410                         if ( ! init ) return {};
    411 
    412                         std::list< ast::ptr< ast::Stmt > > stmts;
    413                         build( callExpr, indices, init, stmts );
    414                         if ( stmts.empty() ) {
    415                                 return {};
    416                         } else {
    417                                 auto block = new ast::CompoundStmt{ init->location, std::move( stmts ) };
    418                                 init = nullptr;  // consumed in creating the list init
    419                                 return block;
    420                         }
    421                 }
    422         };
    423 
    424         class ExprImpl_new final : public InitExpander_new::ExpanderImpl {
    425                 ast::ptr< ast::Expr > arg;
    426         public:
    427                 ExprImpl_new( const ast::Expr * a ) : arg( a ) {}
    428 
    429                 std::vector< ast::ptr< ast::Expr > > next(
    430                         InitExpander_new::IndexList & indices
    431                 ) override {
    432                         if ( ! arg ) return {};
    433 
    434                         const CodeLocation & loc = arg->location;
    435                         const ast::Expr * expr = arg;
    436                         for ( auto it = indices.rbegin(); it != indices.rend(); ++it ) {
    437                                 // go through indices and layer on subscript exprs ?[?]
    438                                 ++it;
    439                                 expr = new ast::UntypedExpr{
    440                                         loc, new ast::NameExpr{ loc, "?[?]" }, { expr, *it } };
    441                         }
    442                         return { expr };
    443                 }
    444 
    445                 ast::ptr< ast::Stmt > buildListInit(
    446                         ast::UntypedExpr *, InitExpander_new::IndexList &
    447                 ) override {
    448                         return {};
    449                 }
    450         };
    451 } // anonymous namespace
    452 
    453 InitExpander_new::InitExpander_new( const ast::Init * init )
    454 : expander( new InitImpl_new{ init } ), crnt(), indices() {}
    455 
    456 InitExpander_new::InitExpander_new( const ast::Expr * expr )
    457 : expander( new ExprImpl_new{ expr } ), crnt(), indices() {}
    458 
    459 std::vector< ast::ptr< ast::Expr > > InitExpander_new::operator* () { return crnt; }
    460 
    461 InitExpander_new & InitExpander_new::operator++ () {
    462         crnt = expander->next( indices );
    463         return *this;
    464 }
    465 
    466 /// builds statement which has the same semantics as a C-style list initializer (for array
    467 /// initializers) using callExpr as the base expression to perform initialization
    468 ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {
    469         return expander->buildListInit( callExpr, indices );
    470 }
    471 
    472 void InitExpander_new::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {
    473         indices.emplace_back( index );
    474         indices.emplace_back( dimension );
    475 }
    476 
    477 void InitExpander_new::clearArrayIndices() { indices.clear(); }
    478 
    479 bool InitExpander_new::addReference() {
    480         for ( ast::ptr< ast::Expr > & expr : crnt ) {
    481                 expr = new ast::AddressExpr{ expr };
    482         }
    483         return ! crnt.empty();
    484 }
    485280
    486281        Type * getTypeofThis( FunctionType * ftype ) {
     
    511306        }
    512307
    513         struct CallFinder_old {
    514                 CallFinder_old( const std::list< std::string > & names ) : names( names ) {}
     308        struct CallFinder {
     309                CallFinder( const std::list< std::string > & names ) : names( names ) {}
    515310
    516311                void postvisit( ApplicationExpr * appExpr ) {
     
    535330        };
    536331
    537         struct CallFinder_new final {
    538                 std::vector< ast::ptr< ast::Expr > > matches;
    539                 const std::vector< std::string > names;
    540 
    541                 CallFinder_new( std::vector< std::string > && ns ) : matches(), names( std::move(ns) ) {}
    542 
    543                 void handleCallExpr( const ast::Expr * expr ) {
    544                         std::string fname = getFunctionName( expr );
    545                         if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
    546                                 matches.emplace_back( expr );
    547                         }
    548                 }
    549 
    550                 void postvisit( const ast::ApplicationExpr * expr ) { handleCallExpr( expr ); }
    551                 void postvisit( const ast::UntypedExpr *     expr ) { handleCallExpr( expr ); }
    552         };
    553 
    554332        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
    555                 static PassVisitor<CallFinder_old> finder( std::list< std::string >{ "?{}", "^?{}" } );
     333                static PassVisitor<CallFinder> finder( std::list< std::string >{ "?{}", "^?{}" } );
    556334                finder.pass.matches = &matches;
    557335                maybeAccept( stmt, finder );
    558         }
    559 
    560         std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt ) {
    561                 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
    562                 maybe_accept( stmt, finder );
    563                 return std::move( finder.pass.matches );
    564336        }
    565337
     
    567339                std::list< Expression * > matches;
    568340                collectCtorDtorCalls( stmt, matches );
    569                 assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() );
     341                assert( matches.size() <= 1 );
    570342                return matches.size() == 1 ? matches.front() : nullptr;
    571343        }
     
    573345        namespace {
    574346                DeclarationWithType * getCalledFunction( Expression * expr );
    575                 const ast::DeclWithType * getCalledFunction( const ast::Expr * expr );
    576347
    577348                template<typename CallExpr>
     
    583354                        return getCalledFunction( expr->get_args().front() );
    584355                }
    585 
    586                 template<typename CallExpr>
    587                 const ast::DeclWithType * handleDerefCalledFunction( const CallExpr * expr ) {
    588                         // (*f)(x) => should get "f"
    589                         std::string name = getFunctionName( expr );
    590                         assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
    591                         assertf( ! expr->args.empty(), "Cannot get called function from dereference with no arguments" );
    592                         return getCalledFunction( expr->args.front() );
    593                 }
    594 
    595356
    596357                DeclarationWithType * getCalledFunction( Expression * expr ) {
     
    613374                        return nullptr;
    614375                }
    615 
    616                 const ast::DeclWithType * getCalledFunction( const ast::Expr * expr ) {
    617                         assert( expr );
    618                         if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( expr ) ) {
    619                                 return varExpr->var;
    620                         } else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( expr ) ) {
    621                                 return memberExpr->member;
    622                         } else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) {
    623                                 return getCalledFunction( castExpr->arg );
    624                         } else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( expr ) ) {
    625                                 return handleDerefCalledFunction( untypedExpr );
    626                         } else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * > ( expr ) ) {
    627                                 return handleDerefCalledFunction( appExpr );
    628                         } else if ( const ast::AddressExpr * addrExpr = dynamic_cast< const ast::AddressExpr * >( expr ) ) {
    629                                 return getCalledFunction( addrExpr->arg );
    630                         } else if ( const ast::CommaExpr * commaExpr = dynamic_cast< const ast::CommaExpr * >( expr ) ) {
    631                                 return getCalledFunction( commaExpr->arg2 );
    632                         }
    633                         return nullptr;
    634                 }
    635 
    636                 DeclarationWithType * getFunctionCore( const Expression * expr ) {
    637                         if ( const auto * appExpr = dynamic_cast< const ApplicationExpr * >( expr ) ) {
    638                                 return getCalledFunction( appExpr->function );
    639                         } else if ( const auto * untyped = dynamic_cast< const UntypedExpr * >( expr ) ) {
    640                                 return getCalledFunction( untyped->function );
    641                         }
    642                         assertf( false, "getFunction with unknown expression: %s", toString( expr ).c_str() );
    643                 }
    644376        }
    645377
    646378        DeclarationWithType * getFunction( Expression * expr ) {
    647                 return getFunctionCore( expr );
    648         }
    649 
    650         const DeclarationWithType * getFunction( const Expression * expr ) {
    651                 return getFunctionCore( expr );
    652         }
    653 
    654         const ast::DeclWithType * getFunction( const ast::Expr * expr ) {
    655                 if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( expr ) ) {
    656                         return getCalledFunction( appExpr->func );
    657                 } else if ( const ast::UntypedExpr * untyped = dynamic_cast< const ast::UntypedExpr * > ( expr ) ) {
    658                         return getCalledFunction( untyped->func );
     379                if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
     380                        return getCalledFunction( appExpr->get_function() );
     381                } else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * > ( expr ) ) {
     382                        return getCalledFunction( untyped->get_function() );
    659383                }
    660384                assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
     
    671395        }
    672396
    673         const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr ) {
    674                 auto appExpr = dynamic_cast< const ast::ApplicationExpr * >( expr );
    675                 if ( ! appExpr ) return nullptr;
    676 
    677                 const ast::DeclWithType * func = getCalledFunction( appExpr->func );
    678                 assertf( func,
    679                         "getCalledFunction returned nullptr: %s", toString( appExpr->func ).c_str() );
    680 
    681                 // check for Intrinsic only -- don't want to remove all overridable ctor/dtor because
    682                 // autogenerated ctor/dtor will call all member dtors, and some members may have a
    683                 // user-defined dtor
    684                 return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr;
    685         }
    686 
    687397        namespace {
    688398                template <typename Predicate>
     
    693403                        return std::all_of( callExprs.begin(), callExprs.end(), pred);
    694404                }
    695 
    696                 template <typename Predicate>
    697                 bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
    698                         std::vector< ast::ptr< ast::Expr > > callExprs = collectCtorDtorCalls( stmt );
    699                         return std::all_of( callExprs.begin(), callExprs.end(), pred );
    700                 }
    701405        }
    702406
     
    704408                return allofCtorDtor( stmt, []( Expression * callExpr ){
    705409                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    706                                 FunctionType *funcType = GenPoly::getFunctionType( appExpr->function->result );
     410                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_result() );
    707411                                assert( funcType );
    708412                                return funcType->get_parameters().size() == 1;
    709                         }
    710                         return false;
    711                 });
    712         }
    713 
    714         bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt ) {
    715                 return allofCtorDtor( stmt, []( const ast::Expr * callExpr ){
    716                         if ( const ast::ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    717                                 const ast::FunctionType * funcType =
    718                                         GenPoly::getFunctionType( appExpr->func->result );
    719                                 assert( funcType );
    720                                 return funcType->params.size() == 1;
    721413                        }
    722414                        return false;
     
    737429                                if ( pos == 0 ) return arg;
    738430                                pos--;
    739                         }
    740                         assert( false );
    741                 }
    742 
    743                 template<typename CallExpr>
    744                 const ast::Expr * callArg( const CallExpr * call, unsigned int pos ) {
    745                         if( pos >= call->args.size() ) {
    746                                 assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.",
    747                                         pos, toString( call ).c_str() );
    748                         }
    749                         for ( const ast::Expr * arg : call->args ) {
    750                                 if ( pos == 0 ) return arg;
    751                                 --pos;
    752431                        }
    753432                        assert( false );
     
    774453        }
    775454
    776         const ast::Expr * getCallArg( const ast::Expr * call, unsigned pos ) {
    777                 if ( auto app = dynamic_cast< const ast::ApplicationExpr * >( call ) ) {
    778                         return callArg( app, pos );
    779                 } else if ( auto untyped = dynamic_cast< const ast::UntypedExpr * >( call ) ) {
    780                         return callArg( untyped, pos );
    781                 } else if ( auto tupleAssn = dynamic_cast< const ast::TupleAssignExpr * >( call ) ) {
    782                         const std::list<ast::ptr<ast::Stmt>>& stmts = tupleAssn->stmtExpr->stmts->kids;
    783                         assertf( ! stmts.empty(), "TupleAssignExpr missing statements." );
    784                         auto stmt  = strict_dynamic_cast< const ast::ExprStmt * >( stmts.back().get() );
    785                         auto tuple = strict_dynamic_cast< const ast::TupleExpr * >( stmt->expr.get() );
    786                         assertf( ! tuple->exprs.empty(), "TupleAssignExpr has empty tuple expr.");
    787                         return getCallArg( tuple->exprs.front(), pos );
    788                 } else if ( auto ctor = dynamic_cast< const ast::ImplicitCopyCtorExpr * >( call ) ) {
    789                         return getCallArg( ctor->callExpr, pos );
    790                 } else {
    791                         assertf( false, "Unexpected expression type passed to getCallArg: %s",
    792                                 toString( call ).c_str() );
    793                 }
    794         }
    795 
    796455        namespace {
    797456                std::string funcName( Expression * func );
    798                 std::string funcName( const ast::Expr * func );
    799457
    800458                template<typename CallExpr>
     
    805463                        assertf( ! expr->get_args().empty(), "Cannot get function name from dereference with no arguments" );
    806464                        return funcName( expr->get_args().front() );
    807                 }
    808 
    809                 template<typename CallExpr>
    810                 std::string handleDerefName( const CallExpr * expr ) {
    811                         // (*f)(x) => should get name "f"
    812                         std::string name = getFunctionName( expr );
    813                         assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
    814                         assertf( ! expr->args.empty(), "Cannot get function name from dereference with no arguments" );
    815                         return funcName( expr->args.front() );
    816465                }
    817466
     
    837486                        }
    838487                }
    839 
    840                 std::string funcName( const ast::Expr * func ) {
    841                         if ( const ast::NameExpr * nameExpr = dynamic_cast< const ast::NameExpr * >( func ) ) {
    842                                 return nameExpr->name;
    843                         } else if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( func ) ) {
    844                                 return varExpr->var->name;
    845                         }       else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( func ) ) {
    846                                 return funcName( castExpr->arg );
    847                         } else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( func ) ) {
    848                                 return memberExpr->member->name;
    849                         } else if ( const ast::UntypedMemberExpr * memberExpr = dynamic_cast< const ast::UntypedMemberExpr * > ( func ) ) {
    850                                 return funcName( memberExpr->member );
    851                         } else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( func ) ) {
    852                                 return handleDerefName( untypedExpr );
    853                         } else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( func ) ) {
    854                                 return handleDerefName( appExpr );
    855                         } else if ( const ast::ConstructorExpr * ctorExpr = dynamic_cast< const ast::ConstructorExpr * >( func ) ) {
    856                                 return funcName( getCallArg( ctorExpr->callExpr, 0 ) );
    857                         } else {
    858                                 assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() );
    859                         }
    860                 }
    861488        }
    862489
     
    875502        }
    876503
    877         std::string getFunctionName( const ast::Expr * expr ) {
    878                 // there's some unforunate overlap here with getCalledFunction. Ideally this would be able to use getCalledFunction and
    879                 // return the name of the DeclarationWithType, but this needs to work for NameExpr and UntypedMemberExpr, where getCalledFunction
    880                 // can't possibly do anything reasonable.
    881                 if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( expr ) ) {
    882                         return funcName( appExpr->func );
    883                 } else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * > ( expr ) ) {
    884                         return funcName( untypedExpr->func );
    885                 } else {
    886                         std::cerr << expr << std::endl;
    887                         assertf( false, "Unexpected expression type passed to getFunctionName" );
    888                 }
    889         }
    890 
    891504        Type * getPointerBase( Type * type ) {
    892505                if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
     
    900513                }
    901514        }
    902         const ast::Type* getPointerBase( const ast::Type* t ) {
    903                 if ( const auto * p = dynamic_cast< const ast::PointerType * >( t ) ) {
    904                         return p->base;
    905                 } else if ( const auto * a = dynamic_cast< const ast::ArrayType * >( t ) ) {
    906                         return a->base;
    907                 } else if ( const auto * r = dynamic_cast< const ast::ReferenceType * >( t ) ) {
    908                         return r->base;
    909                 } else return nullptr;
    910         }
    911515
    912516        Type * isPointerType( Type * type ) {
     
    957561                void previsit( OffsetofExpr * ) {}
    958562                void previsit( OffsetPackExpr * ) {}
     563                void previsit( AttrExpr * ) {}
    959564                void previsit( CommaExpr * ) {}
    960565                void previsit( LogicalExpr * ) {}
     
    1004609        bool isCtorDtorAssign( const std::string & str ) { return isCtorDtor( str ) || isAssignment( str ); }
    1005610
    1006         const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ) {
    1007                 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( decl );
     611        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) {
     612                FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl );
    1008613                if ( ! function ) return nullptr;
    1009614                if ( function->name != fname ) return nullptr;
     
    1022627        }
    1023628
    1024         bool isCopyFunction( const ast::FunctionDecl * decl ) {
    1025                 const ast::FunctionType * ftype = decl->type;
    1026                 if ( ftype->params.size() != 2 ) return false;
    1027 
    1028                 const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() );
    1029                 if ( ! t1 ) return false;
    1030                 const ast::Type * t2 = ftype->params.back()->get_type();
    1031 
    1032                 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
    1033         }
    1034 
    1035         const FunctionDecl * isAssignment( const Declaration * decl ) {
     629        FunctionDecl * isAssignment( Declaration * decl ) {
    1036630                return isCopyFunction( decl, "?=?" );
    1037631        }
    1038         const FunctionDecl * isDestructor( const Declaration * decl ) {
    1039                 if ( isDestructor( decl->name ) ) {
    1040                         return dynamic_cast< const FunctionDecl * >( decl );
     632        FunctionDecl * isDestructor( Declaration * decl ) {
     633                if ( isDestructor( decl->get_name() ) ) {
     634                        return dynamic_cast< FunctionDecl * >( decl );
    1041635                }
    1042636                return nullptr;
    1043637        }
    1044         const FunctionDecl * isDefaultConstructor( const Declaration * decl ) {
     638        FunctionDecl * isDefaultConstructor( Declaration * decl ) {
    1045639                if ( isConstructor( decl->name ) ) {
    1046                         if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
     640                        if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
    1047641                                if ( func->type->parameters.size() == 1 ) {
    1048642                                        return func;
     
    1052646                return nullptr;
    1053647        }
    1054         const FunctionDecl * isCopyConstructor( const Declaration * decl ) {
     648        FunctionDecl * isCopyConstructor( Declaration * decl ) {
    1055649                return isCopyFunction( decl, "?{}" );
    1056650        }
  • src/InitTweak/InitTweak.h

    rb067d9b r7951100  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // InitTweak.h --
     7// RemoveInit.h --
    88//
    99// Author           : Rob Schluntz
    1010// Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 19 14:18:00 2019
    13 // Update Count     : 6
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:30:33 2017
     13// Update Count     : 4
    1414//
    1515
     
    1919#include <memory>             // for shared_ptr
    2020#include <string>             // for string, allocator
    21 #include <vector>
    2221
    23 #include "AST/Fwd.hpp"        // for AST nodes
    2422#include "SynTree/SynTree.h"  // for Visitor Nodes
    2523
    2624// helper functions for initialization
    2725namespace InitTweak {
    28         const FunctionDecl * isAssignment( const Declaration * decl );
    29         const FunctionDecl * isDestructor( const Declaration * decl );
    30         const FunctionDecl * isDefaultConstructor( const Declaration * decl );
    31         const FunctionDecl * isCopyConstructor( const Declaration * decl );
    32         const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname );
    33         bool isCopyFunction( const ast::FunctionDecl * decl );
     26        FunctionDecl * isAssignment( Declaration * decl );
     27        FunctionDecl * isDestructor( Declaration * decl );
     28        FunctionDecl * isDefaultConstructor( Declaration * decl );
     29        FunctionDecl * isCopyConstructor( Declaration * decl );
     30        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname );
    3431
    3532        /// returns the base type of the first parameter to a constructor/destructor/assignment function
     
    4441        /// transform Initializer into an argument list that can be passed to a call expression
    4542        std::list< Expression * > makeInitList( Initializer * init );
    46         std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init );
    4743
    4844        /// True if the resolver should try to construct dwt
     
    6157        /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
    6258        DeclarationWithType * getFunction( Expression * expr );
    63         const DeclarationWithType * getFunction( const Expression * expr );
    64         const ast::DeclWithType * getFunction( const ast::Expr * expr );
    6559
    6660        /// Non-Null if expr is a call expression whose target function is intrinsic
    6761        ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
    68         const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr);
    6962
    7063        /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
     
    7265        /// Currently has assertions that make it less than fully general.
    7366        bool isIntrinsicSingleArgCallStmt( Statement * stmt );
    74         bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );
    7567
    7668        /// True if stmt is a call statement where the function called is intrinsic.
     
    7971        /// get all Ctor/Dtor call expressions from a Statement
    8072        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    81         std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt );
    8273
    8374        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     
    8677        /// returns the name of the function being called
    8778        std::string getFunctionName( Expression * expr );
    88         std::string getFunctionName( const ast::Expr * expr );
    8979
    9080        /// returns the argument to a call expression in position N indexed from 0
    9181        Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    92         const ast::Expr * getCallArg( const ast::Expr * call, unsigned pos );
    9382
    9483        /// returns the base type of a PointerType or ArrayType, else returns NULL
    9584        Type * getPointerBase( Type * );
    96         const ast::Type* getPointerBase( const ast::Type* );
    9785
    9886        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     
    10391        bool isConstExpr( Initializer * init );
    10492
    105         class InitExpander_old {
     93        class InitExpander {
    10694        public:
    10795                // expand by stepping through init to get each list of arguments
    108                 InitExpander_old( Initializer * init );
     96                InitExpander( Initializer * init );
    10997
    11098                // always expand to expr
    111                 InitExpander_old( Expression * expr );
     99                InitExpander( Expression * expr );
    112100
    113101                // iterator-like interface
    114102                std::list< Expression * > operator*();
    115                 InitExpander_old & operator++();
     103                InitExpander & operator++();
    116104
    117105                // builds statement which has the same semantics as a C-style list initializer
     
    132120                IndexList indices;
    133121        };
    134 
    135         class InitExpander_new {
    136         public:
    137                 using IndexList = std::vector< ast::ptr< ast::Expr > >;
    138                 class ExpanderImpl;
    139 
    140         private:
    141                 std::shared_ptr< ExpanderImpl > expander;
    142                 std::vector< ast::ptr< ast::Expr > > crnt;
    143                 // invariant: list of size 2N (elements come in pairs [index, dimension])
    144                 IndexList indices;
    145 
    146         public:
    147                 /// Expand by stepping through init to get each list of arguments
    148                 InitExpander_new( const ast::Init * init );
    149 
    150                 /// Always expand to expression
    151                 InitExpander_new( const ast::Expr * expr );
    152 
    153                 std::vector< ast::ptr< ast::Expr > > operator* ();
    154                 InitExpander_new & operator++ ();
    155 
    156                 /// builds statement which has the same semantics as a C-style list initializer (for array
    157                 /// initializers) using callExpr as the base expression to perform initialization.
    158                 /// Mutates callExpr
    159                 ast::ptr< ast::Stmt > buildListInit( ast::UntypedExpr * callExpr );
    160 
    161                 void addArrayIndex( const ast::Expr * index, const ast::Expr * dimension );
    162 
    163                 void clearArrayIndices();
    164 
    165                 bool addReference();
    166         };
    167122} // namespace
    168123
  • src/InitTweak/module.mk

    rb067d9b r7951100  
    2020        InitTweak/InitTweak.cc
    2121
    22 SRCDEMANGLE += InitTweak/GenInit.cc \
    23         InitTweak/InitTweak.cc
    24 
  • src/MakeLibCfa.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 10:33:33 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Feb 17 21:08:09 2019
    13 // Update Count     : 41
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Fri Apr 22 13:54:15 2016
     13// Update Count     : 40
    1414//
    1515
     
    146146        } // namespace
    147147} // namespace LibCfa
    148 
    149 // Local Variables: //
    150 // tab-width: 4 //
    151 // End: //
  • src/Makefile.am

    rb067d9b r7951100  
    1010## Author           : Peter A. Buhr
    1111## Created On       : Sun May 31 08:51:46 2015
    12 ## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Aug  5 12:57:46 2019
    14 ## Update Count     : 98
     12## Last Modified By : Andrew Beach
     13## Last Modified On : Tus Jul 25 10:34:00 2017
     14## Update Count     : 76
    1515###############################################################################
    1616
    1717# create object files in directory with source files
    18 AUTOMAKE_OPTIONS = foreign subdir-objects
    19 ACLOCAL_AMFLAGS  = -I automake
     18AUTOMAKE_OPTIONS = subdir-objects
    2019
    2120SRC = main.cc \
    22       MakeLibCfa.cc \
    23       CompilationState.cc
    24 
    25 SRCDEMANGLE = CompilationState.cc
     21      MakeLibCfa.cc
    2622
    2723MAINTAINERCLEANFILES =
    28 MOSTLYCLEANFILES =
    2924
    30 if WITH_LIBPROFILER
    31 LIBPROFILER = -lprofiler
    32 endif
     25# Is there a way to use a variable for the directory names?
    3326
    34 if WITH_LIBTCMALLOC
    35 LIBTCMALLOC = -ltcmalloc
    36 TCMALLOCFLAG = -DTCMALLOC
    37 endif
    38 
    39 include AST/module.mk
    4027include CodeGen/module.mk
    4128include CodeTools/module.mk
     
    5037include SynTree/module.mk
    5138include Tuples/module.mk
    52 include Validate/module.mk
    5339include Virtual/module.mk
    5440
    55 $(addprefix $(srcdir)/, ResolvExpr/ConversionCost.cc ResolvExpr/CommonType.cc SymTab/ManglerCommon.cc) : $(srcdir)/SynTree/Type.h
    56 
    57 $(srcdir)/AST/Type.hpp : BasicTypes-gen.cc
    58         ${AM_V_GEN}${CXXCOMPILE} $< -o BasicTypes-gen -Wall -Wextra
    59         @./BasicTypes-gen
    60         @rm BasicTypes-gen
    61 
    6241# put into lib for now
    63 cfa_cpplibdir = $(CFA_LIBDIR)
    64 cfa_cpplib_PROGRAMS = ../driver/cfa-cpp $(DEMANGLER)
    65 EXTRA_PROGRAMS = demangler
    66 ___driver_cfa_cpp_SOURCES = $(SRC)
    67 ___driver_cfa_cpp_LDADD = -ldl $(LIBPROFILER) $(LIBTCMALLOC)
    68 
    69 AM_CXXFLAGS = @HOST_FLAGS@ -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I./Parser -I$(srcdir)/Parser -I$(srcdir)/include -DYY_NO_INPUT -O3 -g -std=c++14 $(TCMALLOCFLAG)
    70 AM_LDFLAGS  = @HOST_FLAGS@ -Xlinker -export-dynamic
    71 ARFLAGS     = cr
    72 
    73 demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
    74 
    75 demangler_LDADD = libdemangle.a -ldl                    # yywrap
    76 
    77 noinst_LIBRARIES = $(LIBDEMANGLE)
    78 EXTRA_LIBRARIES = libdemangle.a
    79 libdemangle_a_SOURCES = $(SRCDEMANGLE)
     42cfa_cpplibdir = ${CFA_LIBDIR}
     43cfa_cpplib_PROGRAMS = driver/cfa-cpp
     44driver_cfa_cpp_SOURCES = ${SRC}
     45driver_cfa_cpp_LDADD = -ldl                     # yywrap
     46driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I${abs_top_srcdir}/src/include -DYY_NO_INPUT -O2 -g -std=c++14
     47driver_cfa_cpp_LDFLAGS = -Xlinker -export-dynamic
    8048
    8149MAINTAINERCLEANFILES += ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}}
  • src/Makefile.in

    rb067d9b r7951100  
    2121###############################################################################
    2222
     23#SRC +=  ArgTweak/Rewriter.cc \
     24#       ArgTweak/Mutate.cc
     25
    2326######################### -*- Mode: Makefile-Gmake -*- ########################
    2427###############################################################################
    2528
    26 #SRC +=  ArgTweak/Rewriter.cc \
    27 #       ArgTweak/Mutate.cc
    28 
    2929######################### -*- Mode: Makefile-Gmake -*- ########################
    3030###############################################################################
     
    5959######################### -*- Mode: Makefile-Gmake -*- ########################
    6060###############################################################################
    61 
    62 ######################### -*- Mode: Makefile-Gmake -*- ########################
    63 ###############################################################################
    64 
    65 ######################### -*- Mode: Makefile-Gmake -*- ########################
    66 ###############################################################################
    67 
    6861
    6962VPATH = @srcdir@
     
    141134build_triplet = @build@
    142135host_triplet = @host@
    143 cfa_cpplib_PROGRAMS = ../driver/cfa-cpp$(EXEEXT) $(DEMANGLER)
    144 EXTRA_PROGRAMS = demangler$(EXEEXT)
     136cfa_cpplib_PROGRAMS = driver/cfa-cpp$(EXEEXT)
    145137subdir = src
    146138ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    147 am__aclocal_m4_deps = $(top_srcdir)/automake/libtool.m4 \
    148         $(top_srcdir)/automake/ltoptions.m4 \
    149         $(top_srcdir)/automake/ltsugar.m4 \
    150         $(top_srcdir)/automake/ltversion.m4 \
    151         $(top_srcdir)/automake/lt~obsolete.m4 \
    152         $(top_srcdir)/automake/cfa.m4 $(top_srcdir)/configure.ac
     139am__aclocal_m4_deps = $(top_srcdir)/configure.ac
    153140am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    154141        $(ACLOCAL_M4)
     
    158145CONFIG_CLEAN_FILES =
    159146CONFIG_CLEAN_VPATH_FILES =
    160 LIBRARIES = $(noinst_LIBRARIES)
    161 AM_V_AR = $(am__v_AR_@AM_V@)
    162 am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
    163 am__v_AR_0 = @echo "  AR      " $@;
    164 am__v_AR_1 =
    165 libdemangle_a_AR = $(AR) $(ARFLAGS)
    166 libdemangle_a_LIBADD =
    167 am__dirstamp = $(am__leading_dot)dirstamp
    168 am__objects_1 = AST/AssertAcyclic.$(OBJEXT) AST/Attribute.$(OBJEXT) \
    169         AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
    170         AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
    171         AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
    172         AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
    173         AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) AST/Stmt.$(OBJEXT) \
    174         AST/SymbolTable.$(OBJEXT) AST/Type.$(OBJEXT) \
    175         AST/TypeEnvironment.$(OBJEXT) AST/TypeSubstitution.$(OBJEXT)
    176 am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \
    177         CodeGen/FixMain.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \
    178         CodeGen/OperatorTable.$(OBJEXT)
    179 am__objects_3 = Common/Assert.$(OBJEXT) Common/Eval.$(OBJEXT) \
    180         Common/PassVisitor.$(OBJEXT) Common/SemanticError.$(OBJEXT) \
    181         Common/Stats/Counter.$(OBJEXT) Common/Stats/Heap.$(OBJEXT) \
    182         Common/Stats/Stats.$(OBJEXT) Common/Stats/Time.$(OBJEXT) \
    183         Common/UniqueName.$(OBJEXT)
    184 am__objects_4 = ControlStruct/ForExprMutator.$(OBJEXT) \
    185         ControlStruct/LabelFixer.$(OBJEXT) \
    186         ControlStruct/LabelGenerator.$(OBJEXT) \
    187         ControlStruct/MLEMutator.$(OBJEXT) \
    188         ControlStruct/Mutate.$(OBJEXT)
    189 am__objects_5 = ResolvExpr/AdjustExprType.$(OBJEXT) \
    190         ResolvExpr/Alternative.$(OBJEXT) \
    191         ResolvExpr/AlternativeFinder.$(OBJEXT) \
    192         ResolvExpr/Candidate.$(OBJEXT) \
    193         ResolvExpr/CandidateFinder.$(OBJEXT) \
    194         ResolvExpr/CastCost.$(OBJEXT) ResolvExpr/CommonType.$(OBJEXT) \
    195         ResolvExpr/ConversionCost.$(OBJEXT) \
    196         ResolvExpr/CurrentObject.$(OBJEXT) \
    197         ResolvExpr/ExplodedActual.$(OBJEXT) \
    198         ResolvExpr/ExplodedArg.$(OBJEXT) \
    199         ResolvExpr/FindOpenVars.$(OBJEXT) ResolvExpr/Occurs.$(OBJEXT) \
    200         ResolvExpr/PolyCost.$(OBJEXT) \
    201         ResolvExpr/PtrsAssignable.$(OBJEXT) \
    202         ResolvExpr/PtrsCastable.$(OBJEXT) \
    203         ResolvExpr/RenameVars.$(OBJEXT) \
    204         ResolvExpr/ResolveAssertions.$(OBJEXT) \
    205         ResolvExpr/Resolver.$(OBJEXT) \
    206         ResolvExpr/ResolveTypeof.$(OBJEXT) \
    207         ResolvExpr/SatisfyAssertions.$(OBJEXT) \
    208         ResolvExpr/SpecCost.$(OBJEXT) \
    209         ResolvExpr/TypeEnvironment.$(OBJEXT) \
    210         ResolvExpr/Unify.$(OBJEXT)
    211 am__objects_6 = SymTab/Autogen.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \
    212         SymTab/Indexer.$(OBJEXT) SymTab/Mangler.$(OBJEXT) \
    213         SymTab/ManglerCommon.$(OBJEXT) SymTab/Validate.$(OBJEXT)
    214 am__objects_7 = SynTree/Type.$(OBJEXT) SynTree/VoidType.$(OBJEXT) \
    215         SynTree/BasicType.$(OBJEXT) SynTree/PointerType.$(OBJEXT) \
    216         SynTree/ArrayType.$(OBJEXT) SynTree/ReferenceType.$(OBJEXT) \
    217         SynTree/FunctionType.$(OBJEXT) \
    218         SynTree/ReferenceToType.$(OBJEXT) SynTree/TupleType.$(OBJEXT) \
    219         SynTree/TypeofType.$(OBJEXT) SynTree/AttrType.$(OBJEXT) \
    220         SynTree/VarArgsType.$(OBJEXT) SynTree/ZeroOneType.$(OBJEXT) \
    221         SynTree/Constant.$(OBJEXT) SynTree/Expression.$(OBJEXT) \
    222         SynTree/TupleExpr.$(OBJEXT) SynTree/CommaExpr.$(OBJEXT) \
    223         SynTree/TypeExpr.$(OBJEXT) SynTree/ApplicationExpr.$(OBJEXT) \
    224         SynTree/AddressExpr.$(OBJEXT) SynTree/Statement.$(OBJEXT) \
    225         SynTree/CompoundStmt.$(OBJEXT) SynTree/DeclStmt.$(OBJEXT) \
    226         SynTree/Declaration.$(OBJEXT) \
    227         SynTree/DeclarationWithType.$(OBJEXT) \
    228         SynTree/ObjectDecl.$(OBJEXT) SynTree/FunctionDecl.$(OBJEXT) \
    229         SynTree/AggregateDecl.$(OBJEXT) \
    230         SynTree/NamedTypeDecl.$(OBJEXT) SynTree/TypeDecl.$(OBJEXT) \
    231         SynTree/Initializer.$(OBJEXT) \
    232         SynTree/TypeSubstitution.$(OBJEXT) SynTree/Attribute.$(OBJEXT) \
    233         SynTree/DeclReplacer.$(OBJEXT)
    234 am__objects_8 = CompilationState.$(OBJEXT) $(am__objects_1) \
    235         $(am__objects_2) Concurrency/Keywords.$(OBJEXT) \
    236         $(am__objects_3) $(am__objects_4) GenPoly/GenPoly.$(OBJEXT) \
    237         GenPoly/Lvalue.$(OBJEXT) InitTweak/GenInit.$(OBJEXT) \
    238         InitTweak/InitTweak.$(OBJEXT) Parser/LinkageSpec.$(OBJEXT) \
    239         $(am__objects_5) $(am__objects_6) SymTab/Demangle.$(OBJEXT) \
    240         $(am__objects_7) Tuples/TupleAssignment.$(OBJEXT) \
    241         Tuples/TupleExpansion.$(OBJEXT) Tuples/Explode.$(OBJEXT) \
    242         Tuples/Tuples.$(OBJEXT) Validate/HandleAttributes.$(OBJEXT) \
    243         Validate/FindSpecialDecls.$(OBJEXT)
    244 am_libdemangle_a_OBJECTS = $(am__objects_8)
    245 libdemangle_a_OBJECTS = $(am_libdemangle_a_OBJECTS)
    246147am__installdirs = "$(DESTDIR)$(cfa_cpplibdir)"
    247148PROGRAMS = $(cfa_cpplib_PROGRAMS)
    248 am__objects_9 = main.$(OBJEXT) MakeLibCfa.$(OBJEXT) \
    249         CompilationState.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
    250         CodeGen/Generate.$(OBJEXT) CodeGen/FixNames.$(OBJEXT) \
    251         CodeTools/DeclStats.$(OBJEXT) \
    252         CodeTools/ResolvProtoDump.$(OBJEXT) \
    253         CodeTools/TrackLoc.$(OBJEXT) Concurrency/Keywords.$(OBJEXT) \
    254         Concurrency/Waitfor.$(OBJEXT) $(am__objects_3) \
    255         Common/DebugMalloc.$(OBJEXT) $(am__objects_4) \
    256         ControlStruct/ExceptTranslate.$(OBJEXT) GenPoly/Box.$(OBJEXT) \
    257         GenPoly/GenPoly.$(OBJEXT) GenPoly/ScrubTyVars.$(OBJEXT) \
    258         GenPoly/Lvalue.$(OBJEXT) GenPoly/Specialize.$(OBJEXT) \
    259         GenPoly/FindFunction.$(OBJEXT) \
    260         GenPoly/InstantiateGeneric.$(OBJEXT) \
    261         InitTweak/GenInit.$(OBJEXT) InitTweak/FixInit.$(OBJEXT) \
    262         InitTweak/FixGlobalInit.$(OBJEXT) \
    263         InitTweak/InitTweak.$(OBJEXT) Parser/parser.$(OBJEXT) \
    264         Parser/lex.$(OBJEXT) Parser/TypedefTable.$(OBJEXT) \
    265         Parser/ParseNode.$(OBJEXT) Parser/DeclarationNode.$(OBJEXT) \
    266         Parser/ExpressionNode.$(OBJEXT) Parser/StatementNode.$(OBJEXT) \
    267         Parser/InitializerNode.$(OBJEXT) Parser/TypeData.$(OBJEXT) \
    268         Parser/LinkageSpec.$(OBJEXT) Parser/parserutility.$(OBJEXT) \
    269         $(am__objects_5) ResolvExpr/AlternativePrinter.$(OBJEXT) \
    270         $(am__objects_6) $(am__objects_7) \
    271         Tuples/TupleAssignment.$(OBJEXT) \
    272         Tuples/TupleExpansion.$(OBJEXT) Tuples/Explode.$(OBJEXT) \
    273         Tuples/Tuples.$(OBJEXT) Validate/HandleAttributes.$(OBJEXT) \
    274         Validate/FindSpecialDecls.$(OBJEXT) \
    275         Virtual/ExpandCasts.$(OBJEXT)
    276 am____driver_cfa_cpp_OBJECTS = $(am__objects_9)
    277 ___driver_cfa_cpp_OBJECTS = $(am____driver_cfa_cpp_OBJECTS)
    278 am__DEPENDENCIES_1 =
    279 ___driver_cfa_cpp_DEPENDENCIES = $(am__DEPENDENCIES_1) \
    280         $(am__DEPENDENCIES_1)
    281 AM_V_lt = $(am__v_lt_@AM_V@)
    282 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
    283 am__v_lt_0 = --silent
    284 am__v_lt_1 =
    285 am_demangler_OBJECTS = SymTab/demangler.$(OBJEXT)
    286 demangler_OBJECTS = $(am_demangler_OBJECTS)
    287 demangler_DEPENDENCIES = libdemangle.a
     149am__dirstamp = $(am__leading_dot)dirstamp
     150am__objects_1 = driver_cfa_cpp-main.$(OBJEXT) \
     151        driver_cfa_cpp-MakeLibCfa.$(OBJEXT) \
     152        CodeGen/driver_cfa_cpp-Generate.$(OBJEXT) \
     153        CodeGen/driver_cfa_cpp-CodeGenerator.$(OBJEXT) \
     154        CodeGen/driver_cfa_cpp-GenType.$(OBJEXT) \
     155        CodeGen/driver_cfa_cpp-FixNames.$(OBJEXT) \
     156        CodeGen/driver_cfa_cpp-FixMain.$(OBJEXT) \
     157        CodeGen/driver_cfa_cpp-OperatorTable.$(OBJEXT) \
     158        CodeTools/driver_cfa_cpp-DeclStats.$(OBJEXT) \
     159        CodeTools/driver_cfa_cpp-TrackLoc.$(OBJEXT) \
     160        Concurrency/driver_cfa_cpp-Keywords.$(OBJEXT) \
     161        Concurrency/driver_cfa_cpp-Waitfor.$(OBJEXT) \
     162        Common/driver_cfa_cpp-SemanticError.$(OBJEXT) \
     163        Common/driver_cfa_cpp-UniqueName.$(OBJEXT) \
     164        Common/driver_cfa_cpp-DebugMalloc.$(OBJEXT) \
     165        Common/driver_cfa_cpp-Assert.$(OBJEXT) \
     166        Common/driver_cfa_cpp-Heap.$(OBJEXT) \
     167        ControlStruct/driver_cfa_cpp-LabelGenerator.$(OBJEXT) \
     168        ControlStruct/driver_cfa_cpp-LabelFixer.$(OBJEXT) \
     169        ControlStruct/driver_cfa_cpp-MLEMutator.$(OBJEXT) \
     170        ControlStruct/driver_cfa_cpp-Mutate.$(OBJEXT) \
     171        ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT) \
     172        ControlStruct/driver_cfa_cpp-ExceptTranslate.$(OBJEXT) \
     173        GenPoly/driver_cfa_cpp-Box.$(OBJEXT) \
     174        GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT) \
     175        GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT) \
     176        GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT) \
     177        GenPoly/driver_cfa_cpp-Specialize.$(OBJEXT) \
     178        GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \
     179        GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT) \
     180        InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT) \
     181        InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT) \
     182        InitTweak/driver_cfa_cpp-FixGlobalInit.$(OBJEXT) \
     183        InitTweak/driver_cfa_cpp-InitTweak.$(OBJEXT) \
     184        Parser/driver_cfa_cpp-parser.$(OBJEXT) \
     185        Parser/driver_cfa_cpp-lex.$(OBJEXT) \
     186        Parser/driver_cfa_cpp-TypedefTable.$(OBJEXT) \
     187        Parser/driver_cfa_cpp-ParseNode.$(OBJEXT) \
     188        Parser/driver_cfa_cpp-DeclarationNode.$(OBJEXT) \
     189        Parser/driver_cfa_cpp-ExpressionNode.$(OBJEXT) \
     190        Parser/driver_cfa_cpp-StatementNode.$(OBJEXT) \
     191        Parser/driver_cfa_cpp-InitializerNode.$(OBJEXT) \
     192        Parser/driver_cfa_cpp-TypeData.$(OBJEXT) \
     193        Parser/driver_cfa_cpp-LinkageSpec.$(OBJEXT) \
     194        Parser/driver_cfa_cpp-parserutility.$(OBJEXT) \
     195        ResolvExpr/driver_cfa_cpp-AlternativeFinder.$(OBJEXT) \
     196        ResolvExpr/driver_cfa_cpp-Alternative.$(OBJEXT) \
     197        ResolvExpr/driver_cfa_cpp-Unify.$(OBJEXT) \
     198        ResolvExpr/driver_cfa_cpp-PtrsAssignable.$(OBJEXT) \
     199        ResolvExpr/driver_cfa_cpp-CommonType.$(OBJEXT) \
     200        ResolvExpr/driver_cfa_cpp-ConversionCost.$(OBJEXT) \
     201        ResolvExpr/driver_cfa_cpp-CastCost.$(OBJEXT) \
     202        ResolvExpr/driver_cfa_cpp-PtrsCastable.$(OBJEXT) \
     203        ResolvExpr/driver_cfa_cpp-AdjustExprType.$(OBJEXT) \
     204        ResolvExpr/driver_cfa_cpp-AlternativePrinter.$(OBJEXT) \
     205        ResolvExpr/driver_cfa_cpp-Resolver.$(OBJEXT) \
     206        ResolvExpr/driver_cfa_cpp-ResolveTypeof.$(OBJEXT) \
     207        ResolvExpr/driver_cfa_cpp-RenameVars.$(OBJEXT) \
     208        ResolvExpr/driver_cfa_cpp-FindOpenVars.$(OBJEXT) \
     209        ResolvExpr/driver_cfa_cpp-PolyCost.$(OBJEXT) \
     210        ResolvExpr/driver_cfa_cpp-Occurs.$(OBJEXT) \
     211        ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT) \
     212        ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT) \
     213        ResolvExpr/driver_cfa_cpp-ExplodedActual.$(OBJEXT) \
     214        SymTab/driver_cfa_cpp-Indexer.$(OBJEXT) \
     215        SymTab/driver_cfa_cpp-Mangler.$(OBJEXT) \
     216        SymTab/driver_cfa_cpp-Validate.$(OBJEXT) \
     217        SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT) \
     218        SymTab/driver_cfa_cpp-Autogen.$(OBJEXT) \
     219        SynTree/driver_cfa_cpp-Type.$(OBJEXT) \
     220        SynTree/driver_cfa_cpp-VoidType.$(OBJEXT) \
     221        SynTree/driver_cfa_cpp-BasicType.$(OBJEXT) \
     222        SynTree/driver_cfa_cpp-PointerType.$(OBJEXT) \
     223        SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT) \
     224        SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT) \
     225        SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT) \
     226        SynTree/driver_cfa_cpp-ReferenceToType.$(OBJEXT) \
     227        SynTree/driver_cfa_cpp-TupleType.$(OBJEXT) \
     228        SynTree/driver_cfa_cpp-TypeofType.$(OBJEXT) \
     229        SynTree/driver_cfa_cpp-AttrType.$(OBJEXT) \
     230        SynTree/driver_cfa_cpp-VarArgsType.$(OBJEXT) \
     231        SynTree/driver_cfa_cpp-ZeroOneType.$(OBJEXT) \
     232        SynTree/driver_cfa_cpp-Constant.$(OBJEXT) \
     233        SynTree/driver_cfa_cpp-Expression.$(OBJEXT) \
     234        SynTree/driver_cfa_cpp-TupleExpr.$(OBJEXT) \
     235        SynTree/driver_cfa_cpp-CommaExpr.$(OBJEXT) \
     236        SynTree/driver_cfa_cpp-TypeExpr.$(OBJEXT) \
     237        SynTree/driver_cfa_cpp-ApplicationExpr.$(OBJEXT) \
     238        SynTree/driver_cfa_cpp-AddressExpr.$(OBJEXT) \
     239        SynTree/driver_cfa_cpp-Statement.$(OBJEXT) \
     240        SynTree/driver_cfa_cpp-CompoundStmt.$(OBJEXT) \
     241        SynTree/driver_cfa_cpp-DeclStmt.$(OBJEXT) \
     242        SynTree/driver_cfa_cpp-Declaration.$(OBJEXT) \
     243        SynTree/driver_cfa_cpp-DeclarationWithType.$(OBJEXT) \
     244        SynTree/driver_cfa_cpp-ObjectDecl.$(OBJEXT) \
     245        SynTree/driver_cfa_cpp-FunctionDecl.$(OBJEXT) \
     246        SynTree/driver_cfa_cpp-AggregateDecl.$(OBJEXT) \
     247        SynTree/driver_cfa_cpp-NamedTypeDecl.$(OBJEXT) \
     248        SynTree/driver_cfa_cpp-TypeDecl.$(OBJEXT) \
     249        SynTree/driver_cfa_cpp-Initializer.$(OBJEXT) \
     250        SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
     251        SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
     252        SynTree/driver_cfa_cpp-DeclReplacer.$(OBJEXT) \
     253        Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT) \
     254        Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT) \
     255        Tuples/driver_cfa_cpp-Explode.$(OBJEXT) \
     256        Virtual/driver_cfa_cpp-ExpandCasts.$(OBJEXT)
     257am_driver_cfa_cpp_OBJECTS = $(am__objects_1)
     258driver_cfa_cpp_OBJECTS = $(am_driver_cfa_cpp_OBJECTS)
     259driver_cfa_cpp_DEPENDENCIES =
     260driver_cfa_cpp_LINK = $(CXXLD) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) \
     261        $(driver_cfa_cpp_LDFLAGS) $(LDFLAGS) -o $@
    288262AM_V_P = $(am__v_P_@AM_V@)
    289263am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    302276am__depfiles_maybe = depfiles
    303277am__mv = mv -f
     278AM_V_lt = $(am__v_lt_@AM_V@)
     279am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
     280am__v_lt_0 = --silent
     281am__v_lt_1 =
    304282CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
    305283        $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
    306 LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
    307         $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
    308         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
    309         $(AM_CXXFLAGS) $(CXXFLAGS)
    310284AM_V_CXX = $(am__v_CXX_@AM_V@)
    311285am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
     
    313287am__v_CXX_1 =
    314288CXXLD = $(CXX)
    315 CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
    316         $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
    317         $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
     289CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
     290        -o $@
    318291AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
    319292am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
    320293am__v_CXXLD_0 = @echo "  CXXLD   " $@;
    321294am__v_CXXLD_1 =
     295@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
    322296LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
    323 LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
    324         $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
    325297AM_V_LEX = $(am__v_LEX_@AM_V@)
    326298am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
     
    328300am__v_LEX_1 =
    329301YLWRAP = $(top_srcdir)/automake/ylwrap
     302@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
    330303am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
    331304                   -e s/c++$$/h++/ -e s/c$$/h/
    332305YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
    333 LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
    334         $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
    335306AM_V_YACC = $(am__v_YACC_@AM_V@)
    336307am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
     
    339310COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    340311        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    341 LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    342         $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
    343         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
    344         $(AM_CFLAGS) $(CFLAGS)
    345312AM_V_CC = $(am__v_CC_@AM_V@)
    346313am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
     
    348315am__v_CC_1 =
    349316CCLD = $(CC)
    350 LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    351         $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
    352         $(AM_LDFLAGS) $(LDFLAGS) -o $@
     317LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    353318AM_V_CCLD = $(am__v_CCLD_@AM_V@)
    354319am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
    355320am__v_CCLD_0 = @echo "  CCLD    " $@;
    356321am__v_CCLD_1 =
    357 SOURCES = $(libdemangle_a_SOURCES) $(___driver_cfa_cpp_SOURCES) \
    358         $(demangler_SOURCES)
    359 DIST_SOURCES = $(libdemangle_a_SOURCES) $(___driver_cfa_cpp_SOURCES) \
    360         $(demangler_SOURCES)
     322SOURCES = $(driver_cfa_cpp_SOURCES)
     323DIST_SOURCES = $(driver_cfa_cpp_SOURCES)
    361324am__can_run_installinfo = \
    362325  case $$AM_UPDATE_INFO_DIR in \
     
    364327    *) (install-info --version) >/dev/null 2>&1;; \
    365328  esac
    366 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
    367         $(LISP)config.h.in
     329am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
    368330# Read a list of newline-separated strings from the standard input,
    369331# and print each of them once, without duplicates.  Input order is
     
    384346ETAGS = etags
    385347CTAGS = ctags
    386 am__DIST_COMMON = $(srcdir)/AST/module.mk $(srcdir)/CodeGen/module.mk \
     348am__DIST_COMMON = $(srcdir)/CodeGen/module.mk \
    387349        $(srcdir)/CodeTools/module.mk $(srcdir)/Common/module.mk \
    388350        $(srcdir)/Concurrency/module.mk \
     
    391353        $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk \
    392354        $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk \
    393         $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk \
    394         $(srcdir)/Virtual/module.mk $(top_srcdir)/automake/depcomp \
    395         $(top_srcdir)/automake/ylwrap Parser/lex.cc Parser/parser.cc \
    396         Parser/parser.hh
     355        $(srcdir)/Tuples/module.mk $(srcdir)/Virtual/module.mk \
     356        $(top_srcdir)/automake/depcomp $(top_srcdir)/automake/ylwrap \
     357        Parser/lex.cc Parser/parser.cc Parser/parser.hh
    397358DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    398359ACLOCAL = @ACLOCAL@
     360ALLOCA = @ALLOCA@
    399361AMTAR = @AMTAR@
    400362AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
    401 AR = @AR@
    402363AUTOCONF = @AUTOCONF@
    403364AUTOHEADER = @AUTOHEADER@
    404365AUTOMAKE = @AUTOMAKE@
    405366AWK = @AWK@
    406 BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
     367BACKEND_CC = @BACKEND_CC@
    407368CC = @CC@
    408369CCAS = @CCAS@
     
    410371CCASFLAGS = @CCASFLAGS@
    411372CCDEPMODE = @CCDEPMODE@
    412 CFACC = @CFACC@
    413 CFACC_INSTALL = @CFACC_INSTALL@
    414 CFACPP = @CFACPP@
    415373CFA_BACKEND_CC = @CFA_BACKEND_CC@
    416374CFA_BINDIR = @CFA_BINDIR@
     
    424382CPPFLAGS = @CPPFLAGS@
    425383CXX = @CXX@
    426 CXXCPP = @CXXCPP@
    427384CXXDEPMODE = @CXXDEPMODE@
    428385CXXFLAGS = @CXXFLAGS@
    429386CYGPATH_W = @CYGPATH_W@
    430387DEFS = @DEFS@
    431 DEMANGLER = @DEMANGLER@
    432388DEPDIR = @DEPDIR@
    433 DLLTOOL = @DLLTOOL@
    434 DRIVER_DIR = @DRIVER_DIR@
    435 DSYMUTIL = @DSYMUTIL@
    436 DUMPBIN = @DUMPBIN@
    437389ECHO_C = @ECHO_C@
    438390ECHO_N = @ECHO_N@
     
    440392EGREP = @EGREP@
    441393EXEEXT = @EXEEXT@
    442 FGREP = @FGREP@
    443394GREP = @GREP@
    444 HAS_DISTCC = @HAS_DISTCC@
    445 HOST_FLAGS = @HOST_FLAGS@
    446395INSTALL = @INSTALL@
    447396INSTALL_DATA = @INSTALL_DATA@
     
    449398INSTALL_SCRIPT = @INSTALL_SCRIPT@
    450399INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
    451 LD = @LD@
    452400LDFLAGS = @LDFLAGS@
    453401LEX = @LEX@
    454402LEXLIB = @LEXLIB@
    455403LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
    456 LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
    457 LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
    458 LIBDEMANGLE = @LIBDEMANGLE@
    459404LIBOBJS = @LIBOBJS@
    460405LIBS = @LIBS@
    461 LIBTOOL = @LIBTOOL@
    462 LIPO = @LIPO@
    463 LN_S = @LN_S@
    464406LTLIBOBJS = @LTLIBOBJS@
    465 LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
     407MACHINE_TYPE = @MACHINE_TYPE@
     408MAINT = @MAINT@
    466409MAKEINFO = @MAKEINFO@
    467 MANIFEST_TOOL = @MANIFEST_TOOL@
    468410MKDIR_P = @MKDIR_P@
    469 NM = @NM@
    470 NMEDIT = @NMEDIT@
    471 OBJDUMP = @OBJDUMP@
    472411OBJEXT = @OBJEXT@
    473 OTOOL = @OTOOL@
    474 OTOOL64 = @OTOOL64@
    475412PACKAGE = @PACKAGE@
    476413PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    482419PATH_SEPARATOR = @PATH_SEPARATOR@
    483420RANLIB = @RANLIB@
    484 SED = @SED@
    485421SET_MAKE = @SET_MAKE@
    486422SHELL = @SHELL@
    487423STRIP = @STRIP@
    488 TARGET_HOSTS = @TARGET_HOSTS@
    489424VERSION = @VERSION@
    490425YACC = @YACC@
     
    494429abs_top_builddir = @abs_top_builddir@
    495430abs_top_srcdir = @abs_top_srcdir@
    496 ac_ct_AR = @ac_ct_AR@
    497431ac_ct_CC = @ac_ct_CC@
    498432ac_ct_CXX = @ac_ct_CXX@
    499 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    500433am__include = @am__include@
    501434am__leading_dot = @am__leading_dot@
     
    546479
    547480# create object files in directory with source files
    548 AUTOMAKE_OPTIONS = foreign subdir-objects
    549 ACLOCAL_AMFLAGS = -I automake
    550 SRC = main.cc MakeLibCfa.cc CompilationState.cc $(SRC_AST) \
    551         $(SRC_CODEGEN) CodeGen/Generate.cc CodeGen/FixNames.cc \
    552         CodeTools/DeclStats.cc CodeTools/ResolvProtoDump.cc \
     481AUTOMAKE_OPTIONS = subdir-objects
     482SRC = main.cc MakeLibCfa.cc CodeGen/Generate.cc \
     483        CodeGen/CodeGenerator.cc CodeGen/GenType.cc \
     484        CodeGen/FixNames.cc CodeGen/FixMain.cc \
     485        CodeGen/OperatorTable.cc CodeTools/DeclStats.cc \
    553486        CodeTools/TrackLoc.cc Concurrency/Keywords.cc \
    554         Concurrency/Waitfor.cc $(SRC_COMMON) Common/DebugMalloc.cc \
    555         $(SRC_CONTROLSTRUCT) ControlStruct/ExceptTranslate.cc \
    556         GenPoly/Box.cc GenPoly/GenPoly.cc GenPoly/ScrubTyVars.cc \
    557         GenPoly/Lvalue.cc GenPoly/Specialize.cc \
    558         GenPoly/FindFunction.cc GenPoly/InstantiateGeneric.cc \
    559         InitTweak/GenInit.cc InitTweak/FixInit.cc \
    560         InitTweak/FixGlobalInit.cc InitTweak/InitTweak.cc \
    561         Parser/parser.yy Parser/lex.ll Parser/TypedefTable.cc \
    562         Parser/ParseNode.cc Parser/DeclarationNode.cc \
    563         Parser/ExpressionNode.cc Parser/StatementNode.cc \
    564         Parser/InitializerNode.cc Parser/TypeData.cc \
    565         Parser/LinkageSpec.cc Parser/parserutility.cc \
    566         $(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc \
    567         $(SRC_SYMTAB) $(SRC_SYNTREE) Tuples/TupleAssignment.cc \
    568         Tuples/TupleExpansion.cc Tuples/Explode.cc Tuples/Tuples.cc \
    569         Validate/HandleAttributes.cc Validate/FindSpecialDecls.cc \
    570         Virtual/ExpandCasts.cc
    571 SRCDEMANGLE = CompilationState.cc $(SRC_AST) $(SRC_CODEGEN) \
    572         Concurrency/Keywords.cc $(SRC_COMMON) $(SRC_CONTROLSTRUCT) \
    573         GenPoly/GenPoly.cc GenPoly/Lvalue.cc InitTweak/GenInit.cc \
    574         InitTweak/InitTweak.cc Parser/LinkageSpec.cc $(SRC_RESOLVEXPR) \
    575         $(SRC_SYMTAB) SymTab/Demangle.cc $(SRC_SYNTREE) \
     487        Concurrency/Waitfor.cc Common/SemanticError.cc \
     488        Common/UniqueName.cc Common/DebugMalloc.cc Common/Assert.cc \
     489        Common/Heap.cc ControlStruct/LabelGenerator.cc \
     490        ControlStruct/LabelFixer.cc ControlStruct/MLEMutator.cc \
     491        ControlStruct/Mutate.cc ControlStruct/ForExprMutator.cc \
     492        ControlStruct/ExceptTranslate.cc GenPoly/Box.cc \
     493        GenPoly/GenPoly.cc GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc \
     494        GenPoly/Specialize.cc GenPoly/FindFunction.cc \
     495        GenPoly/InstantiateGeneric.cc InitTweak/GenInit.cc \
     496        InitTweak/FixInit.cc InitTweak/FixGlobalInit.cc \
     497        InitTweak/InitTweak.cc Parser/parser.yy Parser/lex.ll \
     498        Parser/TypedefTable.cc Parser/ParseNode.cc \
     499        Parser/DeclarationNode.cc Parser/ExpressionNode.cc \
     500        Parser/StatementNode.cc Parser/InitializerNode.cc \
     501        Parser/TypeData.cc Parser/LinkageSpec.cc \
     502        Parser/parserutility.cc ResolvExpr/AlternativeFinder.cc \
     503        ResolvExpr/Alternative.cc ResolvExpr/Unify.cc \
     504        ResolvExpr/PtrsAssignable.cc ResolvExpr/CommonType.cc \
     505        ResolvExpr/ConversionCost.cc ResolvExpr/CastCost.cc \
     506        ResolvExpr/PtrsCastable.cc ResolvExpr/AdjustExprType.cc \
     507        ResolvExpr/AlternativePrinter.cc ResolvExpr/Resolver.cc \
     508        ResolvExpr/ResolveTypeof.cc ResolvExpr/RenameVars.cc \
     509        ResolvExpr/FindOpenVars.cc ResolvExpr/PolyCost.cc \
     510        ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \
     511        ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \
     512        SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \
     513        SymTab/FixFunction.cc SymTab/Autogen.cc SynTree/Type.cc \
     514        SynTree/VoidType.cc SynTree/BasicType.cc \
     515        SynTree/PointerType.cc SynTree/ArrayType.cc \
     516        SynTree/ReferenceType.cc SynTree/FunctionType.cc \
     517        SynTree/ReferenceToType.cc SynTree/TupleType.cc \
     518        SynTree/TypeofType.cc SynTree/AttrType.cc \
     519        SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \
     520        SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \
     521        SynTree/CommaExpr.cc SynTree/TypeExpr.cc \
     522        SynTree/ApplicationExpr.cc SynTree/AddressExpr.cc \
     523        SynTree/Statement.cc SynTree/CompoundStmt.cc \
     524        SynTree/DeclStmt.cc SynTree/Declaration.cc \
     525        SynTree/DeclarationWithType.cc SynTree/ObjectDecl.cc \
     526        SynTree/FunctionDecl.cc SynTree/AggregateDecl.cc \
     527        SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \
     528        SynTree/Initializer.cc SynTree/TypeSubstitution.cc \
     529        SynTree/Attribute.cc SynTree/DeclReplacer.cc \
    576530        Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
    577         Tuples/Explode.cc Tuples/Tuples.cc \
    578         Validate/HandleAttributes.cc Validate/FindSpecialDecls.cc
    579 MAINTAINERCLEANFILES = ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}}
    580 MOSTLYCLEANFILES = Parser/lex.cc Parser/parser.cc Parser/parser.hh \
    581         Parser/parser.output
    582 @WITH_LIBPROFILER_TRUE@LIBPROFILER = -lprofiler
    583 @WITH_LIBTCMALLOC_TRUE@LIBTCMALLOC = -ltcmalloc
    584 @WITH_LIBTCMALLOC_TRUE@TCMALLOCFLAG = -DTCMALLOC
    585 SRC_AST = \
    586         AST/AssertAcyclic.cpp \
    587         AST/Attribute.cpp \
    588         AST/Convert.cpp \
    589         AST/Decl.cpp \
    590         AST/DeclReplacer.cpp \
    591         AST/Expr.cpp \
    592         AST/GenericSubstitution.cpp \
    593         AST/Init.cpp \
    594         AST/LinkageSpec.cpp \
    595         AST/Node.cpp \
    596         AST/Pass.cpp \
    597         AST/Print.cpp \
    598         AST/Stmt.cpp \
    599         AST/SymbolTable.cpp \
    600         AST/Type.cpp \
    601         AST/TypeEnvironment.cpp \
    602         AST/TypeSubstitution.cpp
    603 
    604 SRC_CODEGEN = \
    605         CodeGen/CodeGenerator.cc \
    606         CodeGen/FixMain.cc \
    607         CodeGen/GenType.cc \
    608         CodeGen/OperatorTable.cc
    609 
    610 SRC_COMMON = \
    611       Common/Assert.cc \
    612       Common/Eval.cc \
    613       Common/PassVisitor.cc \
    614       Common/SemanticError.cc \
    615       Common/Stats/Counter.cc \
    616       Common/Stats/Heap.cc \
    617       Common/Stats/Stats.cc \
    618       Common/Stats/Time.cc \
    619       Common/UniqueName.cc
    620 
    621 SRC_CONTROLSTRUCT = \
    622         ControlStruct/ForExprMutator.cc \
    623         ControlStruct/LabelFixer.cc \
    624         ControlStruct/LabelGenerator.cc \
    625         ControlStruct/MLEMutator.cc \
    626         ControlStruct/Mutate.cc
    627 
     531        Tuples/Explode.cc Virtual/ExpandCasts.cc
     532MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
     533        ${cfa_cpplib_PROGRAMS}}
    628534BUILT_SOURCES = Parser/parser.hh
    629535AM_YFLAGS = -d -t -v
    630 SRC_RESOLVEXPR = \
    631       ResolvExpr/AdjustExprType.cc \
    632       ResolvExpr/Alternative.cc \
    633       ResolvExpr/AlternativeFinder.cc \
    634       ResolvExpr/Candidate.cpp \
    635       ResolvExpr/CandidateFinder.cpp \
    636       ResolvExpr/CastCost.cc \
    637       ResolvExpr/CommonType.cc \
    638       ResolvExpr/ConversionCost.cc \
    639       ResolvExpr/CurrentObject.cc \
    640       ResolvExpr/ExplodedActual.cc \
    641       ResolvExpr/ExplodedArg.cpp \
    642       ResolvExpr/FindOpenVars.cc \
    643       ResolvExpr/Occurs.cc \
    644       ResolvExpr/PolyCost.cc \
    645       ResolvExpr/PtrsAssignable.cc \
    646       ResolvExpr/PtrsCastable.cc \
    647       ResolvExpr/RenameVars.cc \
    648       ResolvExpr/ResolveAssertions.cc \
    649       ResolvExpr/Resolver.cc \
    650       ResolvExpr/ResolveTypeof.cc \
    651       ResolvExpr/SatisfyAssertions.cpp \
    652       ResolvExpr/SpecCost.cc \
    653       ResolvExpr/TypeEnvironment.cc \
    654       ResolvExpr/Unify.cc
    655 
    656 SRC_SYMTAB = \
    657       SymTab/Autogen.cc \
    658       SymTab/FixFunction.cc \
    659       SymTab/Indexer.cc \
    660       SymTab/Mangler.cc \
    661       SymTab/ManglerCommon.cc \
    662       SymTab/Validate.cc
    663 
    664 SRC_SYNTREE = \
    665       SynTree/Type.cc \
    666       SynTree/VoidType.cc \
    667       SynTree/BasicType.cc \
    668       SynTree/PointerType.cc \
    669       SynTree/ArrayType.cc \
    670       SynTree/ReferenceType.cc \
    671       SynTree/FunctionType.cc \
    672       SynTree/ReferenceToType.cc \
    673       SynTree/TupleType.cc \
    674       SynTree/TypeofType.cc \
    675       SynTree/AttrType.cc \
    676       SynTree/VarArgsType.cc \
    677       SynTree/ZeroOneType.cc \
    678       SynTree/Constant.cc \
    679       SynTree/Expression.cc \
    680       SynTree/TupleExpr.cc \
    681       SynTree/CommaExpr.cc \
    682       SynTree/TypeExpr.cc \
    683       SynTree/ApplicationExpr.cc \
    684       SynTree/AddressExpr.cc \
    685       SynTree/Statement.cc \
    686       SynTree/CompoundStmt.cc \
    687       SynTree/DeclStmt.cc \
    688       SynTree/Declaration.cc \
    689       SynTree/DeclarationWithType.cc \
    690       SynTree/ObjectDecl.cc \
    691       SynTree/FunctionDecl.cc \
    692       SynTree/AggregateDecl.cc \
    693       SynTree/NamedTypeDecl.cc \
    694       SynTree/TypeDecl.cc \
    695       SynTree/Initializer.cc \
    696       SynTree/TypeSubstitution.cc \
    697       SynTree/Attribute.cc \
    698       SynTree/DeclReplacer.cc
    699 
     536
     537# Is there a way to use a variable for the directory names?
    700538
    701539# put into lib for now
    702 cfa_cpplibdir = $(CFA_LIBDIR)
    703 ___driver_cfa_cpp_SOURCES = $(SRC)
    704 ___driver_cfa_cpp_LDADD = -ldl $(LIBPROFILER) $(LIBTCMALLOC)
    705 AM_CXXFLAGS = @HOST_FLAGS@ -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I./Parser -I$(srcdir)/Parser -I$(srcdir)/include -DYY_NO_INPUT -O3 -g -std=c++14 $(TCMALLOCFLAG)
    706 AM_LDFLAGS = @HOST_FLAGS@ -Xlinker -export-dynamic
    707 ARFLAGS = cr
    708 demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
    709 demangler_LDADD = libdemangle.a -ldl                    # yywrap
    710 noinst_LIBRARIES = $(LIBDEMANGLE)
    711 EXTRA_LIBRARIES = libdemangle.a
    712 libdemangle_a_SOURCES = $(SRCDEMANGLE)
     540cfa_cpplibdir = ${CFA_LIBDIR}
     541driver_cfa_cpp_SOURCES = ${SRC}
     542driver_cfa_cpp_LDADD = -ldl                     # yywrap
     543driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I${abs_top_srcdir}/src/include -DYY_NO_INPUT -O2 -g -std=c++14
     544driver_cfa_cpp_LDFLAGS = -Xlinker -export-dynamic
    713545all: $(BUILT_SOURCES)
    714546        $(MAKE) $(AM_MAKEFLAGS) all-am
    715547
    716548.SUFFIXES:
    717 .SUFFIXES: .cc .cpp .ll .lo .o .obj .yy
    718 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/AST/module.mk $(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk $(srcdir)/Virtual/module.mk $(am__configure_deps)
     549.SUFFIXES: .cc .ll .o .obj .yy
     550$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Virtual/module.mk $(am__configure_deps)
    719551        @for dep in $?; do \
    720552          case '$(am__configure_deps)' in \
     
    736568            cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
    737569        esac;
    738 $(srcdir)/AST/module.mk $(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk $(srcdir)/Virtual/module.mk $(am__empty):
     570$(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Virtual/module.mk $(am__empty):
    739571
    740572$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
    741573        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    742574
    743 $(top_srcdir)/configure: $(am__configure_deps)
     575$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
    744576        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    745 $(ACLOCAL_M4): $(am__aclocal_m4_deps)
     577$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
    746578        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    747579$(am__aclocal_m4_deps):
    748 
    749 clean-noinstLIBRARIES:
    750         -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
    751 AST/$(am__dirstamp):
    752         @$(MKDIR_P) AST
    753         @: > AST/$(am__dirstamp)
    754 AST/$(DEPDIR)/$(am__dirstamp):
    755         @$(MKDIR_P) AST/$(DEPDIR)
    756         @: > AST/$(DEPDIR)/$(am__dirstamp)
    757 AST/AssertAcyclic.$(OBJEXT): AST/$(am__dirstamp) \
    758         AST/$(DEPDIR)/$(am__dirstamp)
    759 AST/Attribute.$(OBJEXT): AST/$(am__dirstamp) \
    760         AST/$(DEPDIR)/$(am__dirstamp)
    761 AST/Convert.$(OBJEXT): AST/$(am__dirstamp) \
    762         AST/$(DEPDIR)/$(am__dirstamp)
    763 AST/Decl.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    764 AST/DeclReplacer.$(OBJEXT): AST/$(am__dirstamp) \
    765         AST/$(DEPDIR)/$(am__dirstamp)
    766 AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    767 AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
    768         AST/$(DEPDIR)/$(am__dirstamp)
    769 AST/Init.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    770 AST/LinkageSpec.$(OBJEXT): AST/$(am__dirstamp) \
    771         AST/$(DEPDIR)/$(am__dirstamp)
    772 AST/Node.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    773 AST/Pass.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    774 AST/Print.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    775 AST/Stmt.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    776 AST/SymbolTable.$(OBJEXT): AST/$(am__dirstamp) \
    777         AST/$(DEPDIR)/$(am__dirstamp)
    778 AST/Type.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    779 AST/TypeEnvironment.$(OBJEXT): AST/$(am__dirstamp) \
    780         AST/$(DEPDIR)/$(am__dirstamp)
    781 AST/TypeSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
    782         AST/$(DEPDIR)/$(am__dirstamp)
    783 CodeGen/$(am__dirstamp):
    784         @$(MKDIR_P) CodeGen
    785         @: > CodeGen/$(am__dirstamp)
    786 CodeGen/$(DEPDIR)/$(am__dirstamp):
    787         @$(MKDIR_P) CodeGen/$(DEPDIR)
    788         @: > CodeGen/$(DEPDIR)/$(am__dirstamp)
    789 CodeGen/CodeGenerator.$(OBJEXT): CodeGen/$(am__dirstamp) \
    790         CodeGen/$(DEPDIR)/$(am__dirstamp)
    791 CodeGen/FixMain.$(OBJEXT): CodeGen/$(am__dirstamp) \
    792         CodeGen/$(DEPDIR)/$(am__dirstamp)
    793 CodeGen/GenType.$(OBJEXT): CodeGen/$(am__dirstamp) \
    794         CodeGen/$(DEPDIR)/$(am__dirstamp)
    795 CodeGen/OperatorTable.$(OBJEXT): CodeGen/$(am__dirstamp) \
    796         CodeGen/$(DEPDIR)/$(am__dirstamp)
    797 Concurrency/$(am__dirstamp):
    798         @$(MKDIR_P) Concurrency
    799         @: > Concurrency/$(am__dirstamp)
    800 Concurrency/$(DEPDIR)/$(am__dirstamp):
    801         @$(MKDIR_P) Concurrency/$(DEPDIR)
    802         @: > Concurrency/$(DEPDIR)/$(am__dirstamp)
    803 Concurrency/Keywords.$(OBJEXT): Concurrency/$(am__dirstamp) \
    804         Concurrency/$(DEPDIR)/$(am__dirstamp)
    805 Common/$(am__dirstamp):
    806         @$(MKDIR_P) Common
    807         @: > Common/$(am__dirstamp)
    808 Common/$(DEPDIR)/$(am__dirstamp):
    809         @$(MKDIR_P) Common/$(DEPDIR)
    810         @: > Common/$(DEPDIR)/$(am__dirstamp)
    811 Common/Assert.$(OBJEXT): Common/$(am__dirstamp) \
    812         Common/$(DEPDIR)/$(am__dirstamp)
    813 Common/Eval.$(OBJEXT): Common/$(am__dirstamp) \
    814         Common/$(DEPDIR)/$(am__dirstamp)
    815 Common/PassVisitor.$(OBJEXT): Common/$(am__dirstamp) \
    816         Common/$(DEPDIR)/$(am__dirstamp)
    817 Common/SemanticError.$(OBJEXT): Common/$(am__dirstamp) \
    818         Common/$(DEPDIR)/$(am__dirstamp)
    819 Common/Stats/$(am__dirstamp):
    820         @$(MKDIR_P) Common/Stats
    821         @: > Common/Stats/$(am__dirstamp)
    822 Common/Stats/$(DEPDIR)/$(am__dirstamp):
    823         @$(MKDIR_P) Common/Stats/$(DEPDIR)
    824         @: > Common/Stats/$(DEPDIR)/$(am__dirstamp)
    825 Common/Stats/Counter.$(OBJEXT): Common/Stats/$(am__dirstamp) \
    826         Common/Stats/$(DEPDIR)/$(am__dirstamp)
    827 Common/Stats/Heap.$(OBJEXT): Common/Stats/$(am__dirstamp) \
    828         Common/Stats/$(DEPDIR)/$(am__dirstamp)
    829 Common/Stats/Stats.$(OBJEXT): Common/Stats/$(am__dirstamp) \
    830         Common/Stats/$(DEPDIR)/$(am__dirstamp)
    831 Common/Stats/Time.$(OBJEXT): Common/Stats/$(am__dirstamp) \
    832         Common/Stats/$(DEPDIR)/$(am__dirstamp)
    833 Common/UniqueName.$(OBJEXT): Common/$(am__dirstamp) \
    834         Common/$(DEPDIR)/$(am__dirstamp)
    835 ControlStruct/$(am__dirstamp):
    836         @$(MKDIR_P) ControlStruct
    837         @: > ControlStruct/$(am__dirstamp)
    838 ControlStruct/$(DEPDIR)/$(am__dirstamp):
    839         @$(MKDIR_P) ControlStruct/$(DEPDIR)
    840         @: > ControlStruct/$(DEPDIR)/$(am__dirstamp)
    841 ControlStruct/ForExprMutator.$(OBJEXT): ControlStruct/$(am__dirstamp) \
    842         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    843 ControlStruct/LabelFixer.$(OBJEXT): ControlStruct/$(am__dirstamp) \
    844         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    845 ControlStruct/LabelGenerator.$(OBJEXT): ControlStruct/$(am__dirstamp) \
    846         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    847 ControlStruct/MLEMutator.$(OBJEXT): ControlStruct/$(am__dirstamp) \
    848         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    849 ControlStruct/Mutate.$(OBJEXT): ControlStruct/$(am__dirstamp) \
    850         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    851 GenPoly/$(am__dirstamp):
    852         @$(MKDIR_P) GenPoly
    853         @: > GenPoly/$(am__dirstamp)
    854 GenPoly/$(DEPDIR)/$(am__dirstamp):
    855         @$(MKDIR_P) GenPoly/$(DEPDIR)
    856         @: > GenPoly/$(DEPDIR)/$(am__dirstamp)
    857 GenPoly/GenPoly.$(OBJEXT): GenPoly/$(am__dirstamp) \
    858         GenPoly/$(DEPDIR)/$(am__dirstamp)
    859 GenPoly/Lvalue.$(OBJEXT): GenPoly/$(am__dirstamp) \
    860         GenPoly/$(DEPDIR)/$(am__dirstamp)
    861 InitTweak/$(am__dirstamp):
    862         @$(MKDIR_P) InitTweak
    863         @: > InitTweak/$(am__dirstamp)
    864 InitTweak/$(DEPDIR)/$(am__dirstamp):
    865         @$(MKDIR_P) InitTweak/$(DEPDIR)
    866         @: > InitTweak/$(DEPDIR)/$(am__dirstamp)
    867 InitTweak/GenInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
    868         InitTweak/$(DEPDIR)/$(am__dirstamp)
    869 InitTweak/InitTweak.$(OBJEXT): InitTweak/$(am__dirstamp) \
    870         InitTweak/$(DEPDIR)/$(am__dirstamp)
    871 Parser/$(am__dirstamp):
    872         @$(MKDIR_P) Parser
    873         @: > Parser/$(am__dirstamp)
    874 Parser/$(DEPDIR)/$(am__dirstamp):
    875         @$(MKDIR_P) Parser/$(DEPDIR)
    876         @: > Parser/$(DEPDIR)/$(am__dirstamp)
    877 Parser/LinkageSpec.$(OBJEXT): Parser/$(am__dirstamp) \
    878         Parser/$(DEPDIR)/$(am__dirstamp)
    879 ResolvExpr/$(am__dirstamp):
    880         @$(MKDIR_P) ResolvExpr
    881         @: > ResolvExpr/$(am__dirstamp)
    882 ResolvExpr/$(DEPDIR)/$(am__dirstamp):
    883         @$(MKDIR_P) ResolvExpr/$(DEPDIR)
    884         @: > ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    885 ResolvExpr/AdjustExprType.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    886         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    887 ResolvExpr/Alternative.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    888         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    889 ResolvExpr/AlternativeFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    890         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    891 ResolvExpr/Candidate.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    892         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    893 ResolvExpr/CandidateFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    894         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    895 ResolvExpr/CastCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    896         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    897 ResolvExpr/CommonType.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    898         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    899 ResolvExpr/ConversionCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    900         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    901 ResolvExpr/CurrentObject.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    902         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    903 ResolvExpr/ExplodedActual.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    904         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    905 ResolvExpr/ExplodedArg.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    906         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    907 ResolvExpr/FindOpenVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    908         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    909 ResolvExpr/Occurs.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    910         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    911 ResolvExpr/PolyCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    912         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    913 ResolvExpr/PtrsAssignable.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    914         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    915 ResolvExpr/PtrsCastable.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    916         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    917 ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    918         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    919 ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    920         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    921 ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    922         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    923 ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    924         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    925 ResolvExpr/SatisfyAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    926         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    927 ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    928         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    929 ResolvExpr/TypeEnvironment.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    930         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    931 ResolvExpr/Unify.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    932         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    933 SymTab/$(am__dirstamp):
    934         @$(MKDIR_P) SymTab
    935         @: > SymTab/$(am__dirstamp)
    936 SymTab/$(DEPDIR)/$(am__dirstamp):
    937         @$(MKDIR_P) SymTab/$(DEPDIR)
    938         @: > SymTab/$(DEPDIR)/$(am__dirstamp)
    939 SymTab/Autogen.$(OBJEXT): SymTab/$(am__dirstamp) \
    940         SymTab/$(DEPDIR)/$(am__dirstamp)
    941 SymTab/FixFunction.$(OBJEXT): SymTab/$(am__dirstamp) \
    942         SymTab/$(DEPDIR)/$(am__dirstamp)
    943 SymTab/Indexer.$(OBJEXT): SymTab/$(am__dirstamp) \
    944         SymTab/$(DEPDIR)/$(am__dirstamp)
    945 SymTab/Mangler.$(OBJEXT): SymTab/$(am__dirstamp) \
    946         SymTab/$(DEPDIR)/$(am__dirstamp)
    947 SymTab/ManglerCommon.$(OBJEXT): SymTab/$(am__dirstamp) \
    948         SymTab/$(DEPDIR)/$(am__dirstamp)
    949 SymTab/Validate.$(OBJEXT): SymTab/$(am__dirstamp) \
    950         SymTab/$(DEPDIR)/$(am__dirstamp)
    951 SymTab/Demangle.$(OBJEXT): SymTab/$(am__dirstamp) \
    952         SymTab/$(DEPDIR)/$(am__dirstamp)
    953 SynTree/$(am__dirstamp):
    954         @$(MKDIR_P) SynTree
    955         @: > SynTree/$(am__dirstamp)
    956 SynTree/$(DEPDIR)/$(am__dirstamp):
    957         @$(MKDIR_P) SynTree/$(DEPDIR)
    958         @: > SynTree/$(DEPDIR)/$(am__dirstamp)
    959 SynTree/Type.$(OBJEXT): SynTree/$(am__dirstamp) \
    960         SynTree/$(DEPDIR)/$(am__dirstamp)
    961 SynTree/VoidType.$(OBJEXT): SynTree/$(am__dirstamp) \
    962         SynTree/$(DEPDIR)/$(am__dirstamp)
    963 SynTree/BasicType.$(OBJEXT): SynTree/$(am__dirstamp) \
    964         SynTree/$(DEPDIR)/$(am__dirstamp)
    965 SynTree/PointerType.$(OBJEXT): SynTree/$(am__dirstamp) \
    966         SynTree/$(DEPDIR)/$(am__dirstamp)
    967 SynTree/ArrayType.$(OBJEXT): SynTree/$(am__dirstamp) \
    968         SynTree/$(DEPDIR)/$(am__dirstamp)
    969 SynTree/ReferenceType.$(OBJEXT): SynTree/$(am__dirstamp) \
    970         SynTree/$(DEPDIR)/$(am__dirstamp)
    971 SynTree/FunctionType.$(OBJEXT): SynTree/$(am__dirstamp) \
    972         SynTree/$(DEPDIR)/$(am__dirstamp)
    973 SynTree/ReferenceToType.$(OBJEXT): SynTree/$(am__dirstamp) \
    974         SynTree/$(DEPDIR)/$(am__dirstamp)
    975 SynTree/TupleType.$(OBJEXT): SynTree/$(am__dirstamp) \
    976         SynTree/$(DEPDIR)/$(am__dirstamp)
    977 SynTree/TypeofType.$(OBJEXT): SynTree/$(am__dirstamp) \
    978         SynTree/$(DEPDIR)/$(am__dirstamp)
    979 SynTree/AttrType.$(OBJEXT): SynTree/$(am__dirstamp) \
    980         SynTree/$(DEPDIR)/$(am__dirstamp)
    981 SynTree/VarArgsType.$(OBJEXT): SynTree/$(am__dirstamp) \
    982         SynTree/$(DEPDIR)/$(am__dirstamp)
    983 SynTree/ZeroOneType.$(OBJEXT): SynTree/$(am__dirstamp) \
    984         SynTree/$(DEPDIR)/$(am__dirstamp)
    985 SynTree/Constant.$(OBJEXT): SynTree/$(am__dirstamp) \
    986         SynTree/$(DEPDIR)/$(am__dirstamp)
    987 SynTree/Expression.$(OBJEXT): SynTree/$(am__dirstamp) \
    988         SynTree/$(DEPDIR)/$(am__dirstamp)
    989 SynTree/TupleExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    990         SynTree/$(DEPDIR)/$(am__dirstamp)
    991 SynTree/CommaExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    992         SynTree/$(DEPDIR)/$(am__dirstamp)
    993 SynTree/TypeExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    994         SynTree/$(DEPDIR)/$(am__dirstamp)
    995 SynTree/ApplicationExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    996         SynTree/$(DEPDIR)/$(am__dirstamp)
    997 SynTree/AddressExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    998         SynTree/$(DEPDIR)/$(am__dirstamp)
    999 SynTree/Statement.$(OBJEXT): SynTree/$(am__dirstamp) \
    1000         SynTree/$(DEPDIR)/$(am__dirstamp)
    1001 SynTree/CompoundStmt.$(OBJEXT): SynTree/$(am__dirstamp) \
    1002         SynTree/$(DEPDIR)/$(am__dirstamp)
    1003 SynTree/DeclStmt.$(OBJEXT): SynTree/$(am__dirstamp) \
    1004         SynTree/$(DEPDIR)/$(am__dirstamp)
    1005 SynTree/Declaration.$(OBJEXT): SynTree/$(am__dirstamp) \
    1006         SynTree/$(DEPDIR)/$(am__dirstamp)
    1007 SynTree/DeclarationWithType.$(OBJEXT): SynTree/$(am__dirstamp) \
    1008         SynTree/$(DEPDIR)/$(am__dirstamp)
    1009 SynTree/ObjectDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
    1010         SynTree/$(DEPDIR)/$(am__dirstamp)
    1011 SynTree/FunctionDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
    1012         SynTree/$(DEPDIR)/$(am__dirstamp)
    1013 SynTree/AggregateDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
    1014         SynTree/$(DEPDIR)/$(am__dirstamp)
    1015 SynTree/NamedTypeDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
    1016         SynTree/$(DEPDIR)/$(am__dirstamp)
    1017 SynTree/TypeDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
    1018         SynTree/$(DEPDIR)/$(am__dirstamp)
    1019 SynTree/Initializer.$(OBJEXT): SynTree/$(am__dirstamp) \
    1020         SynTree/$(DEPDIR)/$(am__dirstamp)
    1021 SynTree/TypeSubstitution.$(OBJEXT): SynTree/$(am__dirstamp) \
    1022         SynTree/$(DEPDIR)/$(am__dirstamp)
    1023 SynTree/Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
    1024         SynTree/$(DEPDIR)/$(am__dirstamp)
    1025 SynTree/DeclReplacer.$(OBJEXT): SynTree/$(am__dirstamp) \
    1026         SynTree/$(DEPDIR)/$(am__dirstamp)
    1027 Tuples/$(am__dirstamp):
    1028         @$(MKDIR_P) Tuples
    1029         @: > Tuples/$(am__dirstamp)
    1030 Tuples/$(DEPDIR)/$(am__dirstamp):
    1031         @$(MKDIR_P) Tuples/$(DEPDIR)
    1032         @: > Tuples/$(DEPDIR)/$(am__dirstamp)
    1033 Tuples/TupleAssignment.$(OBJEXT): Tuples/$(am__dirstamp) \
    1034         Tuples/$(DEPDIR)/$(am__dirstamp)
    1035 Tuples/TupleExpansion.$(OBJEXT): Tuples/$(am__dirstamp) \
    1036         Tuples/$(DEPDIR)/$(am__dirstamp)
    1037 Tuples/Explode.$(OBJEXT): Tuples/$(am__dirstamp) \
    1038         Tuples/$(DEPDIR)/$(am__dirstamp)
    1039 Tuples/Tuples.$(OBJEXT): Tuples/$(am__dirstamp) \
    1040         Tuples/$(DEPDIR)/$(am__dirstamp)
    1041 Validate/$(am__dirstamp):
    1042         @$(MKDIR_P) Validate
    1043         @: > Validate/$(am__dirstamp)
    1044 Validate/$(DEPDIR)/$(am__dirstamp):
    1045         @$(MKDIR_P) Validate/$(DEPDIR)
    1046         @: > Validate/$(DEPDIR)/$(am__dirstamp)
    1047 Validate/HandleAttributes.$(OBJEXT): Validate/$(am__dirstamp) \
    1048         Validate/$(DEPDIR)/$(am__dirstamp)
    1049 Validate/FindSpecialDecls.$(OBJEXT): Validate/$(am__dirstamp) \
    1050         Validate/$(DEPDIR)/$(am__dirstamp)
    1051 
    1052 libdemangle.a: $(libdemangle_a_OBJECTS) $(libdemangle_a_DEPENDENCIES) $(EXTRA_libdemangle_a_DEPENDENCIES)
    1053         $(AM_V_at)-rm -f libdemangle.a
    1054         $(AM_V_AR)$(libdemangle_a_AR) libdemangle.a $(libdemangle_a_OBJECTS) $(libdemangle_a_LIBADD)
    1055         $(AM_V_at)$(RANLIB) libdemangle.a
    1056580install-cfa_cpplibPROGRAMS: $(cfa_cpplib_PROGRAMS)
    1057581        @$(NORMAL_INSTALL)
     
    1064588        sed 's/$(EXEEXT)$$//' | \
    1065589        while read p p1; do if test -f $$p \
    1066          || test -f $$p1 \
    1067590          ; then echo "$$p"; echo "$$p"; else :; fi; \
    1068591        done | \
     
    1079602            if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
    1080603            test -z "$$files" || { \
    1081             echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cfa_cpplibdir)$$dir'"; \
    1082             $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cfa_cpplibdir)$$dir" || exit $$?; \
     604              echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cfa_cpplibdir)$$dir'"; \
     605              $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cfa_cpplibdir)$$dir" || exit $$?; \
    1083606            } \
    1084607        ; done
     
    1096619
    1097620clean-cfa_cpplibPROGRAMS:
    1098         @list='$(cfa_cpplib_PROGRAMS)'; test -n "$$list" || exit 0; \
    1099         echo " rm -f" $$list; \
    1100         rm -f $$list || exit $$?; \
    1101         test -n "$(EXEEXT)" || exit 0; \
    1102         list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
    1103         echo " rm -f" $$list; \
    1104         rm -f $$list
    1105 CodeGen/Generate.$(OBJEXT): CodeGen/$(am__dirstamp) \
     621        -test -z "$(cfa_cpplib_PROGRAMS)" || rm -f $(cfa_cpplib_PROGRAMS)
     622CodeGen/$(am__dirstamp):
     623        @$(MKDIR_P) CodeGen
     624        @: > CodeGen/$(am__dirstamp)
     625CodeGen/$(DEPDIR)/$(am__dirstamp):
     626        @$(MKDIR_P) CodeGen/$(DEPDIR)
     627        @: > CodeGen/$(DEPDIR)/$(am__dirstamp)
     628CodeGen/driver_cfa_cpp-Generate.$(OBJEXT): CodeGen/$(am__dirstamp) \
    1106629        CodeGen/$(DEPDIR)/$(am__dirstamp)
    1107 CodeGen/FixNames.$(OBJEXT): CodeGen/$(am__dirstamp) \
     630CodeGen/driver_cfa_cpp-CodeGenerator.$(OBJEXT):  \
     631        CodeGen/$(am__dirstamp) CodeGen/$(DEPDIR)/$(am__dirstamp)
     632CodeGen/driver_cfa_cpp-GenType.$(OBJEXT): CodeGen/$(am__dirstamp) \
    1108633        CodeGen/$(DEPDIR)/$(am__dirstamp)
     634CodeGen/driver_cfa_cpp-FixNames.$(OBJEXT): CodeGen/$(am__dirstamp) \
     635        CodeGen/$(DEPDIR)/$(am__dirstamp)
     636CodeGen/driver_cfa_cpp-FixMain.$(OBJEXT): CodeGen/$(am__dirstamp) \
     637        CodeGen/$(DEPDIR)/$(am__dirstamp)
     638CodeGen/driver_cfa_cpp-OperatorTable.$(OBJEXT):  \
     639        CodeGen/$(am__dirstamp) CodeGen/$(DEPDIR)/$(am__dirstamp)
    1109640CodeTools/$(am__dirstamp):
    1110641        @$(MKDIR_P) CodeTools
     
    1113644        @$(MKDIR_P) CodeTools/$(DEPDIR)
    1114645        @: > CodeTools/$(DEPDIR)/$(am__dirstamp)
    1115 CodeTools/DeclStats.$(OBJEXT): CodeTools/$(am__dirstamp) \
    1116         CodeTools/$(DEPDIR)/$(am__dirstamp)
    1117 CodeTools/ResolvProtoDump.$(OBJEXT): CodeTools/$(am__dirstamp) \
    1118         CodeTools/$(DEPDIR)/$(am__dirstamp)
    1119 CodeTools/TrackLoc.$(OBJEXT): CodeTools/$(am__dirstamp) \
    1120         CodeTools/$(DEPDIR)/$(am__dirstamp)
    1121 Concurrency/Waitfor.$(OBJEXT): Concurrency/$(am__dirstamp) \
     646CodeTools/driver_cfa_cpp-DeclStats.$(OBJEXT):  \
     647        CodeTools/$(am__dirstamp) CodeTools/$(DEPDIR)/$(am__dirstamp)
     648CodeTools/driver_cfa_cpp-TrackLoc.$(OBJEXT):  \
     649        CodeTools/$(am__dirstamp) CodeTools/$(DEPDIR)/$(am__dirstamp)
     650Concurrency/$(am__dirstamp):
     651        @$(MKDIR_P) Concurrency
     652        @: > Concurrency/$(am__dirstamp)
     653Concurrency/$(DEPDIR)/$(am__dirstamp):
     654        @$(MKDIR_P) Concurrency/$(DEPDIR)
     655        @: > Concurrency/$(DEPDIR)/$(am__dirstamp)
     656Concurrency/driver_cfa_cpp-Keywords.$(OBJEXT):  \
     657        Concurrency/$(am__dirstamp) \
    1122658        Concurrency/$(DEPDIR)/$(am__dirstamp)
    1123 Common/DebugMalloc.$(OBJEXT): Common/$(am__dirstamp) \
     659Concurrency/driver_cfa_cpp-Waitfor.$(OBJEXT):  \
     660        Concurrency/$(am__dirstamp) \
     661        Concurrency/$(DEPDIR)/$(am__dirstamp)
     662Common/$(am__dirstamp):
     663        @$(MKDIR_P) Common
     664        @: > Common/$(am__dirstamp)
     665Common/$(DEPDIR)/$(am__dirstamp):
     666        @$(MKDIR_P) Common/$(DEPDIR)
     667        @: > Common/$(DEPDIR)/$(am__dirstamp)
     668Common/driver_cfa_cpp-SemanticError.$(OBJEXT): Common/$(am__dirstamp) \
    1124669        Common/$(DEPDIR)/$(am__dirstamp)
    1125 ControlStruct/ExceptTranslate.$(OBJEXT):  \
     670Common/driver_cfa_cpp-UniqueName.$(OBJEXT): Common/$(am__dirstamp) \
     671        Common/$(DEPDIR)/$(am__dirstamp)
     672Common/driver_cfa_cpp-DebugMalloc.$(OBJEXT): Common/$(am__dirstamp) \
     673        Common/$(DEPDIR)/$(am__dirstamp)
     674Common/driver_cfa_cpp-Assert.$(OBJEXT): Common/$(am__dirstamp) \
     675        Common/$(DEPDIR)/$(am__dirstamp)
     676Common/driver_cfa_cpp-Heap.$(OBJEXT): Common/$(am__dirstamp) \
     677        Common/$(DEPDIR)/$(am__dirstamp)
     678ControlStruct/$(am__dirstamp):
     679        @$(MKDIR_P) ControlStruct
     680        @: > ControlStruct/$(am__dirstamp)
     681ControlStruct/$(DEPDIR)/$(am__dirstamp):
     682        @$(MKDIR_P) ControlStruct/$(DEPDIR)
     683        @: > ControlStruct/$(DEPDIR)/$(am__dirstamp)
     684ControlStruct/driver_cfa_cpp-LabelGenerator.$(OBJEXT):  \
    1126685        ControlStruct/$(am__dirstamp) \
    1127686        ControlStruct/$(DEPDIR)/$(am__dirstamp)
    1128 GenPoly/Box.$(OBJEXT): GenPoly/$(am__dirstamp) \
     687ControlStruct/driver_cfa_cpp-LabelFixer.$(OBJEXT):  \
     688        ControlStruct/$(am__dirstamp) \
     689        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     690ControlStruct/driver_cfa_cpp-MLEMutator.$(OBJEXT):  \
     691        ControlStruct/$(am__dirstamp) \
     692        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     693ControlStruct/driver_cfa_cpp-Mutate.$(OBJEXT):  \
     694        ControlStruct/$(am__dirstamp) \
     695        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     696ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT):  \
     697        ControlStruct/$(am__dirstamp) \
     698        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     699ControlStruct/driver_cfa_cpp-ExceptTranslate.$(OBJEXT):  \
     700        ControlStruct/$(am__dirstamp) \
     701        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     702GenPoly/$(am__dirstamp):
     703        @$(MKDIR_P) GenPoly
     704        @: > GenPoly/$(am__dirstamp)
     705GenPoly/$(DEPDIR)/$(am__dirstamp):
     706        @$(MKDIR_P) GenPoly/$(DEPDIR)
     707        @: > GenPoly/$(DEPDIR)/$(am__dirstamp)
     708GenPoly/driver_cfa_cpp-Box.$(OBJEXT): GenPoly/$(am__dirstamp) \
    1129709        GenPoly/$(DEPDIR)/$(am__dirstamp)
    1130 GenPoly/ScrubTyVars.$(OBJEXT): GenPoly/$(am__dirstamp) \
     710GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT): GenPoly/$(am__dirstamp) \
    1131711        GenPoly/$(DEPDIR)/$(am__dirstamp)
    1132 GenPoly/Specialize.$(OBJEXT): GenPoly/$(am__dirstamp) \
     712GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT): GenPoly/$(am__dirstamp) \
    1133713        GenPoly/$(DEPDIR)/$(am__dirstamp)
    1134 GenPoly/FindFunction.$(OBJEXT): GenPoly/$(am__dirstamp) \
     714GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT): GenPoly/$(am__dirstamp) \
    1135715        GenPoly/$(DEPDIR)/$(am__dirstamp)
    1136 GenPoly/InstantiateGeneric.$(OBJEXT): GenPoly/$(am__dirstamp) \
     716GenPoly/driver_cfa_cpp-Specialize.$(OBJEXT): GenPoly/$(am__dirstamp) \
    1137717        GenPoly/$(DEPDIR)/$(am__dirstamp)
    1138 InitTweak/FixInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
     718GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT):  \
     719        GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
     720GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT):  \
     721        GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
     722InitTweak/$(am__dirstamp):
     723        @$(MKDIR_P) InitTweak
     724        @: > InitTweak/$(am__dirstamp)
     725InitTweak/$(DEPDIR)/$(am__dirstamp):
     726        @$(MKDIR_P) InitTweak/$(DEPDIR)
     727        @: > InitTweak/$(DEPDIR)/$(am__dirstamp)
     728InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
    1139729        InitTweak/$(DEPDIR)/$(am__dirstamp)
    1140 InitTweak/FixGlobalInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
     730InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
    1141731        InitTweak/$(DEPDIR)/$(am__dirstamp)
     732InitTweak/driver_cfa_cpp-FixGlobalInit.$(OBJEXT):  \
     733        InitTweak/$(am__dirstamp) InitTweak/$(DEPDIR)/$(am__dirstamp)
     734InitTweak/driver_cfa_cpp-InitTweak.$(OBJEXT):  \
     735        InitTweak/$(am__dirstamp) InitTweak/$(DEPDIR)/$(am__dirstamp)
    1142736Parser/parser.hh: Parser/parser.cc
    1143737        @if test ! -f $@; then rm -f Parser/parser.cc; else :; fi
    1144738        @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) Parser/parser.cc; else :; fi
    1145 Parser/parser.$(OBJEXT): Parser/$(am__dirstamp) \
     739Parser/$(am__dirstamp):
     740        @$(MKDIR_P) Parser
     741        @: > Parser/$(am__dirstamp)
     742Parser/$(DEPDIR)/$(am__dirstamp):
     743        @$(MKDIR_P) Parser/$(DEPDIR)
     744        @: > Parser/$(DEPDIR)/$(am__dirstamp)
     745Parser/driver_cfa_cpp-parser.$(OBJEXT): Parser/$(am__dirstamp) \
    1146746        Parser/$(DEPDIR)/$(am__dirstamp)
    1147 Parser/lex.$(OBJEXT): Parser/$(am__dirstamp) \
     747Parser/driver_cfa_cpp-lex.$(OBJEXT): Parser/$(am__dirstamp) \
    1148748        Parser/$(DEPDIR)/$(am__dirstamp)
    1149 Parser/TypedefTable.$(OBJEXT): Parser/$(am__dirstamp) \
     749Parser/driver_cfa_cpp-TypedefTable.$(OBJEXT): Parser/$(am__dirstamp) \
    1150750        Parser/$(DEPDIR)/$(am__dirstamp)
    1151 Parser/ParseNode.$(OBJEXT): Parser/$(am__dirstamp) \
     751Parser/driver_cfa_cpp-ParseNode.$(OBJEXT): Parser/$(am__dirstamp) \
    1152752        Parser/$(DEPDIR)/$(am__dirstamp)
    1153 Parser/DeclarationNode.$(OBJEXT): Parser/$(am__dirstamp) \
     753Parser/driver_cfa_cpp-DeclarationNode.$(OBJEXT):  \
     754        Parser/$(am__dirstamp) Parser/$(DEPDIR)/$(am__dirstamp)
     755Parser/driver_cfa_cpp-ExpressionNode.$(OBJEXT):  \
     756        Parser/$(am__dirstamp) Parser/$(DEPDIR)/$(am__dirstamp)
     757Parser/driver_cfa_cpp-StatementNode.$(OBJEXT): Parser/$(am__dirstamp) \
    1154758        Parser/$(DEPDIR)/$(am__dirstamp)
    1155 Parser/ExpressionNode.$(OBJEXT): Parser/$(am__dirstamp) \
     759Parser/driver_cfa_cpp-InitializerNode.$(OBJEXT):  \
     760        Parser/$(am__dirstamp) Parser/$(DEPDIR)/$(am__dirstamp)
     761Parser/driver_cfa_cpp-TypeData.$(OBJEXT): Parser/$(am__dirstamp) \
    1156762        Parser/$(DEPDIR)/$(am__dirstamp)
    1157 Parser/StatementNode.$(OBJEXT): Parser/$(am__dirstamp) \
     763Parser/driver_cfa_cpp-LinkageSpec.$(OBJEXT): Parser/$(am__dirstamp) \
    1158764        Parser/$(DEPDIR)/$(am__dirstamp)
    1159 Parser/InitializerNode.$(OBJEXT): Parser/$(am__dirstamp) \
     765Parser/driver_cfa_cpp-parserutility.$(OBJEXT): Parser/$(am__dirstamp) \
    1160766        Parser/$(DEPDIR)/$(am__dirstamp)
    1161 Parser/TypeData.$(OBJEXT): Parser/$(am__dirstamp) \
    1162         Parser/$(DEPDIR)/$(am__dirstamp)
    1163 Parser/parserutility.$(OBJEXT): Parser/$(am__dirstamp) \
    1164         Parser/$(DEPDIR)/$(am__dirstamp)
    1165 ResolvExpr/AlternativePrinter.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     767ResolvExpr/$(am__dirstamp):
     768        @$(MKDIR_P) ResolvExpr
     769        @: > ResolvExpr/$(am__dirstamp)
     770ResolvExpr/$(DEPDIR)/$(am__dirstamp):
     771        @$(MKDIR_P) ResolvExpr/$(DEPDIR)
     772        @: > ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     773ResolvExpr/driver_cfa_cpp-AlternativeFinder.$(OBJEXT):  \
     774        ResolvExpr/$(am__dirstamp) \
    1166775        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     776ResolvExpr/driver_cfa_cpp-Alternative.$(OBJEXT):  \
     777        ResolvExpr/$(am__dirstamp) \
     778        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     779ResolvExpr/driver_cfa_cpp-Unify.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     780        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     781ResolvExpr/driver_cfa_cpp-PtrsAssignable.$(OBJEXT):  \
     782        ResolvExpr/$(am__dirstamp) \
     783        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     784ResolvExpr/driver_cfa_cpp-CommonType.$(OBJEXT):  \
     785        ResolvExpr/$(am__dirstamp) \
     786        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     787ResolvExpr/driver_cfa_cpp-ConversionCost.$(OBJEXT):  \
     788        ResolvExpr/$(am__dirstamp) \
     789        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     790ResolvExpr/driver_cfa_cpp-CastCost.$(OBJEXT):  \
     791        ResolvExpr/$(am__dirstamp) \
     792        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     793ResolvExpr/driver_cfa_cpp-PtrsCastable.$(OBJEXT):  \
     794        ResolvExpr/$(am__dirstamp) \
     795        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     796ResolvExpr/driver_cfa_cpp-AdjustExprType.$(OBJEXT):  \
     797        ResolvExpr/$(am__dirstamp) \
     798        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     799ResolvExpr/driver_cfa_cpp-AlternativePrinter.$(OBJEXT):  \
     800        ResolvExpr/$(am__dirstamp) \
     801        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     802ResolvExpr/driver_cfa_cpp-Resolver.$(OBJEXT):  \
     803        ResolvExpr/$(am__dirstamp) \
     804        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     805ResolvExpr/driver_cfa_cpp-ResolveTypeof.$(OBJEXT):  \
     806        ResolvExpr/$(am__dirstamp) \
     807        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     808ResolvExpr/driver_cfa_cpp-RenameVars.$(OBJEXT):  \
     809        ResolvExpr/$(am__dirstamp) \
     810        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     811ResolvExpr/driver_cfa_cpp-FindOpenVars.$(OBJEXT):  \
     812        ResolvExpr/$(am__dirstamp) \
     813        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     814ResolvExpr/driver_cfa_cpp-PolyCost.$(OBJEXT):  \
     815        ResolvExpr/$(am__dirstamp) \
     816        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     817ResolvExpr/driver_cfa_cpp-Occurs.$(OBJEXT):  \
     818        ResolvExpr/$(am__dirstamp) \
     819        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     820ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT):  \
     821        ResolvExpr/$(am__dirstamp) \
     822        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     823ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT):  \
     824        ResolvExpr/$(am__dirstamp) \
     825        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     826ResolvExpr/driver_cfa_cpp-ExplodedActual.$(OBJEXT):  \
     827        ResolvExpr/$(am__dirstamp) \
     828        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     829SymTab/$(am__dirstamp):
     830        @$(MKDIR_P) SymTab
     831        @: > SymTab/$(am__dirstamp)
     832SymTab/$(DEPDIR)/$(am__dirstamp):
     833        @$(MKDIR_P) SymTab/$(DEPDIR)
     834        @: > SymTab/$(DEPDIR)/$(am__dirstamp)
     835SymTab/driver_cfa_cpp-Indexer.$(OBJEXT): SymTab/$(am__dirstamp) \
     836        SymTab/$(DEPDIR)/$(am__dirstamp)
     837SymTab/driver_cfa_cpp-Mangler.$(OBJEXT): SymTab/$(am__dirstamp) \
     838        SymTab/$(DEPDIR)/$(am__dirstamp)
     839SymTab/driver_cfa_cpp-Validate.$(OBJEXT): SymTab/$(am__dirstamp) \
     840        SymTab/$(DEPDIR)/$(am__dirstamp)
     841SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT): SymTab/$(am__dirstamp) \
     842        SymTab/$(DEPDIR)/$(am__dirstamp)
     843SymTab/driver_cfa_cpp-Autogen.$(OBJEXT): SymTab/$(am__dirstamp) \
     844        SymTab/$(DEPDIR)/$(am__dirstamp)
     845SynTree/$(am__dirstamp):
     846        @$(MKDIR_P) SynTree
     847        @: > SynTree/$(am__dirstamp)
     848SynTree/$(DEPDIR)/$(am__dirstamp):
     849        @$(MKDIR_P) SynTree/$(DEPDIR)
     850        @: > SynTree/$(DEPDIR)/$(am__dirstamp)
     851SynTree/driver_cfa_cpp-Type.$(OBJEXT): SynTree/$(am__dirstamp) \
     852        SynTree/$(DEPDIR)/$(am__dirstamp)
     853SynTree/driver_cfa_cpp-VoidType.$(OBJEXT): SynTree/$(am__dirstamp) \
     854        SynTree/$(DEPDIR)/$(am__dirstamp)
     855SynTree/driver_cfa_cpp-BasicType.$(OBJEXT): SynTree/$(am__dirstamp) \
     856        SynTree/$(DEPDIR)/$(am__dirstamp)
     857SynTree/driver_cfa_cpp-PointerType.$(OBJEXT): SynTree/$(am__dirstamp) \
     858        SynTree/$(DEPDIR)/$(am__dirstamp)
     859SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT): SynTree/$(am__dirstamp) \
     860        SynTree/$(DEPDIR)/$(am__dirstamp)
     861SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT):  \
     862        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     863SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT):  \
     864        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     865SynTree/driver_cfa_cpp-ReferenceToType.$(OBJEXT):  \
     866        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     867SynTree/driver_cfa_cpp-TupleType.$(OBJEXT): SynTree/$(am__dirstamp) \
     868        SynTree/$(DEPDIR)/$(am__dirstamp)
     869SynTree/driver_cfa_cpp-TypeofType.$(OBJEXT): SynTree/$(am__dirstamp) \
     870        SynTree/$(DEPDIR)/$(am__dirstamp)
     871SynTree/driver_cfa_cpp-AttrType.$(OBJEXT): SynTree/$(am__dirstamp) \
     872        SynTree/$(DEPDIR)/$(am__dirstamp)
     873SynTree/driver_cfa_cpp-VarArgsType.$(OBJEXT): SynTree/$(am__dirstamp) \
     874        SynTree/$(DEPDIR)/$(am__dirstamp)
     875SynTree/driver_cfa_cpp-ZeroOneType.$(OBJEXT): SynTree/$(am__dirstamp) \
     876        SynTree/$(DEPDIR)/$(am__dirstamp)
     877SynTree/driver_cfa_cpp-Constant.$(OBJEXT): SynTree/$(am__dirstamp) \
     878        SynTree/$(DEPDIR)/$(am__dirstamp)
     879SynTree/driver_cfa_cpp-Expression.$(OBJEXT): SynTree/$(am__dirstamp) \
     880        SynTree/$(DEPDIR)/$(am__dirstamp)
     881SynTree/driver_cfa_cpp-TupleExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     882        SynTree/$(DEPDIR)/$(am__dirstamp)
     883SynTree/driver_cfa_cpp-CommaExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     884        SynTree/$(DEPDIR)/$(am__dirstamp)
     885SynTree/driver_cfa_cpp-TypeExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     886        SynTree/$(DEPDIR)/$(am__dirstamp)
     887SynTree/driver_cfa_cpp-ApplicationExpr.$(OBJEXT):  \
     888        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     889SynTree/driver_cfa_cpp-AddressExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     890        SynTree/$(DEPDIR)/$(am__dirstamp)
     891SynTree/driver_cfa_cpp-Statement.$(OBJEXT): SynTree/$(am__dirstamp) \
     892        SynTree/$(DEPDIR)/$(am__dirstamp)
     893SynTree/driver_cfa_cpp-CompoundStmt.$(OBJEXT):  \
     894        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     895SynTree/driver_cfa_cpp-DeclStmt.$(OBJEXT): SynTree/$(am__dirstamp) \
     896        SynTree/$(DEPDIR)/$(am__dirstamp)
     897SynTree/driver_cfa_cpp-Declaration.$(OBJEXT): SynTree/$(am__dirstamp) \
     898        SynTree/$(DEPDIR)/$(am__dirstamp)
     899SynTree/driver_cfa_cpp-DeclarationWithType.$(OBJEXT):  \
     900        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     901SynTree/driver_cfa_cpp-ObjectDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
     902        SynTree/$(DEPDIR)/$(am__dirstamp)
     903SynTree/driver_cfa_cpp-FunctionDecl.$(OBJEXT):  \
     904        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     905SynTree/driver_cfa_cpp-AggregateDecl.$(OBJEXT):  \
     906        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     907SynTree/driver_cfa_cpp-NamedTypeDecl.$(OBJEXT):  \
     908        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     909SynTree/driver_cfa_cpp-TypeDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
     910        SynTree/$(DEPDIR)/$(am__dirstamp)
     911SynTree/driver_cfa_cpp-Initializer.$(OBJEXT): SynTree/$(am__dirstamp) \
     912        SynTree/$(DEPDIR)/$(am__dirstamp)
     913SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT):  \
     914        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     915SynTree/driver_cfa_cpp-Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
     916        SynTree/$(DEPDIR)/$(am__dirstamp)
     917SynTree/driver_cfa_cpp-DeclReplacer.$(OBJEXT):  \
     918        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     919Tuples/$(am__dirstamp):
     920        @$(MKDIR_P) Tuples
     921        @: > Tuples/$(am__dirstamp)
     922Tuples/$(DEPDIR)/$(am__dirstamp):
     923        @$(MKDIR_P) Tuples/$(DEPDIR)
     924        @: > Tuples/$(DEPDIR)/$(am__dirstamp)
     925Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT):  \
     926        Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
     927Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT):  \
     928        Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
     929Tuples/driver_cfa_cpp-Explode.$(OBJEXT): Tuples/$(am__dirstamp) \
     930        Tuples/$(DEPDIR)/$(am__dirstamp)
    1167931Virtual/$(am__dirstamp):
    1168932        @$(MKDIR_P) Virtual
     
    1171935        @$(MKDIR_P) Virtual/$(DEPDIR)
    1172936        @: > Virtual/$(DEPDIR)/$(am__dirstamp)
    1173 Virtual/ExpandCasts.$(OBJEXT): Virtual/$(am__dirstamp) \
     937Virtual/driver_cfa_cpp-ExpandCasts.$(OBJEXT): Virtual/$(am__dirstamp) \
    1174938        Virtual/$(DEPDIR)/$(am__dirstamp)
    1175 ../driver/$(am__dirstamp):
    1176         @$(MKDIR_P) ../driver
    1177         @: > ../driver/$(am__dirstamp)
    1178 
    1179 ../driver/cfa-cpp$(EXEEXT): $(___driver_cfa_cpp_OBJECTS) $(___driver_cfa_cpp_DEPENDENCIES) $(EXTRA____driver_cfa_cpp_DEPENDENCIES) ../driver/$(am__dirstamp)
    1180         @rm -f ../driver/cfa-cpp$(EXEEXT)
    1181         $(AM_V_CXXLD)$(CXXLINK) $(___driver_cfa_cpp_OBJECTS) $(___driver_cfa_cpp_LDADD) $(LIBS)
    1182 SymTab/demangler.$(OBJEXT): SymTab/$(am__dirstamp) \
    1183         SymTab/$(DEPDIR)/$(am__dirstamp)
    1184 
    1185 demangler$(EXEEXT): $(demangler_OBJECTS) $(demangler_DEPENDENCIES) $(EXTRA_demangler_DEPENDENCIES)
    1186         @rm -f demangler$(EXEEXT)
    1187         $(AM_V_CXXLD)$(CXXLINK) $(demangler_OBJECTS) $(demangler_LDADD) $(LIBS)
     939driver/$(am__dirstamp):
     940        @$(MKDIR_P) driver
     941        @: > driver/$(am__dirstamp)
     942
     943driver/cfa-cpp$(EXEEXT): $(driver_cfa_cpp_OBJECTS) $(driver_cfa_cpp_DEPENDENCIES) $(EXTRA_driver_cfa_cpp_DEPENDENCIES) driver/$(am__dirstamp)
     944        @rm -f driver/cfa-cpp$(EXEEXT)
     945        $(AM_V_CXXLD)$(driver_cfa_cpp_LINK) $(driver_cfa_cpp_OBJECTS) $(driver_cfa_cpp_LDADD) $(LIBS)
    1188946
    1189947mostlyclean-compile:
    1190948        -rm -f *.$(OBJEXT)
    1191         -rm -f AST/*.$(OBJEXT)
    1192949        -rm -f CodeGen/*.$(OBJEXT)
    1193950        -rm -f CodeTools/*.$(OBJEXT)
    1194951        -rm -f Common/*.$(OBJEXT)
    1195         -rm -f Common/Stats/*.$(OBJEXT)
    1196952        -rm -f Concurrency/*.$(OBJEXT)
    1197953        -rm -f ControlStruct/*.$(OBJEXT)
     
    1203959        -rm -f SynTree/*.$(OBJEXT)
    1204960        -rm -f Tuples/*.$(OBJEXT)
    1205         -rm -f Validate/*.$(OBJEXT)
    1206961        -rm -f Virtual/*.$(OBJEXT)
    1207962
     
    1209964        -rm -f *.tab.c
    1210965
    1211 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompilationState.Po@am__quote@
    1212 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MakeLibCfa.Po@am__quote@
    1213 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
    1214 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/AssertAcyclic.Po@am__quote@
    1215 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Attribute.Po@am__quote@
    1216 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Convert.Po@am__quote@
    1217 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Decl.Po@am__quote@
    1218 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@
    1219 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Expr.Po@am__quote@
    1220 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/GenericSubstitution.Po@am__quote@
    1221 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@
    1222 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/LinkageSpec.Po@am__quote@
    1223 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Node.Po@am__quote@
    1224 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Pass.Po@am__quote@
    1225 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Print.Po@am__quote@
    1226 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Stmt.Po@am__quote@
    1227 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/SymbolTable.Po@am__quote@
    1228 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Type.Po@am__quote@
    1229 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/TypeEnvironment.Po@am__quote@
    1230 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/TypeSubstitution.Po@am__quote@
    1231 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/CodeGenerator.Po@am__quote@
    1232 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/FixMain.Po@am__quote@
    1233 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/FixNames.Po@am__quote@
    1234 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/GenType.Po@am__quote@
    1235 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/Generate.Po@am__quote@
    1236 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/OperatorTable.Po@am__quote@
    1237 @AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/DeclStats.Po@am__quote@
    1238 @AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/ResolvProtoDump.Po@am__quote@
    1239 @AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/TrackLoc.Po@am__quote@
    1240 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/Assert.Po@am__quote@
    1241 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/DebugMalloc.Po@am__quote@
    1242 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/Eval.Po@am__quote@
    1243 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/PassVisitor.Po@am__quote@
    1244 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/SemanticError.Po@am__quote@
    1245 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/UniqueName.Po@am__quote@
    1246 @AMDEP_TRUE@@am__include@ @am__quote@Common/Stats/$(DEPDIR)/Counter.Po@am__quote@
    1247 @AMDEP_TRUE@@am__include@ @am__quote@Common/Stats/$(DEPDIR)/Heap.Po@am__quote@
    1248 @AMDEP_TRUE@@am__include@ @am__quote@Common/Stats/$(DEPDIR)/Stats.Po@am__quote@
    1249 @AMDEP_TRUE@@am__include@ @am__quote@Common/Stats/$(DEPDIR)/Time.Po@am__quote@
    1250 @AMDEP_TRUE@@am__include@ @am__quote@Concurrency/$(DEPDIR)/Keywords.Po@am__quote@
    1251 @AMDEP_TRUE@@am__include@ @am__quote@Concurrency/$(DEPDIR)/Waitfor.Po@am__quote@
    1252 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/ExceptTranslate.Po@am__quote@
    1253 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/ForExprMutator.Po@am__quote@
    1254 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/LabelFixer.Po@am__quote@
    1255 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/LabelGenerator.Po@am__quote@
    1256 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/MLEMutator.Po@am__quote@
    1257 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/Mutate.Po@am__quote@
    1258 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/Box.Po@am__quote@
    1259 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/FindFunction.Po@am__quote@
    1260 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/GenPoly.Po@am__quote@
    1261 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/InstantiateGeneric.Po@am__quote@
    1262 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/Lvalue.Po@am__quote@
    1263 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/ScrubTyVars.Po@am__quote@
    1264 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/Specialize.Po@am__quote@
    1265 @AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/FixGlobalInit.Po@am__quote@
    1266 @AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/FixInit.Po@am__quote@
    1267 @AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/GenInit.Po@am__quote@
    1268 @AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/InitTweak.Po@am__quote@
    1269 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/DeclarationNode.Po@am__quote@
    1270 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/ExpressionNode.Po@am__quote@
    1271 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/InitializerNode.Po@am__quote@
    1272 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/LinkageSpec.Po@am__quote@
    1273 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/ParseNode.Po@am__quote@
    1274 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/StatementNode.Po@am__quote@
    1275 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/TypeData.Po@am__quote@
    1276 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/TypedefTable.Po@am__quote@
    1277 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/lex.Po@am__quote@
    1278 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/parser.Po@am__quote@
    1279 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/parserutility.Po@am__quote@
    1280 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/AdjustExprType.Po@am__quote@
    1281 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Alternative.Po@am__quote@
    1282 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/AlternativeFinder.Po@am__quote@
    1283 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/AlternativePrinter.Po@am__quote@
    1284 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Candidate.Po@am__quote@
    1285 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CandidateFinder.Po@am__quote@
    1286 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CastCost.Po@am__quote@
    1287 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CommonType.Po@am__quote@
    1288 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ConversionCost.Po@am__quote@
    1289 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CurrentObject.Po@am__quote@
    1290 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ExplodedActual.Po@am__quote@
    1291 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ExplodedArg.Po@am__quote@
    1292 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/FindOpenVars.Po@am__quote@
    1293 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Occurs.Po@am__quote@
    1294 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PolyCost.Po@am__quote@
    1295 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsAssignable.Po@am__quote@
    1296 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsCastable.Po@am__quote@
    1297 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/RenameVars.Po@am__quote@
    1298 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveAssertions.Po@am__quote@
    1299 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@
    1300 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Resolver.Po@am__quote@
    1301 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SatisfyAssertions.Po@am__quote@
    1302 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SpecCost.Po@am__quote@
    1303 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@
    1304 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Unify.Po@am__quote@
    1305 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/Autogen.Po@am__quote@
    1306 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/Demangle.Po@am__quote@
    1307 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/FixFunction.Po@am__quote@
    1308 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/Indexer.Po@am__quote@
    1309 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/Mangler.Po@am__quote@
    1310 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/ManglerCommon.Po@am__quote@
    1311 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/Validate.Po@am__quote@
    1312 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/demangler.Po@am__quote@
    1313 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/AddressExpr.Po@am__quote@
    1314 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/AggregateDecl.Po@am__quote@
    1315 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/ApplicationExpr.Po@am__quote@
    1316 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/ArrayType.Po@am__quote@
    1317 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/AttrType.Po@am__quote@
    1318 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/Attribute.Po@am__quote@
    1319 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/BasicType.Po@am__quote@
    1320 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/CommaExpr.Po@am__quote@
    1321 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/CompoundStmt.Po@am__quote@
    1322 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/Constant.Po@am__quote@
    1323 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/DeclReplacer.Po@am__quote@
    1324 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/DeclStmt.Po@am__quote@
    1325 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/Declaration.Po@am__quote@
    1326 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/DeclarationWithType.Po@am__quote@
    1327 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/Expression.Po@am__quote@
    1328 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/FunctionDecl.Po@am__quote@
    1329 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/FunctionType.Po@am__quote@
    1330 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/Initializer.Po@am__quote@
    1331 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/NamedTypeDecl.Po@am__quote@
    1332 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/ObjectDecl.Po@am__quote@
    1333 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/PointerType.Po@am__quote@
    1334 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/ReferenceToType.Po@am__quote@
    1335 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/ReferenceType.Po@am__quote@
    1336 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/Statement.Po@am__quote@
    1337 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/TupleExpr.Po@am__quote@
    1338 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/TupleType.Po@am__quote@
    1339 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/Type.Po@am__quote@
    1340 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/TypeDecl.Po@am__quote@
    1341 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/TypeExpr.Po@am__quote@
    1342 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/TypeSubstitution.Po@am__quote@
    1343 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/TypeofType.Po@am__quote@
    1344 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/VarArgsType.Po@am__quote@
    1345 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/VoidType.Po@am__quote@
    1346 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/ZeroOneType.Po@am__quote@
    1347 @AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/Explode.Po@am__quote@
    1348 @AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/TupleAssignment.Po@am__quote@
    1349 @AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/TupleExpansion.Po@am__quote@
    1350 @AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/Tuples.Po@am__quote@
    1351 @AMDEP_TRUE@@am__include@ @am__quote@Validate/$(DEPDIR)/FindSpecialDecls.Po@am__quote@
    1352 @AMDEP_TRUE@@am__include@ @am__quote@Validate/$(DEPDIR)/HandleAttributes.Po@am__quote@
    1353 @AMDEP_TRUE@@am__include@ @am__quote@Virtual/$(DEPDIR)/ExpandCasts.Po@am__quote@
     966@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver_cfa_cpp-MakeLibCfa.Po@am__quote@
     967@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver_cfa_cpp-main.Po@am__quote@
     968@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-CodeGenerator.Po@am__quote@
     969@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-FixMain.Po@am__quote@
     970@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-FixNames.Po@am__quote@
     971@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-GenType.Po@am__quote@
     972@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Po@am__quote@
     973@AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Po@am__quote@
     974@AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Po@am__quote@
     975@AMDEP_TRUE@@am__include@ @am__quote@CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Po@am__quote@
     976@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-Assert.Po@am__quote@
     977@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Po@am__quote@
     978@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-Heap.Po@am__quote@
     979@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Po@am__quote@
     980@AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Po@am__quote@
     981@AMDEP_TRUE@@am__include@ @am__quote@Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Po@am__quote@
     982@AMDEP_TRUE@@am__include@ @am__quote@Concurrency/$(DEPDIR)/driver_cfa_cpp-Waitfor.Po@am__quote@
     983@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Po@am__quote@
     984@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Po@am__quote@
     985@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Po@am__quote@
     986@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Po@am__quote@
     987@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Po@am__quote@
     988@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Po@am__quote@
     989@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Po@am__quote@
     990@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po@am__quote@
     991@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po@am__quote@
     992@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po@am__quote@
     993@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Po@am__quote@
     994@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po@am__quote@
     995@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po@am__quote@
     996@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Po@am__quote@
     997@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po@am__quote@
     998@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po@am__quote@
     999@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Po@am__quote@
     1000@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Po@am__quote@
     1001@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Po@am__quote@
     1002@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-InitializerNode.Po@am__quote@
     1003@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Po@am__quote@
     1004@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Po@am__quote@
     1005@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Po@am__quote@
     1006@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Po@am__quote@
     1007@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-TypedefTable.Po@am__quote@
     1008@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-lex.Po@am__quote@
     1009@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-parser.Po@am__quote@
     1010@AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-parserutility.Po@am__quote@
     1011@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AdjustExprType.Po@am__quote@
     1012@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Alternative.Po@am__quote@
     1013@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativeFinder.Po@am__quote@
     1014@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativePrinter.Po@am__quote@
     1015@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CastCost.Po@am__quote@
     1016@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Po@am__quote@
     1017@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Po@am__quote@
     1018@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po@am__quote@
     1019@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po@am__quote@
     1020@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Po@am__quote@
     1021@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Po@am__quote@
     1022@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PolyCost.Po@am__quote@
     1023@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsAssignable.Po@am__quote@
     1024@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsCastable.Po@am__quote@
     1025@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-RenameVars.Po@am__quote@
     1026@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ResolveTypeof.Po@am__quote@
     1027@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Resolver.Po@am__quote@
     1028@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Po@am__quote@
     1029@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Po@am__quote@
     1030@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po@am__quote@
     1031@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po@am__quote@
     1032@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Po@am__quote@
     1033@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Po@am__quote@
     1034@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Po@am__quote@
     1035@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po@am__quote@
     1036@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Po@am__quote@
     1037@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ApplicationExpr.Po@am__quote@
     1038@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Po@am__quote@
     1039@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Po@am__quote@
     1040@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po@am__quote@
     1041@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Po@am__quote@
     1042@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Po@am__quote@
     1043@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Po@am__quote@
     1044@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Po@am__quote@
     1045@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Po@am__quote@
     1046@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Po@am__quote@
     1047@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Po@am__quote@
     1048@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-DeclarationWithType.Po@am__quote@
     1049@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Expression.Po@am__quote@
     1050@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionDecl.Po@am__quote@
     1051@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Po@am__quote@
     1052@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Po@am__quote@
     1053@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Po@am__quote@
     1054@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Po@am__quote@
     1055@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Po@am__quote@
     1056@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Po@am__quote@
     1057@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po@am__quote@
     1058@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Po@am__quote@
     1059@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Po@am__quote@
     1060@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TupleType.Po@am__quote@
     1061@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Type.Po@am__quote@
     1062@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TypeDecl.Po@am__quote@
     1063@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TypeExpr.Po@am__quote@
     1064@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TypeSubstitution.Po@am__quote@
     1065@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Po@am__quote@
     1066@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Po@am__quote@
     1067@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po@am__quote@
     1068@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Po@am__quote@
     1069@AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Po@am__quote@
     1070@AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Po@am__quote@
     1071@AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Po@am__quote@
     1072@AMDEP_TRUE@@am__include@ @am__quote@Virtual/$(DEPDIR)/driver_cfa_cpp-ExpandCasts.Po@am__quote@
    13541073
    13551074.cc.o:
     
    13691088@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
    13701089
    1371 .cc.lo:
    1372 @am__fastdepCXX_TRUE@   $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
    1373 @am__fastdepCXX_TRUE@   $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
    1374 @am__fastdepCXX_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Plo
    1375 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
    1376 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1377 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
    1378 
    1379 .cpp.o:
    1380 @am__fastdepCXX_TRUE@   $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
    1381 @am__fastdepCXX_TRUE@   $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
    1382 @am__fastdepCXX_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
    1383 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
    1384 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1385 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
    1386 
    1387 .cpp.obj:
    1388 @am__fastdepCXX_TRUE@   $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
    1389 @am__fastdepCXX_TRUE@   $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
    1390 @am__fastdepCXX_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
    1391 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
    1392 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1393 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
    1394 
    1395 .cpp.lo:
    1396 @am__fastdepCXX_TRUE@   $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
    1397 @am__fastdepCXX_TRUE@   $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
    1398 @am__fastdepCXX_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Plo
    1399 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
    1400 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1401 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
     1090driver_cfa_cpp-main.o: main.cc
     1091@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT driver_cfa_cpp-main.o -MD -MP -MF $(DEPDIR)/driver_cfa_cpp-main.Tpo -c -o driver_cfa_cpp-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc
     1092@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/driver_cfa_cpp-main.Tpo $(DEPDIR)/driver_cfa_cpp-main.Po
     1093@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='main.cc' object='driver_cfa_cpp-main.o' libtool=no @AMDEPBACKSLASH@
     1094@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1095@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o driver_cfa_cpp-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc
     1096
     1097driver_cfa_cpp-main.obj: main.cc
     1098@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT driver_cfa_cpp-main.obj -MD -MP -MF $(DEPDIR)/driver_cfa_cpp-main.Tpo -c -o driver_cfa_cpp-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi`
     1099@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/driver_cfa_cpp-main.Tpo $(DEPDIR)/driver_cfa_cpp-main.Po
     1100@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='main.cc' object='driver_cfa_cpp-main.obj' libtool=no @AMDEPBACKSLASH@
     1101@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1102@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o driver_cfa_cpp-main.obj `if test -f 'main.cc'; then $(CYGPATH_W) 'main.cc'; else $(CYGPATH_W) '$(srcdir)/main.cc'; fi`
     1103
     1104driver_cfa_cpp-MakeLibCfa.o: MakeLibCfa.cc
     1105@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT driver_cfa_cpp-MakeLibCfa.o -MD -MP -MF $(DEPDIR)/driver_cfa_cpp-MakeLibCfa.Tpo -c -o driver_cfa_cpp-MakeLibCfa.o `test -f 'MakeLibCfa.cc' || echo '$(srcdir)/'`MakeLibCfa.cc
     1106@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/driver_cfa_cpp-MakeLibCfa.Tpo $(DEPDIR)/driver_cfa_cpp-MakeLibCfa.Po
     1107@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='MakeLibCfa.cc' object='driver_cfa_cpp-MakeLibCfa.o' libtool=no @AMDEPBACKSLASH@
     1108@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1109@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o driver_cfa_cpp-MakeLibCfa.o `test -f 'MakeLibCfa.cc' || echo '$(srcdir)/'`MakeLibCfa.cc
     1110
     1111driver_cfa_cpp-MakeLibCfa.obj: MakeLibCfa.cc
     1112@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT driver_cfa_cpp-MakeLibCfa.obj -MD -MP -MF $(DEPDIR)/driver_cfa_cpp-MakeLibCfa.Tpo -c -o driver_cfa_cpp-MakeLibCfa.obj `if test -f 'MakeLibCfa.cc'; then $(CYGPATH_W) 'MakeLibCfa.cc'; else $(CYGPATH_W) '$(srcdir)/MakeLibCfa.cc'; fi`
     1113@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/driver_cfa_cpp-MakeLibCfa.Tpo $(DEPDIR)/driver_cfa_cpp-MakeLibCfa.Po
     1114@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='MakeLibCfa.cc' object='driver_cfa_cpp-MakeLibCfa.obj' libtool=no @AMDEPBACKSLASH@
     1115@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1116@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o driver_cfa_cpp-MakeLibCfa.obj `if test -f 'MakeLibCfa.cc'; then $(CYGPATH_W) 'MakeLibCfa.cc'; else $(CYGPATH_W) '$(srcdir)/MakeLibCfa.cc'; fi`
     1117
     1118CodeGen/driver_cfa_cpp-Generate.o: CodeGen/Generate.cc
     1119@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-Generate.o -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Tpo -c -o CodeGen/driver_cfa_cpp-Generate.o `test -f 'CodeGen/Generate.cc' || echo '$(srcdir)/'`CodeGen/Generate.cc
     1120@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Po
     1121@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/Generate.cc' object='CodeGen/driver_cfa_cpp-Generate.o' libtool=no @AMDEPBACKSLASH@
     1122@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1123@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-Generate.o `test -f 'CodeGen/Generate.cc' || echo '$(srcdir)/'`CodeGen/Generate.cc
     1124
     1125CodeGen/driver_cfa_cpp-Generate.obj: CodeGen/Generate.cc
     1126@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-Generate.obj -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Tpo -c -o CodeGen/driver_cfa_cpp-Generate.obj `if test -f 'CodeGen/Generate.cc'; then $(CYGPATH_W) 'CodeGen/Generate.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/Generate.cc'; fi`
     1127@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Po
     1128@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/Generate.cc' object='CodeGen/driver_cfa_cpp-Generate.obj' libtool=no @AMDEPBACKSLASH@
     1129@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1130@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-Generate.obj `if test -f 'CodeGen/Generate.cc'; then $(CYGPATH_W) 'CodeGen/Generate.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/Generate.cc'; fi`
     1131
     1132CodeGen/driver_cfa_cpp-CodeGenerator.o: CodeGen/CodeGenerator.cc
     1133@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-CodeGenerator.o -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-CodeGenerator.Tpo -c -o CodeGen/driver_cfa_cpp-CodeGenerator.o `test -f 'CodeGen/CodeGenerator.cc' || echo '$(srcdir)/'`CodeGen/CodeGenerator.cc
     1134@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-CodeGenerator.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-CodeGenerator.Po
     1135@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/CodeGenerator.cc' object='CodeGen/driver_cfa_cpp-CodeGenerator.o' libtool=no @AMDEPBACKSLASH@
     1136@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1137@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-CodeGenerator.o `test -f 'CodeGen/CodeGenerator.cc' || echo '$(srcdir)/'`CodeGen/CodeGenerator.cc
     1138
     1139CodeGen/driver_cfa_cpp-CodeGenerator.obj: CodeGen/CodeGenerator.cc
     1140@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-CodeGenerator.obj -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-CodeGenerator.Tpo -c -o CodeGen/driver_cfa_cpp-CodeGenerator.obj `if test -f 'CodeGen/CodeGenerator.cc'; then $(CYGPATH_W) 'CodeGen/CodeGenerator.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/CodeGenerator.cc'; fi`
     1141@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-CodeGenerator.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-CodeGenerator.Po
     1142@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/CodeGenerator.cc' object='CodeGen/driver_cfa_cpp-CodeGenerator.obj' libtool=no @AMDEPBACKSLASH@
     1143@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1144@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-CodeGenerator.obj `if test -f 'CodeGen/CodeGenerator.cc'; then $(CYGPATH_W) 'CodeGen/CodeGenerator.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/CodeGenerator.cc'; fi`
     1145
     1146CodeGen/driver_cfa_cpp-GenType.o: CodeGen/GenType.cc
     1147@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-GenType.o -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-GenType.Tpo -c -o CodeGen/driver_cfa_cpp-GenType.o `test -f 'CodeGen/GenType.cc' || echo '$(srcdir)/'`CodeGen/GenType.cc
     1148@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-GenType.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-GenType.Po
     1149@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/GenType.cc' object='CodeGen/driver_cfa_cpp-GenType.o' libtool=no @AMDEPBACKSLASH@
     1150@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1151@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-GenType.o `test -f 'CodeGen/GenType.cc' || echo '$(srcdir)/'`CodeGen/GenType.cc
     1152
     1153CodeGen/driver_cfa_cpp-GenType.obj: CodeGen/GenType.cc
     1154@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-GenType.obj -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-GenType.Tpo -c -o CodeGen/driver_cfa_cpp-GenType.obj `if test -f 'CodeGen/GenType.cc'; then $(CYGPATH_W) 'CodeGen/GenType.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/GenType.cc'; fi`
     1155@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-GenType.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-GenType.Po
     1156@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/GenType.cc' object='CodeGen/driver_cfa_cpp-GenType.obj' libtool=no @AMDEPBACKSLASH@
     1157@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1158@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-GenType.obj `if test -f 'CodeGen/GenType.cc'; then $(CYGPATH_W) 'CodeGen/GenType.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/GenType.cc'; fi`
     1159
     1160CodeGen/driver_cfa_cpp-FixNames.o: CodeGen/FixNames.cc
     1161@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-FixNames.o -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-FixNames.Tpo -c -o CodeGen/driver_cfa_cpp-FixNames.o `test -f 'CodeGen/FixNames.cc' || echo '$(srcdir)/'`CodeGen/FixNames.cc
     1162@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-FixNames.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-FixNames.Po
     1163@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/FixNames.cc' object='CodeGen/driver_cfa_cpp-FixNames.o' libtool=no @AMDEPBACKSLASH@
     1164@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1165@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-FixNames.o `test -f 'CodeGen/FixNames.cc' || echo '$(srcdir)/'`CodeGen/FixNames.cc
     1166
     1167CodeGen/driver_cfa_cpp-FixNames.obj: CodeGen/FixNames.cc
     1168@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-FixNames.obj -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-FixNames.Tpo -c -o CodeGen/driver_cfa_cpp-FixNames.obj `if test -f 'CodeGen/FixNames.cc'; then $(CYGPATH_W) 'CodeGen/FixNames.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/FixNames.cc'; fi`
     1169@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-FixNames.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-FixNames.Po
     1170@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/FixNames.cc' object='CodeGen/driver_cfa_cpp-FixNames.obj' libtool=no @AMDEPBACKSLASH@
     1171@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1172@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-FixNames.obj `if test -f 'CodeGen/FixNames.cc'; then $(CYGPATH_W) 'CodeGen/FixNames.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/FixNames.cc'; fi`
     1173
     1174CodeGen/driver_cfa_cpp-FixMain.o: CodeGen/FixMain.cc
     1175@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-FixMain.o -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-FixMain.Tpo -c -o CodeGen/driver_cfa_cpp-FixMain.o `test -f 'CodeGen/FixMain.cc' || echo '$(srcdir)/'`CodeGen/FixMain.cc
     1176@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-FixMain.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-FixMain.Po
     1177@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/FixMain.cc' object='CodeGen/driver_cfa_cpp-FixMain.o' libtool=no @AMDEPBACKSLASH@
     1178@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1179@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-FixMain.o `test -f 'CodeGen/FixMain.cc' || echo '$(srcdir)/'`CodeGen/FixMain.cc
     1180
     1181CodeGen/driver_cfa_cpp-FixMain.obj: CodeGen/FixMain.cc
     1182@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-FixMain.obj -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-FixMain.Tpo -c -o CodeGen/driver_cfa_cpp-FixMain.obj `if test -f 'CodeGen/FixMain.cc'; then $(CYGPATH_W) 'CodeGen/FixMain.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/FixMain.cc'; fi`
     1183@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-FixMain.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-FixMain.Po
     1184@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/FixMain.cc' object='CodeGen/driver_cfa_cpp-FixMain.obj' libtool=no @AMDEPBACKSLASH@
     1185@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1186@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-FixMain.obj `if test -f 'CodeGen/FixMain.cc'; then $(CYGPATH_W) 'CodeGen/FixMain.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/FixMain.cc'; fi`
     1187
     1188CodeGen/driver_cfa_cpp-OperatorTable.o: CodeGen/OperatorTable.cc
     1189@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-OperatorTable.o -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Tpo -c -o CodeGen/driver_cfa_cpp-OperatorTable.o `test -f 'CodeGen/OperatorTable.cc' || echo '$(srcdir)/'`CodeGen/OperatorTable.cc
     1190@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Po
     1191@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/OperatorTable.cc' object='CodeGen/driver_cfa_cpp-OperatorTable.o' libtool=no @AMDEPBACKSLASH@
     1192@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1193@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-OperatorTable.o `test -f 'CodeGen/OperatorTable.cc' || echo '$(srcdir)/'`CodeGen/OperatorTable.cc
     1194
     1195CodeGen/driver_cfa_cpp-OperatorTable.obj: CodeGen/OperatorTable.cc
     1196@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeGen/driver_cfa_cpp-OperatorTable.obj -MD -MP -MF CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Tpo -c -o CodeGen/driver_cfa_cpp-OperatorTable.obj `if test -f 'CodeGen/OperatorTable.cc'; then $(CYGPATH_W) 'CodeGen/OperatorTable.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/OperatorTable.cc'; fi`
     1197@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Tpo CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Po
     1198@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeGen/OperatorTable.cc' object='CodeGen/driver_cfa_cpp-OperatorTable.obj' libtool=no @AMDEPBACKSLASH@
     1199@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1200@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeGen/driver_cfa_cpp-OperatorTable.obj `if test -f 'CodeGen/OperatorTable.cc'; then $(CYGPATH_W) 'CodeGen/OperatorTable.cc'; else $(CYGPATH_W) '$(srcdir)/CodeGen/OperatorTable.cc'; fi`
     1201
     1202CodeTools/driver_cfa_cpp-DeclStats.o: CodeTools/DeclStats.cc
     1203@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeTools/driver_cfa_cpp-DeclStats.o -MD -MP -MF CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Tpo -c -o CodeTools/driver_cfa_cpp-DeclStats.o `test -f 'CodeTools/DeclStats.cc' || echo '$(srcdir)/'`CodeTools/DeclStats.cc
     1204@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Tpo CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Po
     1205@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeTools/DeclStats.cc' object='CodeTools/driver_cfa_cpp-DeclStats.o' libtool=no @AMDEPBACKSLASH@
     1206@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1207@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeTools/driver_cfa_cpp-DeclStats.o `test -f 'CodeTools/DeclStats.cc' || echo '$(srcdir)/'`CodeTools/DeclStats.cc
     1208
     1209CodeTools/driver_cfa_cpp-DeclStats.obj: CodeTools/DeclStats.cc
     1210@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeTools/driver_cfa_cpp-DeclStats.obj -MD -MP -MF CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Tpo -c -o CodeTools/driver_cfa_cpp-DeclStats.obj `if test -f 'CodeTools/DeclStats.cc'; then $(CYGPATH_W) 'CodeTools/DeclStats.cc'; else $(CYGPATH_W) '$(srcdir)/CodeTools/DeclStats.cc'; fi`
     1211@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Tpo CodeTools/$(DEPDIR)/driver_cfa_cpp-DeclStats.Po
     1212@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeTools/DeclStats.cc' object='CodeTools/driver_cfa_cpp-DeclStats.obj' libtool=no @AMDEPBACKSLASH@
     1213@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1214@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeTools/driver_cfa_cpp-DeclStats.obj `if test -f 'CodeTools/DeclStats.cc'; then $(CYGPATH_W) 'CodeTools/DeclStats.cc'; else $(CYGPATH_W) '$(srcdir)/CodeTools/DeclStats.cc'; fi`
     1215
     1216CodeTools/driver_cfa_cpp-TrackLoc.o: CodeTools/TrackLoc.cc
     1217@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeTools/driver_cfa_cpp-TrackLoc.o -MD -MP -MF CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo -c -o CodeTools/driver_cfa_cpp-TrackLoc.o `test -f 'CodeTools/TrackLoc.cc' || echo '$(srcdir)/'`CodeTools/TrackLoc.cc
     1218@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Po
     1219@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeTools/TrackLoc.cc' object='CodeTools/driver_cfa_cpp-TrackLoc.o' libtool=no @AMDEPBACKSLASH@
     1220@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1221@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeTools/driver_cfa_cpp-TrackLoc.o `test -f 'CodeTools/TrackLoc.cc' || echo '$(srcdir)/'`CodeTools/TrackLoc.cc
     1222
     1223CodeTools/driver_cfa_cpp-TrackLoc.obj: CodeTools/TrackLoc.cc
     1224@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT CodeTools/driver_cfa_cpp-TrackLoc.obj -MD -MP -MF CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo -c -o CodeTools/driver_cfa_cpp-TrackLoc.obj `if test -f 'CodeTools/TrackLoc.cc'; then $(CYGPATH_W) 'CodeTools/TrackLoc.cc'; else $(CYGPATH_W) '$(srcdir)/CodeTools/TrackLoc.cc'; fi`
     1225@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Tpo CodeTools/$(DEPDIR)/driver_cfa_cpp-TrackLoc.Po
     1226@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='CodeTools/TrackLoc.cc' object='CodeTools/driver_cfa_cpp-TrackLoc.obj' libtool=no @AMDEPBACKSLASH@
     1227@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1228@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o CodeTools/driver_cfa_cpp-TrackLoc.obj `if test -f 'CodeTools/TrackLoc.cc'; then $(CYGPATH_W) 'CodeTools/TrackLoc.cc'; else $(CYGPATH_W) '$(srcdir)/CodeTools/TrackLoc.cc'; fi`
     1229
     1230Concurrency/driver_cfa_cpp-Keywords.o: Concurrency/Keywords.cc
     1231@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Concurrency/driver_cfa_cpp-Keywords.o -MD -MP -MF Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Tpo -c -o Concurrency/driver_cfa_cpp-Keywords.o `test -f 'Concurrency/Keywords.cc' || echo '$(srcdir)/'`Concurrency/Keywords.cc
     1232@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Tpo Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Po
     1233@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Concurrency/Keywords.cc' object='Concurrency/driver_cfa_cpp-Keywords.o' libtool=no @AMDEPBACKSLASH@
     1234@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1235@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Concurrency/driver_cfa_cpp-Keywords.o `test -f 'Concurrency/Keywords.cc' || echo '$(srcdir)/'`Concurrency/Keywords.cc
     1236
     1237Concurrency/driver_cfa_cpp-Keywords.obj: Concurrency/Keywords.cc
     1238@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Concurrency/driver_cfa_cpp-Keywords.obj -MD -MP -MF Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Tpo -c -o Concurrency/driver_cfa_cpp-Keywords.obj `if test -f 'Concurrency/Keywords.cc'; then $(CYGPATH_W) 'Concurrency/Keywords.cc'; else $(CYGPATH_W) '$(srcdir)/Concurrency/Keywords.cc'; fi`
     1239@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Tpo Concurrency/$(DEPDIR)/driver_cfa_cpp-Keywords.Po
     1240@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Concurrency/Keywords.cc' object='Concurrency/driver_cfa_cpp-Keywords.obj' libtool=no @AMDEPBACKSLASH@
     1241@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1242@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Concurrency/driver_cfa_cpp-Keywords.obj `if test -f 'Concurrency/Keywords.cc'; then $(CYGPATH_W) 'Concurrency/Keywords.cc'; else $(CYGPATH_W) '$(srcdir)/Concurrency/Keywords.cc'; fi`
     1243
     1244Concurrency/driver_cfa_cpp-Waitfor.o: Concurrency/Waitfor.cc
     1245@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Concurrency/driver_cfa_cpp-Waitfor.o -MD -MP -MF Concurrency/$(DEPDIR)/driver_cfa_cpp-Waitfor.Tpo -c -o Concurrency/driver_cfa_cpp-Waitfor.o `test -f 'Concurrency/Waitfor.cc' || echo '$(srcdir)/'`Concurrency/Waitfor.cc
     1246@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Concurrency/$(DEPDIR)/driver_cfa_cpp-Waitfor.Tpo Concurrency/$(DEPDIR)/driver_cfa_cpp-Waitfor.Po
     1247@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Concurrency/Waitfor.cc' object='Concurrency/driver_cfa_cpp-Waitfor.o' libtool=no @AMDEPBACKSLASH@
     1248@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1249@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Concurrency/driver_cfa_cpp-Waitfor.o `test -f 'Concurrency/Waitfor.cc' || echo '$(srcdir)/'`Concurrency/Waitfor.cc
     1250
     1251Concurrency/driver_cfa_cpp-Waitfor.obj: Concurrency/Waitfor.cc
     1252@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Concurrency/driver_cfa_cpp-Waitfor.obj -MD -MP -MF Concurrency/$(DEPDIR)/driver_cfa_cpp-Waitfor.Tpo -c -o Concurrency/driver_cfa_cpp-Waitfor.obj `if test -f 'Concurrency/Waitfor.cc'; then $(CYGPATH_W) 'Concurrency/Waitfor.cc'; else $(CYGPATH_W) '$(srcdir)/Concurrency/Waitfor.cc'; fi`
     1253@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Concurrency/$(DEPDIR)/driver_cfa_cpp-Waitfor.Tpo Concurrency/$(DEPDIR)/driver_cfa_cpp-Waitfor.Po
     1254@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Concurrency/Waitfor.cc' object='Concurrency/driver_cfa_cpp-Waitfor.obj' libtool=no @AMDEPBACKSLASH@
     1255@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1256@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Concurrency/driver_cfa_cpp-Waitfor.obj `if test -f 'Concurrency/Waitfor.cc'; then $(CYGPATH_W) 'Concurrency/Waitfor.cc'; else $(CYGPATH_W) '$(srcdir)/Concurrency/Waitfor.cc'; fi`
     1257
     1258Common/driver_cfa_cpp-SemanticError.o: Common/SemanticError.cc
     1259@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-SemanticError.o -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Tpo -c -o Common/driver_cfa_cpp-SemanticError.o `test -f 'Common/SemanticError.cc' || echo '$(srcdir)/'`Common/SemanticError.cc
     1260@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Tpo Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Po
     1261@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/SemanticError.cc' object='Common/driver_cfa_cpp-SemanticError.o' libtool=no @AMDEPBACKSLASH@
     1262@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1263@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-SemanticError.o `test -f 'Common/SemanticError.cc' || echo '$(srcdir)/'`Common/SemanticError.cc
     1264
     1265Common/driver_cfa_cpp-SemanticError.obj: Common/SemanticError.cc
     1266@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-SemanticError.obj -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Tpo -c -o Common/driver_cfa_cpp-SemanticError.obj `if test -f 'Common/SemanticError.cc'; then $(CYGPATH_W) 'Common/SemanticError.cc'; else $(CYGPATH_W) '$(srcdir)/Common/SemanticError.cc'; fi`
     1267@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Tpo Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Po
     1268@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/SemanticError.cc' object='Common/driver_cfa_cpp-SemanticError.obj' libtool=no @AMDEPBACKSLASH@
     1269@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1270@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-SemanticError.obj `if test -f 'Common/SemanticError.cc'; then $(CYGPATH_W) 'Common/SemanticError.cc'; else $(CYGPATH_W) '$(srcdir)/Common/SemanticError.cc'; fi`
     1271
     1272Common/driver_cfa_cpp-UniqueName.o: Common/UniqueName.cc
     1273@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-UniqueName.o -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Tpo -c -o Common/driver_cfa_cpp-UniqueName.o `test -f 'Common/UniqueName.cc' || echo '$(srcdir)/'`Common/UniqueName.cc
     1274@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Tpo Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Po
     1275@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/UniqueName.cc' object='Common/driver_cfa_cpp-UniqueName.o' libtool=no @AMDEPBACKSLASH@
     1276@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1277@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-UniqueName.o `test -f 'Common/UniqueName.cc' || echo '$(srcdir)/'`Common/UniqueName.cc
     1278
     1279Common/driver_cfa_cpp-UniqueName.obj: Common/UniqueName.cc
     1280@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-UniqueName.obj -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Tpo -c -o Common/driver_cfa_cpp-UniqueName.obj `if test -f 'Common/UniqueName.cc'; then $(CYGPATH_W) 'Common/UniqueName.cc'; else $(CYGPATH_W) '$(srcdir)/Common/UniqueName.cc'; fi`
     1281@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Tpo Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Po
     1282@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/UniqueName.cc' object='Common/driver_cfa_cpp-UniqueName.obj' libtool=no @AMDEPBACKSLASH@
     1283@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1284@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-UniqueName.obj `if test -f 'Common/UniqueName.cc'; then $(CYGPATH_W) 'Common/UniqueName.cc'; else $(CYGPATH_W) '$(srcdir)/Common/UniqueName.cc'; fi`
     1285
     1286Common/driver_cfa_cpp-DebugMalloc.o: Common/DebugMalloc.cc
     1287@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-DebugMalloc.o -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Tpo -c -o Common/driver_cfa_cpp-DebugMalloc.o `test -f 'Common/DebugMalloc.cc' || echo '$(srcdir)/'`Common/DebugMalloc.cc
     1288@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Tpo Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Po
     1289@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/DebugMalloc.cc' object='Common/driver_cfa_cpp-DebugMalloc.o' libtool=no @AMDEPBACKSLASH@
     1290@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1291@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-DebugMalloc.o `test -f 'Common/DebugMalloc.cc' || echo '$(srcdir)/'`Common/DebugMalloc.cc
     1292
     1293Common/driver_cfa_cpp-DebugMalloc.obj: Common/DebugMalloc.cc
     1294@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-DebugMalloc.obj -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Tpo -c -o Common/driver_cfa_cpp-DebugMalloc.obj `if test -f 'Common/DebugMalloc.cc'; then $(CYGPATH_W) 'Common/DebugMalloc.cc'; else $(CYGPATH_W) '$(srcdir)/Common/DebugMalloc.cc'; fi`
     1295@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Tpo Common/$(DEPDIR)/driver_cfa_cpp-DebugMalloc.Po
     1296@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/DebugMalloc.cc' object='Common/driver_cfa_cpp-DebugMalloc.obj' libtool=no @AMDEPBACKSLASH@
     1297@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1298@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-DebugMalloc.obj `if test -f 'Common/DebugMalloc.cc'; then $(CYGPATH_W) 'Common/DebugMalloc.cc'; else $(CYGPATH_W) '$(srcdir)/Common/DebugMalloc.cc'; fi`
     1299
     1300Common/driver_cfa_cpp-Assert.o: Common/Assert.cc
     1301@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-Assert.o -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo -c -o Common/driver_cfa_cpp-Assert.o `test -f 'Common/Assert.cc' || echo '$(srcdir)/'`Common/Assert.cc
     1302@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo Common/$(DEPDIR)/driver_cfa_cpp-Assert.Po
     1303@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/Assert.cc' object='Common/driver_cfa_cpp-Assert.o' libtool=no @AMDEPBACKSLASH@
     1304@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1305@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-Assert.o `test -f 'Common/Assert.cc' || echo '$(srcdir)/'`Common/Assert.cc
     1306
     1307Common/driver_cfa_cpp-Assert.obj: Common/Assert.cc
     1308@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-Assert.obj -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo -c -o Common/driver_cfa_cpp-Assert.obj `if test -f 'Common/Assert.cc'; then $(CYGPATH_W) 'Common/Assert.cc'; else $(CYGPATH_W) '$(srcdir)/Common/Assert.cc'; fi`
     1309@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo Common/$(DEPDIR)/driver_cfa_cpp-Assert.Po
     1310@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/Assert.cc' object='Common/driver_cfa_cpp-Assert.obj' libtool=no @AMDEPBACKSLASH@
     1311@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1312@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-Assert.obj `if test -f 'Common/Assert.cc'; then $(CYGPATH_W) 'Common/Assert.cc'; else $(CYGPATH_W) '$(srcdir)/Common/Assert.cc'; fi`
     1313
     1314Common/driver_cfa_cpp-Heap.o: Common/Heap.cc
     1315@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-Heap.o -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-Heap.Tpo -c -o Common/driver_cfa_cpp-Heap.o `test -f 'Common/Heap.cc' || echo '$(srcdir)/'`Common/Heap.cc
     1316@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-Heap.Tpo Common/$(DEPDIR)/driver_cfa_cpp-Heap.Po
     1317@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/Heap.cc' object='Common/driver_cfa_cpp-Heap.o' libtool=no @AMDEPBACKSLASH@
     1318@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1319@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-Heap.o `test -f 'Common/Heap.cc' || echo '$(srcdir)/'`Common/Heap.cc
     1320
     1321Common/driver_cfa_cpp-Heap.obj: Common/Heap.cc
     1322@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-Heap.obj -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-Heap.Tpo -c -o Common/driver_cfa_cpp-Heap.obj `if test -f 'Common/Heap.cc'; then $(CYGPATH_W) 'Common/Heap.cc'; else $(CYGPATH_W) '$(srcdir)/Common/Heap.cc'; fi`
     1323@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-Heap.Tpo Common/$(DEPDIR)/driver_cfa_cpp-Heap.Po
     1324@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Common/Heap.cc' object='Common/driver_cfa_cpp-Heap.obj' libtool=no @AMDEPBACKSLASH@
     1325@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1326@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-Heap.obj `if test -f 'Common/Heap.cc'; then $(CYGPATH_W) 'Common/Heap.cc'; else $(CYGPATH_W) '$(srcdir)/Common/Heap.cc'; fi`
     1327
     1328ControlStruct/driver_cfa_cpp-LabelGenerator.o: ControlStruct/LabelGenerator.cc
     1329@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-LabelGenerator.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Tpo -c -o ControlStruct/driver_cfa_cpp-LabelGenerator.o `test -f 'ControlStruct/LabelGenerator.cc' || echo '$(srcdir)/'`ControlStruct/LabelGenerator.cc
     1330@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Po
     1331@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/LabelGenerator.cc' object='ControlStruct/driver_cfa_cpp-LabelGenerator.o' libtool=no @AMDEPBACKSLASH@
     1332@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1333@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-LabelGenerator.o `test -f 'ControlStruct/LabelGenerator.cc' || echo '$(srcdir)/'`ControlStruct/LabelGenerator.cc
     1334
     1335ControlStruct/driver_cfa_cpp-LabelGenerator.obj: ControlStruct/LabelGenerator.cc
     1336@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-LabelGenerator.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Tpo -c -o ControlStruct/driver_cfa_cpp-LabelGenerator.obj `if test -f 'ControlStruct/LabelGenerator.cc'; then $(CYGPATH_W) 'ControlStruct/LabelGenerator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/LabelGenerator.cc'; fi`
     1337@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Po
     1338@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/LabelGenerator.cc' object='ControlStruct/driver_cfa_cpp-LabelGenerator.obj' libtool=no @AMDEPBACKSLASH@
     1339@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1340@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-LabelGenerator.obj `if test -f 'ControlStruct/LabelGenerator.cc'; then $(CYGPATH_W) 'ControlStruct/LabelGenerator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/LabelGenerator.cc'; fi`
     1341
     1342ControlStruct/driver_cfa_cpp-LabelFixer.o: ControlStruct/LabelFixer.cc
     1343@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-LabelFixer.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Tpo -c -o ControlStruct/driver_cfa_cpp-LabelFixer.o `test -f 'ControlStruct/LabelFixer.cc' || echo '$(srcdir)/'`ControlStruct/LabelFixer.cc
     1344@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Po
     1345@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/LabelFixer.cc' object='ControlStruct/driver_cfa_cpp-LabelFixer.o' libtool=no @AMDEPBACKSLASH@
     1346@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1347@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-LabelFixer.o `test -f 'ControlStruct/LabelFixer.cc' || echo '$(srcdir)/'`ControlStruct/LabelFixer.cc
     1348
     1349ControlStruct/driver_cfa_cpp-LabelFixer.obj: ControlStruct/LabelFixer.cc
     1350@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-LabelFixer.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Tpo -c -o ControlStruct/driver_cfa_cpp-LabelFixer.obj `if test -f 'ControlStruct/LabelFixer.cc'; then $(CYGPATH_W) 'ControlStruct/LabelFixer.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/LabelFixer.cc'; fi`
     1351@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Po
     1352@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/LabelFixer.cc' object='ControlStruct/driver_cfa_cpp-LabelFixer.obj' libtool=no @AMDEPBACKSLASH@
     1353@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1354@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-LabelFixer.obj `if test -f 'ControlStruct/LabelFixer.cc'; then $(CYGPATH_W) 'ControlStruct/LabelFixer.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/LabelFixer.cc'; fi`
     1355
     1356ControlStruct/driver_cfa_cpp-MLEMutator.o: ControlStruct/MLEMutator.cc
     1357@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-MLEMutator.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Tpo -c -o ControlStruct/driver_cfa_cpp-MLEMutator.o `test -f 'ControlStruct/MLEMutator.cc' || echo '$(srcdir)/'`ControlStruct/MLEMutator.cc
     1358@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Po
     1359@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/MLEMutator.cc' object='ControlStruct/driver_cfa_cpp-MLEMutator.o' libtool=no @AMDEPBACKSLASH@
     1360@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1361@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-MLEMutator.o `test -f 'ControlStruct/MLEMutator.cc' || echo '$(srcdir)/'`ControlStruct/MLEMutator.cc
     1362
     1363ControlStruct/driver_cfa_cpp-MLEMutator.obj: ControlStruct/MLEMutator.cc
     1364@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-MLEMutator.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Tpo -c -o ControlStruct/driver_cfa_cpp-MLEMutator.obj `if test -f 'ControlStruct/MLEMutator.cc'; then $(CYGPATH_W) 'ControlStruct/MLEMutator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/MLEMutator.cc'; fi`
     1365@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Po
     1366@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/MLEMutator.cc' object='ControlStruct/driver_cfa_cpp-MLEMutator.obj' libtool=no @AMDEPBACKSLASH@
     1367@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1368@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-MLEMutator.obj `if test -f 'ControlStruct/MLEMutator.cc'; then $(CYGPATH_W) 'ControlStruct/MLEMutator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/MLEMutator.cc'; fi`
     1369
     1370ControlStruct/driver_cfa_cpp-Mutate.o: ControlStruct/Mutate.cc
     1371@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-Mutate.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Tpo -c -o ControlStruct/driver_cfa_cpp-Mutate.o `test -f 'ControlStruct/Mutate.cc' || echo '$(srcdir)/'`ControlStruct/Mutate.cc
     1372@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Po
     1373@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/Mutate.cc' object='ControlStruct/driver_cfa_cpp-Mutate.o' libtool=no @AMDEPBACKSLASH@
     1374@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1375@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-Mutate.o `test -f 'ControlStruct/Mutate.cc' || echo '$(srcdir)/'`ControlStruct/Mutate.cc
     1376
     1377ControlStruct/driver_cfa_cpp-Mutate.obj: ControlStruct/Mutate.cc
     1378@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-Mutate.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Tpo -c -o ControlStruct/driver_cfa_cpp-Mutate.obj `if test -f 'ControlStruct/Mutate.cc'; then $(CYGPATH_W) 'ControlStruct/Mutate.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/Mutate.cc'; fi`
     1379@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Po
     1380@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/Mutate.cc' object='ControlStruct/driver_cfa_cpp-Mutate.obj' libtool=no @AMDEPBACKSLASH@
     1381@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1382@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-Mutate.obj `if test -f 'ControlStruct/Mutate.cc'; then $(CYGPATH_W) 'ControlStruct/Mutate.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/Mutate.cc'; fi`
     1383
     1384ControlStruct/driver_cfa_cpp-ForExprMutator.o: ControlStruct/ForExprMutator.cc
     1385@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-ForExprMutator.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Tpo -c -o ControlStruct/driver_cfa_cpp-ForExprMutator.o `test -f 'ControlStruct/ForExprMutator.cc' || echo '$(srcdir)/'`ControlStruct/ForExprMutator.cc
     1386@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Po
     1387@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/ForExprMutator.cc' object='ControlStruct/driver_cfa_cpp-ForExprMutator.o' libtool=no @AMDEPBACKSLASH@
     1388@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1389@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ForExprMutator.o `test -f 'ControlStruct/ForExprMutator.cc' || echo '$(srcdir)/'`ControlStruct/ForExprMutator.cc
     1390
     1391ControlStruct/driver_cfa_cpp-ForExprMutator.obj: ControlStruct/ForExprMutator.cc
     1392@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-ForExprMutator.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Tpo -c -o ControlStruct/driver_cfa_cpp-ForExprMutator.obj `if test -f 'ControlStruct/ForExprMutator.cc'; then $(CYGPATH_W) 'ControlStruct/ForExprMutator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ForExprMutator.cc'; fi`
     1393@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-ForExprMutator.Po
     1394@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/ForExprMutator.cc' object='ControlStruct/driver_cfa_cpp-ForExprMutator.obj' libtool=no @AMDEPBACKSLASH@
     1395@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1396@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ForExprMutator.obj `if test -f 'ControlStruct/ForExprMutator.cc'; then $(CYGPATH_W) 'ControlStruct/ForExprMutator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ForExprMutator.cc'; fi`
     1397
     1398ControlStruct/driver_cfa_cpp-ExceptTranslate.o: ControlStruct/ExceptTranslate.cc
     1399@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-ExceptTranslate.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.o `test -f 'ControlStruct/ExceptTranslate.cc' || echo '$(srcdir)/'`ControlStruct/ExceptTranslate.cc
     1400@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Po
     1401@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/ExceptTranslate.cc' object='ControlStruct/driver_cfa_cpp-ExceptTranslate.o' libtool=no @AMDEPBACKSLASH@
     1402@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1403@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.o `test -f 'ControlStruct/ExceptTranslate.cc' || echo '$(srcdir)/'`ControlStruct/ExceptTranslate.cc
     1404
     1405ControlStruct/driver_cfa_cpp-ExceptTranslate.obj: ControlStruct/ExceptTranslate.cc
     1406@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-ExceptTranslate.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.obj `if test -f 'ControlStruct/ExceptTranslate.cc'; then $(CYGPATH_W) 'ControlStruct/ExceptTranslate.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ExceptTranslate.cc'; fi`
     1407@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-ExceptTranslate.Po
     1408@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ControlStruct/ExceptTranslate.cc' object='ControlStruct/driver_cfa_cpp-ExceptTranslate.obj' libtool=no @AMDEPBACKSLASH@
     1409@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1410@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ExceptTranslate.obj `if test -f 'ControlStruct/ExceptTranslate.cc'; then $(CYGPATH_W) 'ControlStruct/ExceptTranslate.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ExceptTranslate.cc'; fi`
     1411
     1412GenPoly/driver_cfa_cpp-Box.o: GenPoly/Box.cc
     1413@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Box.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Tpo -c -o GenPoly/driver_cfa_cpp-Box.o `test -f 'GenPoly/Box.cc' || echo '$(srcdir)/'`GenPoly/Box.cc
     1414@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Po
     1415@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/Box.cc' object='GenPoly/driver_cfa_cpp-Box.o' libtool=no @AMDEPBACKSLASH@
     1416@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1417@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-Box.o `test -f 'GenPoly/Box.cc' || echo '$(srcdir)/'`GenPoly/Box.cc
     1418
     1419GenPoly/driver_cfa_cpp-Box.obj: GenPoly/Box.cc
     1420@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Box.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Tpo -c -o GenPoly/driver_cfa_cpp-Box.obj `if test -f 'GenPoly/Box.cc'; then $(CYGPATH_W) 'GenPoly/Box.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/Box.cc'; fi`
     1421@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Po
     1422@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/Box.cc' object='GenPoly/driver_cfa_cpp-Box.obj' libtool=no @AMDEPBACKSLASH@
     1423@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1424@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-Box.obj `if test -f 'GenPoly/Box.cc'; then $(CYGPATH_W) 'GenPoly/Box.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/Box.cc'; fi`
     1425
     1426GenPoly/driver_cfa_cpp-GenPoly.o: GenPoly/GenPoly.cc
     1427@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-GenPoly.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Tpo -c -o GenPoly/driver_cfa_cpp-GenPoly.o `test -f 'GenPoly/GenPoly.cc' || echo '$(srcdir)/'`GenPoly/GenPoly.cc
     1428@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po
     1429@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/GenPoly.cc' object='GenPoly/driver_cfa_cpp-GenPoly.o' libtool=no @AMDEPBACKSLASH@
     1430@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1431@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-GenPoly.o `test -f 'GenPoly/GenPoly.cc' || echo '$(srcdir)/'`GenPoly/GenPoly.cc
     1432
     1433GenPoly/driver_cfa_cpp-GenPoly.obj: GenPoly/GenPoly.cc
     1434@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-GenPoly.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Tpo -c -o GenPoly/driver_cfa_cpp-GenPoly.obj `if test -f 'GenPoly/GenPoly.cc'; then $(CYGPATH_W) 'GenPoly/GenPoly.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/GenPoly.cc'; fi`
     1435@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po
     1436@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/GenPoly.cc' object='GenPoly/driver_cfa_cpp-GenPoly.obj' libtool=no @AMDEPBACKSLASH@
     1437@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1438@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-GenPoly.obj `if test -f 'GenPoly/GenPoly.cc'; then $(CYGPATH_W) 'GenPoly/GenPoly.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/GenPoly.cc'; fi`
     1439
     1440GenPoly/driver_cfa_cpp-ScrubTyVars.o: GenPoly/ScrubTyVars.cc
     1441@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-ScrubTyVars.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Tpo -c -o GenPoly/driver_cfa_cpp-ScrubTyVars.o `test -f 'GenPoly/ScrubTyVars.cc' || echo '$(srcdir)/'`GenPoly/ScrubTyVars.cc
     1442@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po
     1443@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/ScrubTyVars.cc' object='GenPoly/driver_cfa_cpp-ScrubTyVars.o' libtool=no @AMDEPBACKSLASH@
     1444@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1445@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-ScrubTyVars.o `test -f 'GenPoly/ScrubTyVars.cc' || echo '$(srcdir)/'`GenPoly/ScrubTyVars.cc
     1446
     1447GenPoly/driver_cfa_cpp-ScrubTyVars.obj: GenPoly/ScrubTyVars.cc
     1448@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-ScrubTyVars.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Tpo -c -o GenPoly/driver_cfa_cpp-ScrubTyVars.obj `if test -f 'GenPoly/ScrubTyVars.cc'; then $(CYGPATH_W) 'GenPoly/ScrubTyVars.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/ScrubTyVars.cc'; fi`
     1449@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po
     1450@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/ScrubTyVars.cc' object='GenPoly/driver_cfa_cpp-ScrubTyVars.obj' libtool=no @AMDEPBACKSLASH@
     1451@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1452@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-ScrubTyVars.obj `if test -f 'GenPoly/ScrubTyVars.cc'; then $(CYGPATH_W) 'GenPoly/ScrubTyVars.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/ScrubTyVars.cc'; fi`
     1453
     1454GenPoly/driver_cfa_cpp-Lvalue.o: GenPoly/Lvalue.cc
     1455@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Lvalue.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Tpo -c -o GenPoly/driver_cfa_cpp-Lvalue.o `test -f 'GenPoly/Lvalue.cc' || echo '$(srcdir)/'`GenPoly/Lvalue.cc
     1456@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Po
     1457@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/Lvalue.cc' object='GenPoly/driver_cfa_cpp-Lvalue.o' libtool=no @AMDEPBACKSLASH@
     1458@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1459@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-Lvalue.o `test -f 'GenPoly/Lvalue.cc' || echo '$(srcdir)/'`GenPoly/Lvalue.cc
     1460
     1461GenPoly/driver_cfa_cpp-Lvalue.obj: GenPoly/Lvalue.cc
     1462@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Lvalue.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Tpo -c -o GenPoly/driver_cfa_cpp-Lvalue.obj `if test -f 'GenPoly/Lvalue.cc'; then $(CYGPATH_W) 'GenPoly/Lvalue.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/Lvalue.cc'; fi`
     1463@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Po
     1464@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/Lvalue.cc' object='GenPoly/driver_cfa_cpp-Lvalue.obj' libtool=no @AMDEPBACKSLASH@
     1465@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1466@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-Lvalue.obj `if test -f 'GenPoly/Lvalue.cc'; then $(CYGPATH_W) 'GenPoly/Lvalue.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/Lvalue.cc'; fi`
     1467
     1468GenPoly/driver_cfa_cpp-Specialize.o: GenPoly/Specialize.cc
     1469@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Specialize.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Tpo -c -o GenPoly/driver_cfa_cpp-Specialize.o `test -f 'GenPoly/Specialize.cc' || echo '$(srcdir)/'`GenPoly/Specialize.cc
     1470@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po
     1471@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/Specialize.cc' object='GenPoly/driver_cfa_cpp-Specialize.o' libtool=no @AMDEPBACKSLASH@
     1472@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1473@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-Specialize.o `test -f 'GenPoly/Specialize.cc' || echo '$(srcdir)/'`GenPoly/Specialize.cc
     1474
     1475GenPoly/driver_cfa_cpp-Specialize.obj: GenPoly/Specialize.cc
     1476@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Specialize.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Tpo -c -o GenPoly/driver_cfa_cpp-Specialize.obj `if test -f 'GenPoly/Specialize.cc'; then $(CYGPATH_W) 'GenPoly/Specialize.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/Specialize.cc'; fi`
     1477@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po
     1478@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/Specialize.cc' object='GenPoly/driver_cfa_cpp-Specialize.obj' libtool=no @AMDEPBACKSLASH@
     1479@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1480@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-Specialize.obj `if test -f 'GenPoly/Specialize.cc'; then $(CYGPATH_W) 'GenPoly/Specialize.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/Specialize.cc'; fi`
     1481
     1482GenPoly/driver_cfa_cpp-FindFunction.o: GenPoly/FindFunction.cc
     1483@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-FindFunction.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Tpo -c -o GenPoly/driver_cfa_cpp-FindFunction.o `test -f 'GenPoly/FindFunction.cc' || echo '$(srcdir)/'`GenPoly/FindFunction.cc
     1484@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po
     1485@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/FindFunction.cc' object='GenPoly/driver_cfa_cpp-FindFunction.o' libtool=no @AMDEPBACKSLASH@
     1486@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1487@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-FindFunction.o `test -f 'GenPoly/FindFunction.cc' || echo '$(srcdir)/'`GenPoly/FindFunction.cc
     1488
     1489GenPoly/driver_cfa_cpp-FindFunction.obj: GenPoly/FindFunction.cc
     1490@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-FindFunction.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Tpo -c -o GenPoly/driver_cfa_cpp-FindFunction.obj `if test -f 'GenPoly/FindFunction.cc'; then $(CYGPATH_W) 'GenPoly/FindFunction.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/FindFunction.cc'; fi`
     1491@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po
     1492@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/FindFunction.cc' object='GenPoly/driver_cfa_cpp-FindFunction.obj' libtool=no @AMDEPBACKSLASH@
     1493@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1494@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-FindFunction.obj `if test -f 'GenPoly/FindFunction.cc'; then $(CYGPATH_W) 'GenPoly/FindFunction.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/FindFunction.cc'; fi`
     1495
     1496GenPoly/driver_cfa_cpp-InstantiateGeneric.o: GenPoly/InstantiateGeneric.cc
     1497@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
     1498@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po
     1499@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/InstantiateGeneric.cc' object='GenPoly/driver_cfa_cpp-InstantiateGeneric.o' libtool=no @AMDEPBACKSLASH@
     1500@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1501@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
     1502
     1503GenPoly/driver_cfa_cpp-InstantiateGeneric.obj: GenPoly/InstantiateGeneric.cc
     1504@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.obj `if test -f 'GenPoly/InstantiateGeneric.cc'; then $(CYGPATH_W) 'GenPoly/InstantiateGeneric.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/InstantiateGeneric.cc'; fi`
     1505@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po
     1506@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/InstantiateGeneric.cc' object='GenPoly/driver_cfa_cpp-InstantiateGeneric.obj' libtool=no @AMDEPBACKSLASH@
     1507@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1508@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.obj `if test -f 'GenPoly/InstantiateGeneric.cc'; then $(CYGPATH_W) 'GenPoly/InstantiateGeneric.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/InstantiateGeneric.cc'; fi`
     1509
     1510InitTweak/driver_cfa_cpp-GenInit.o: InitTweak/GenInit.cc
     1511@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-GenInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo -c -o InitTweak/driver_cfa_cpp-GenInit.o `test -f 'InitTweak/GenInit.cc' || echo '$(srcdir)/'`InitTweak/GenInit.cc
     1512@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po
     1513@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/GenInit.cc' object='InitTweak/driver_cfa_cpp-GenInit.o' libtool=no @AMDEPBACKSLASH@
     1514@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1515@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-GenInit.o `test -f 'InitTweak/GenInit.cc' || echo '$(srcdir)/'`InitTweak/GenInit.cc
     1516
     1517InitTweak/driver_cfa_cpp-GenInit.obj: InitTweak/GenInit.cc
     1518@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-GenInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo -c -o InitTweak/driver_cfa_cpp-GenInit.obj `if test -f 'InitTweak/GenInit.cc'; then $(CYGPATH_W) 'InitTweak/GenInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/GenInit.cc'; fi`
     1519@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po
     1520@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/GenInit.cc' object='InitTweak/driver_cfa_cpp-GenInit.obj' libtool=no @AMDEPBACKSLASH@
     1521@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1522@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-GenInit.obj `if test -f 'InitTweak/GenInit.cc'; then $(CYGPATH_W) 'InitTweak/GenInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/GenInit.cc'; fi`
     1523
     1524InitTweak/driver_cfa_cpp-FixInit.o: InitTweak/FixInit.cc
     1525@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixInit.o `test -f 'InitTweak/FixInit.cc' || echo '$(srcdir)/'`InitTweak/FixInit.cc
     1526@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po
     1527@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/FixInit.cc' object='InitTweak/driver_cfa_cpp-FixInit.o' libtool=no @AMDEPBACKSLASH@
     1528@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1529@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixInit.o `test -f 'InitTweak/FixInit.cc' || echo '$(srcdir)/'`InitTweak/FixInit.cc
     1530
     1531InitTweak/driver_cfa_cpp-FixInit.obj: InitTweak/FixInit.cc
     1532@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixInit.obj `if test -f 'InitTweak/FixInit.cc'; then $(CYGPATH_W) 'InitTweak/FixInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixInit.cc'; fi`
     1533@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po
     1534@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/FixInit.cc' object='InitTweak/driver_cfa_cpp-FixInit.obj' libtool=no @AMDEPBACKSLASH@
     1535@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1536@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixInit.obj `if test -f 'InitTweak/FixInit.cc'; then $(CYGPATH_W) 'InitTweak/FixInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixInit.cc'; fi`
     1537
     1538InitTweak/driver_cfa_cpp-FixGlobalInit.o: InitTweak/FixGlobalInit.cc
     1539@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixGlobalInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.o `test -f 'InitTweak/FixGlobalInit.cc' || echo '$(srcdir)/'`InitTweak/FixGlobalInit.cc
     1540@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Po
     1541@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/FixGlobalInit.cc' object='InitTweak/driver_cfa_cpp-FixGlobalInit.o' libtool=no @AMDEPBACKSLASH@
     1542@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1543@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.o `test -f 'InitTweak/FixGlobalInit.cc' || echo '$(srcdir)/'`InitTweak/FixGlobalInit.cc
     1544
     1545InitTweak/driver_cfa_cpp-FixGlobalInit.obj: InitTweak/FixGlobalInit.cc
     1546@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixGlobalInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.obj `if test -f 'InitTweak/FixGlobalInit.cc'; then $(CYGPATH_W) 'InitTweak/FixGlobalInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixGlobalInit.cc'; fi`
     1547@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Po
     1548@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/FixGlobalInit.cc' object='InitTweak/driver_cfa_cpp-FixGlobalInit.obj' libtool=no @AMDEPBACKSLASH@
     1549@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1550@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.obj `if test -f 'InitTweak/FixGlobalInit.cc'; then $(CYGPATH_W) 'InitTweak/FixGlobalInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixGlobalInit.cc'; fi`
     1551
     1552InitTweak/driver_cfa_cpp-InitTweak.o: InitTweak/InitTweak.cc
     1553@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-InitTweak.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo -c -o InitTweak/driver_cfa_cpp-InitTweak.o `test -f 'InitTweak/InitTweak.cc' || echo '$(srcdir)/'`InitTweak/InitTweak.cc
     1554@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Po
     1555@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/InitTweak.cc' object='InitTweak/driver_cfa_cpp-InitTweak.o' libtool=no @AMDEPBACKSLASH@
     1556@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1557@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-InitTweak.o `test -f 'InitTweak/InitTweak.cc' || echo '$(srcdir)/'`InitTweak/InitTweak.cc
     1558
     1559InitTweak/driver_cfa_cpp-InitTweak.obj: InitTweak/InitTweak.cc
     1560@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-InitTweak.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo -c -o InitTweak/driver_cfa_cpp-InitTweak.obj `if test -f 'InitTweak/InitTweak.cc'; then $(CYGPATH_W) 'InitTweak/InitTweak.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/InitTweak.cc'; fi`
     1561@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Po
     1562@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='InitTweak/InitTweak.cc' object='InitTweak/driver_cfa_cpp-InitTweak.obj' libtool=no @AMDEPBACKSLASH@
     1563@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1564@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-InitTweak.obj `if test -f 'InitTweak/InitTweak.cc'; then $(CYGPATH_W) 'InitTweak/InitTweak.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/InitTweak.cc'; fi`
     1565
     1566Parser/driver_cfa_cpp-parser.o: Parser/parser.cc
     1567@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-parser.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-parser.Tpo -c -o Parser/driver_cfa_cpp-parser.o `test -f 'Parser/parser.cc' || echo '$(srcdir)/'`Parser/parser.cc
     1568@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-parser.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-parser.Po
     1569@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/parser.cc' object='Parser/driver_cfa_cpp-parser.o' libtool=no @AMDEPBACKSLASH@
     1570@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1571@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-parser.o `test -f 'Parser/parser.cc' || echo '$(srcdir)/'`Parser/parser.cc
     1572
     1573Parser/driver_cfa_cpp-parser.obj: Parser/parser.cc
     1574@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-parser.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-parser.Tpo -c -o Parser/driver_cfa_cpp-parser.obj `if test -f 'Parser/parser.cc'; then $(CYGPATH_W) 'Parser/parser.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/parser.cc'; fi`
     1575@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-parser.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-parser.Po
     1576@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/parser.cc' object='Parser/driver_cfa_cpp-parser.obj' libtool=no @AMDEPBACKSLASH@
     1577@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1578@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-parser.obj `if test -f 'Parser/parser.cc'; then $(CYGPATH_W) 'Parser/parser.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/parser.cc'; fi`
     1579
     1580Parser/driver_cfa_cpp-lex.o: Parser/lex.cc
     1581@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-lex.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-lex.Tpo -c -o Parser/driver_cfa_cpp-lex.o `test -f 'Parser/lex.cc' || echo '$(srcdir)/'`Parser/lex.cc
     1582@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-lex.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-lex.Po
     1583@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/lex.cc' object='Parser/driver_cfa_cpp-lex.o' libtool=no @AMDEPBACKSLASH@
     1584@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1585@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-lex.o `test -f 'Parser/lex.cc' || echo '$(srcdir)/'`Parser/lex.cc
     1586
     1587Parser/driver_cfa_cpp-lex.obj: Parser/lex.cc
     1588@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-lex.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-lex.Tpo -c -o Parser/driver_cfa_cpp-lex.obj `if test -f 'Parser/lex.cc'; then $(CYGPATH_W) 'Parser/lex.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/lex.cc'; fi`
     1589@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-lex.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-lex.Po
     1590@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/lex.cc' object='Parser/driver_cfa_cpp-lex.obj' libtool=no @AMDEPBACKSLASH@
     1591@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1592@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-lex.obj `if test -f 'Parser/lex.cc'; then $(CYGPATH_W) 'Parser/lex.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/lex.cc'; fi`
     1593
     1594Parser/driver_cfa_cpp-TypedefTable.o: Parser/TypedefTable.cc
     1595@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-TypedefTable.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-TypedefTable.Tpo -c -o Parser/driver_cfa_cpp-TypedefTable.o `test -f 'Parser/TypedefTable.cc' || echo '$(srcdir)/'`Parser/TypedefTable.cc
     1596@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-TypedefTable.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-TypedefTable.Po
     1597@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/TypedefTable.cc' object='Parser/driver_cfa_cpp-TypedefTable.o' libtool=no @AMDEPBACKSLASH@
     1598@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1599@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-TypedefTable.o `test -f 'Parser/TypedefTable.cc' || echo '$(srcdir)/'`Parser/TypedefTable.cc
     1600
     1601Parser/driver_cfa_cpp-TypedefTable.obj: Parser/TypedefTable.cc
     1602@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-TypedefTable.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-TypedefTable.Tpo -c -o Parser/driver_cfa_cpp-TypedefTable.obj `if test -f 'Parser/TypedefTable.cc'; then $(CYGPATH_W) 'Parser/TypedefTable.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/TypedefTable.cc'; fi`
     1603@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-TypedefTable.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-TypedefTable.Po
     1604@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/TypedefTable.cc' object='Parser/driver_cfa_cpp-TypedefTable.obj' libtool=no @AMDEPBACKSLASH@
     1605@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1606@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-TypedefTable.obj `if test -f 'Parser/TypedefTable.cc'; then $(CYGPATH_W) 'Parser/TypedefTable.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/TypedefTable.cc'; fi`
     1607
     1608Parser/driver_cfa_cpp-ParseNode.o: Parser/ParseNode.cc
     1609@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-ParseNode.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Tpo -c -o Parser/driver_cfa_cpp-ParseNode.o `test -f 'Parser/ParseNode.cc' || echo '$(srcdir)/'`Parser/ParseNode.cc
     1610@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Po
     1611@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/ParseNode.cc' object='Parser/driver_cfa_cpp-ParseNode.o' libtool=no @AMDEPBACKSLASH@
     1612@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1613@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-ParseNode.o `test -f 'Parser/ParseNode.cc' || echo '$(srcdir)/'`Parser/ParseNode.cc
     1614
     1615Parser/driver_cfa_cpp-ParseNode.obj: Parser/ParseNode.cc
     1616@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-ParseNode.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Tpo -c -o Parser/driver_cfa_cpp-ParseNode.obj `if test -f 'Parser/ParseNode.cc'; then $(CYGPATH_W) 'Parser/ParseNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/ParseNode.cc'; fi`
     1617@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Po
     1618@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/ParseNode.cc' object='Parser/driver_cfa_cpp-ParseNode.obj' libtool=no @AMDEPBACKSLASH@
     1619@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1620@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-ParseNode.obj `if test -f 'Parser/ParseNode.cc'; then $(CYGPATH_W) 'Parser/ParseNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/ParseNode.cc'; fi`
     1621
     1622Parser/driver_cfa_cpp-DeclarationNode.o: Parser/DeclarationNode.cc
     1623@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-DeclarationNode.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Tpo -c -o Parser/driver_cfa_cpp-DeclarationNode.o `test -f 'Parser/DeclarationNode.cc' || echo '$(srcdir)/'`Parser/DeclarationNode.cc
     1624@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Po
     1625@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/DeclarationNode.cc' object='Parser/driver_cfa_cpp-DeclarationNode.o' libtool=no @AMDEPBACKSLASH@
     1626@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1627@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-DeclarationNode.o `test -f 'Parser/DeclarationNode.cc' || echo '$(srcdir)/'`Parser/DeclarationNode.cc
     1628
     1629Parser/driver_cfa_cpp-DeclarationNode.obj: Parser/DeclarationNode.cc
     1630@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-DeclarationNode.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Tpo -c -o Parser/driver_cfa_cpp-DeclarationNode.obj `if test -f 'Parser/DeclarationNode.cc'; then $(CYGPATH_W) 'Parser/DeclarationNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/DeclarationNode.cc'; fi`
     1631@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Po
     1632@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/DeclarationNode.cc' object='Parser/driver_cfa_cpp-DeclarationNode.obj' libtool=no @AMDEPBACKSLASH@
     1633@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1634@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-DeclarationNode.obj `if test -f 'Parser/DeclarationNode.cc'; then $(CYGPATH_W) 'Parser/DeclarationNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/DeclarationNode.cc'; fi`
     1635
     1636Parser/driver_cfa_cpp-ExpressionNode.o: Parser/ExpressionNode.cc
     1637@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-ExpressionNode.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Tpo -c -o Parser/driver_cfa_cpp-ExpressionNode.o `test -f 'Parser/ExpressionNode.cc' || echo '$(srcdir)/'`Parser/ExpressionNode.cc
     1638@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Po
     1639@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/ExpressionNode.cc' object='Parser/driver_cfa_cpp-ExpressionNode.o' libtool=no @AMDEPBACKSLASH@
     1640@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1641@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-ExpressionNode.o `test -f 'Parser/ExpressionNode.cc' || echo '$(srcdir)/'`Parser/ExpressionNode.cc
     1642
     1643Parser/driver_cfa_cpp-ExpressionNode.obj: Parser/ExpressionNode.cc
     1644@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-ExpressionNode.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Tpo -c -o Parser/driver_cfa_cpp-ExpressionNode.obj `if test -f 'Parser/ExpressionNode.cc'; then $(CYGPATH_W) 'Parser/ExpressionNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/ExpressionNode.cc'; fi`
     1645@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Po
     1646@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/ExpressionNode.cc' object='Parser/driver_cfa_cpp-ExpressionNode.obj' libtool=no @AMDEPBACKSLASH@
     1647@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1648@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-ExpressionNode.obj `if test -f 'Parser/ExpressionNode.cc'; then $(CYGPATH_W) 'Parser/ExpressionNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/ExpressionNode.cc'; fi`
     1649
     1650Parser/driver_cfa_cpp-StatementNode.o: Parser/StatementNode.cc
     1651@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-StatementNode.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Tpo -c -o Parser/driver_cfa_cpp-StatementNode.o `test -f 'Parser/StatementNode.cc' || echo '$(srcdir)/'`Parser/StatementNode.cc
     1652@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Po
     1653@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/StatementNode.cc' object='Parser/driver_cfa_cpp-StatementNode.o' libtool=no @AMDEPBACKSLASH@
     1654@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1655@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-StatementNode.o `test -f 'Parser/StatementNode.cc' || echo '$(srcdir)/'`Parser/StatementNode.cc
     1656
     1657Parser/driver_cfa_cpp-StatementNode.obj: Parser/StatementNode.cc
     1658@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-StatementNode.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Tpo -c -o Parser/driver_cfa_cpp-StatementNode.obj `if test -f 'Parser/StatementNode.cc'; then $(CYGPATH_W) 'Parser/StatementNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/StatementNode.cc'; fi`
     1659@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Po
     1660@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/StatementNode.cc' object='Parser/driver_cfa_cpp-StatementNode.obj' libtool=no @AMDEPBACKSLASH@
     1661@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1662@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-StatementNode.obj `if test -f 'Parser/StatementNode.cc'; then $(CYGPATH_W) 'Parser/StatementNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/StatementNode.cc'; fi`
     1663
     1664Parser/driver_cfa_cpp-InitializerNode.o: Parser/InitializerNode.cc
     1665@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-InitializerNode.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-InitializerNode.Tpo -c -o Parser/driver_cfa_cpp-InitializerNode.o `test -f 'Parser/InitializerNode.cc' || echo '$(srcdir)/'`Parser/InitializerNode.cc
     1666@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-InitializerNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-InitializerNode.Po
     1667@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/InitializerNode.cc' object='Parser/driver_cfa_cpp-InitializerNode.o' libtool=no @AMDEPBACKSLASH@
     1668@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1669@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-InitializerNode.o `test -f 'Parser/InitializerNode.cc' || echo '$(srcdir)/'`Parser/InitializerNode.cc
     1670
     1671Parser/driver_cfa_cpp-InitializerNode.obj: Parser/InitializerNode.cc
     1672@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-InitializerNode.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-InitializerNode.Tpo -c -o Parser/driver_cfa_cpp-InitializerNode.obj `if test -f 'Parser/InitializerNode.cc'; then $(CYGPATH_W) 'Parser/InitializerNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/InitializerNode.cc'; fi`
     1673@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-InitializerNode.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-InitializerNode.Po
     1674@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/InitializerNode.cc' object='Parser/driver_cfa_cpp-InitializerNode.obj' libtool=no @AMDEPBACKSLASH@
     1675@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1676@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-InitializerNode.obj `if test -f 'Parser/InitializerNode.cc'; then $(CYGPATH_W) 'Parser/InitializerNode.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/InitializerNode.cc'; fi`
     1677
     1678Parser/driver_cfa_cpp-TypeData.o: Parser/TypeData.cc
     1679@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-TypeData.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Tpo -c -o Parser/driver_cfa_cpp-TypeData.o `test -f 'Parser/TypeData.cc' || echo '$(srcdir)/'`Parser/TypeData.cc
     1680@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Po
     1681@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/TypeData.cc' object='Parser/driver_cfa_cpp-TypeData.o' libtool=no @AMDEPBACKSLASH@
     1682@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1683@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-TypeData.o `test -f 'Parser/TypeData.cc' || echo '$(srcdir)/'`Parser/TypeData.cc
     1684
     1685Parser/driver_cfa_cpp-TypeData.obj: Parser/TypeData.cc
     1686@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-TypeData.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Tpo -c -o Parser/driver_cfa_cpp-TypeData.obj `if test -f 'Parser/TypeData.cc'; then $(CYGPATH_W) 'Parser/TypeData.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/TypeData.cc'; fi`
     1687@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Po
     1688@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/TypeData.cc' object='Parser/driver_cfa_cpp-TypeData.obj' libtool=no @AMDEPBACKSLASH@
     1689@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1690@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-TypeData.obj `if test -f 'Parser/TypeData.cc'; then $(CYGPATH_W) 'Parser/TypeData.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/TypeData.cc'; fi`
     1691
     1692Parser/driver_cfa_cpp-LinkageSpec.o: Parser/LinkageSpec.cc
     1693@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-LinkageSpec.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Tpo -c -o Parser/driver_cfa_cpp-LinkageSpec.o `test -f 'Parser/LinkageSpec.cc' || echo '$(srcdir)/'`Parser/LinkageSpec.cc
     1694@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Po
     1695@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/LinkageSpec.cc' object='Parser/driver_cfa_cpp-LinkageSpec.o' libtool=no @AMDEPBACKSLASH@
     1696@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1697@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-LinkageSpec.o `test -f 'Parser/LinkageSpec.cc' || echo '$(srcdir)/'`Parser/LinkageSpec.cc
     1698
     1699Parser/driver_cfa_cpp-LinkageSpec.obj: Parser/LinkageSpec.cc
     1700@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-LinkageSpec.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Tpo -c -o Parser/driver_cfa_cpp-LinkageSpec.obj `if test -f 'Parser/LinkageSpec.cc'; then $(CYGPATH_W) 'Parser/LinkageSpec.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/LinkageSpec.cc'; fi`
     1701@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Po
     1702@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/LinkageSpec.cc' object='Parser/driver_cfa_cpp-LinkageSpec.obj' libtool=no @AMDEPBACKSLASH@
     1703@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1704@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-LinkageSpec.obj `if test -f 'Parser/LinkageSpec.cc'; then $(CYGPATH_W) 'Parser/LinkageSpec.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/LinkageSpec.cc'; fi`
     1705
     1706Parser/driver_cfa_cpp-parserutility.o: Parser/parserutility.cc
     1707@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-parserutility.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-parserutility.Tpo -c -o Parser/driver_cfa_cpp-parserutility.o `test -f 'Parser/parserutility.cc' || echo '$(srcdir)/'`Parser/parserutility.cc
     1708@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-parserutility.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-parserutility.Po
     1709@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/parserutility.cc' object='Parser/driver_cfa_cpp-parserutility.o' libtool=no @AMDEPBACKSLASH@
     1710@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1711@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-parserutility.o `test -f 'Parser/parserutility.cc' || echo '$(srcdir)/'`Parser/parserutility.cc
     1712
     1713Parser/driver_cfa_cpp-parserutility.obj: Parser/parserutility.cc
     1714@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-parserutility.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-parserutility.Tpo -c -o Parser/driver_cfa_cpp-parserutility.obj `if test -f 'Parser/parserutility.cc'; then $(CYGPATH_W) 'Parser/parserutility.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/parserutility.cc'; fi`
     1715@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-parserutility.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-parserutility.Po
     1716@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Parser/parserutility.cc' object='Parser/driver_cfa_cpp-parserutility.obj' libtool=no @AMDEPBACKSLASH@
     1717@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1718@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-parserutility.obj `if test -f 'Parser/parserutility.cc'; then $(CYGPATH_W) 'Parser/parserutility.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/parserutility.cc'; fi`
     1719
     1720ResolvExpr/driver_cfa_cpp-AlternativeFinder.o: ResolvExpr/AlternativeFinder.cc
     1721@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-AlternativeFinder.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativeFinder.Tpo -c -o ResolvExpr/driver_cfa_cpp-AlternativeFinder.o `test -f 'ResolvExpr/AlternativeFinder.cc' || echo '$(srcdir)/'`ResolvExpr/AlternativeFinder.cc
     1722@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativeFinder.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativeFinder.Po
     1723@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/AlternativeFinder.cc' object='ResolvExpr/driver_cfa_cpp-AlternativeFinder.o' libtool=no @AMDEPBACKSLASH@
     1724@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1725@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-AlternativeFinder.o `test -f 'ResolvExpr/AlternativeFinder.cc' || echo '$(srcdir)/'`ResolvExpr/AlternativeFinder.cc
     1726
     1727ResolvExpr/driver_cfa_cpp-AlternativeFinder.obj: ResolvExpr/AlternativeFinder.cc
     1728@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-AlternativeFinder.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativeFinder.Tpo -c -o ResolvExpr/driver_cfa_cpp-AlternativeFinder.obj `if test -f 'ResolvExpr/AlternativeFinder.cc'; then $(CYGPATH_W) 'ResolvExpr/AlternativeFinder.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/AlternativeFinder.cc'; fi`
     1729@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativeFinder.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativeFinder.Po
     1730@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/AlternativeFinder.cc' object='ResolvExpr/driver_cfa_cpp-AlternativeFinder.obj' libtool=no @AMDEPBACKSLASH@
     1731@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1732@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-AlternativeFinder.obj `if test -f 'ResolvExpr/AlternativeFinder.cc'; then $(CYGPATH_W) 'ResolvExpr/AlternativeFinder.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/AlternativeFinder.cc'; fi`
     1733
     1734ResolvExpr/driver_cfa_cpp-Alternative.o: ResolvExpr/Alternative.cc
     1735@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Alternative.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Alternative.Tpo -c -o ResolvExpr/driver_cfa_cpp-Alternative.o `test -f 'ResolvExpr/Alternative.cc' || echo '$(srcdir)/'`ResolvExpr/Alternative.cc
     1736@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Alternative.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Alternative.Po
     1737@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Alternative.cc' object='ResolvExpr/driver_cfa_cpp-Alternative.o' libtool=no @AMDEPBACKSLASH@
     1738@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1739@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Alternative.o `test -f 'ResolvExpr/Alternative.cc' || echo '$(srcdir)/'`ResolvExpr/Alternative.cc
     1740
     1741ResolvExpr/driver_cfa_cpp-Alternative.obj: ResolvExpr/Alternative.cc
     1742@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Alternative.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Alternative.Tpo -c -o ResolvExpr/driver_cfa_cpp-Alternative.obj `if test -f 'ResolvExpr/Alternative.cc'; then $(CYGPATH_W) 'ResolvExpr/Alternative.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Alternative.cc'; fi`
     1743@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Alternative.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Alternative.Po
     1744@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Alternative.cc' object='ResolvExpr/driver_cfa_cpp-Alternative.obj' libtool=no @AMDEPBACKSLASH@
     1745@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1746@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Alternative.obj `if test -f 'ResolvExpr/Alternative.cc'; then $(CYGPATH_W) 'ResolvExpr/Alternative.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Alternative.cc'; fi`
     1747
     1748ResolvExpr/driver_cfa_cpp-Unify.o: ResolvExpr/Unify.cc
     1749@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Unify.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Tpo -c -o ResolvExpr/driver_cfa_cpp-Unify.o `test -f 'ResolvExpr/Unify.cc' || echo '$(srcdir)/'`ResolvExpr/Unify.cc
     1750@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Po
     1751@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Unify.cc' object='ResolvExpr/driver_cfa_cpp-Unify.o' libtool=no @AMDEPBACKSLASH@
     1752@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1753@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Unify.o `test -f 'ResolvExpr/Unify.cc' || echo '$(srcdir)/'`ResolvExpr/Unify.cc
     1754
     1755ResolvExpr/driver_cfa_cpp-Unify.obj: ResolvExpr/Unify.cc
     1756@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Unify.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Tpo -c -o ResolvExpr/driver_cfa_cpp-Unify.obj `if test -f 'ResolvExpr/Unify.cc'; then $(CYGPATH_W) 'ResolvExpr/Unify.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Unify.cc'; fi`
     1757@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Po
     1758@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Unify.cc' object='ResolvExpr/driver_cfa_cpp-Unify.obj' libtool=no @AMDEPBACKSLASH@
     1759@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1760@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Unify.obj `if test -f 'ResolvExpr/Unify.cc'; then $(CYGPATH_W) 'ResolvExpr/Unify.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Unify.cc'; fi`
     1761
     1762ResolvExpr/driver_cfa_cpp-PtrsAssignable.o: ResolvExpr/PtrsAssignable.cc
     1763@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-PtrsAssignable.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsAssignable.Tpo -c -o ResolvExpr/driver_cfa_cpp-PtrsAssignable.o `test -f 'ResolvExpr/PtrsAssignable.cc' || echo '$(srcdir)/'`ResolvExpr/PtrsAssignable.cc
     1764@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsAssignable.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsAssignable.Po
     1765@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/PtrsAssignable.cc' object='ResolvExpr/driver_cfa_cpp-PtrsAssignable.o' libtool=no @AMDEPBACKSLASH@
     1766@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1767@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-PtrsAssignable.o `test -f 'ResolvExpr/PtrsAssignable.cc' || echo '$(srcdir)/'`ResolvExpr/PtrsAssignable.cc
     1768
     1769ResolvExpr/driver_cfa_cpp-PtrsAssignable.obj: ResolvExpr/PtrsAssignable.cc
     1770@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-PtrsAssignable.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsAssignable.Tpo -c -o ResolvExpr/driver_cfa_cpp-PtrsAssignable.obj `if test -f 'ResolvExpr/PtrsAssignable.cc'; then $(CYGPATH_W) 'ResolvExpr/PtrsAssignable.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/PtrsAssignable.cc'; fi`
     1771@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsAssignable.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsAssignable.Po
     1772@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/PtrsAssignable.cc' object='ResolvExpr/driver_cfa_cpp-PtrsAssignable.obj' libtool=no @AMDEPBACKSLASH@
     1773@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1774@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-PtrsAssignable.obj `if test -f 'ResolvExpr/PtrsAssignable.cc'; then $(CYGPATH_W) 'ResolvExpr/PtrsAssignable.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/PtrsAssignable.cc'; fi`
     1775
     1776ResolvExpr/driver_cfa_cpp-CommonType.o: ResolvExpr/CommonType.cc
     1777@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CommonType.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Tpo -c -o ResolvExpr/driver_cfa_cpp-CommonType.o `test -f 'ResolvExpr/CommonType.cc' || echo '$(srcdir)/'`ResolvExpr/CommonType.cc
     1778@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Po
     1779@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CommonType.cc' object='ResolvExpr/driver_cfa_cpp-CommonType.o' libtool=no @AMDEPBACKSLASH@
     1780@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1781@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CommonType.o `test -f 'ResolvExpr/CommonType.cc' || echo '$(srcdir)/'`ResolvExpr/CommonType.cc
     1782
     1783ResolvExpr/driver_cfa_cpp-CommonType.obj: ResolvExpr/CommonType.cc
     1784@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CommonType.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Tpo -c -o ResolvExpr/driver_cfa_cpp-CommonType.obj `if test -f 'ResolvExpr/CommonType.cc'; then $(CYGPATH_W) 'ResolvExpr/CommonType.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CommonType.cc'; fi`
     1785@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CommonType.Po
     1786@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CommonType.cc' object='ResolvExpr/driver_cfa_cpp-CommonType.obj' libtool=no @AMDEPBACKSLASH@
     1787@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1788@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CommonType.obj `if test -f 'ResolvExpr/CommonType.cc'; then $(CYGPATH_W) 'ResolvExpr/CommonType.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CommonType.cc'; fi`
     1789
     1790ResolvExpr/driver_cfa_cpp-ConversionCost.o: ResolvExpr/ConversionCost.cc
     1791@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ConversionCost.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Tpo -c -o ResolvExpr/driver_cfa_cpp-ConversionCost.o `test -f 'ResolvExpr/ConversionCost.cc' || echo '$(srcdir)/'`ResolvExpr/ConversionCost.cc
     1792@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Po
     1793@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/ConversionCost.cc' object='ResolvExpr/driver_cfa_cpp-ConversionCost.o' libtool=no @AMDEPBACKSLASH@
     1794@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1795@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ConversionCost.o `test -f 'ResolvExpr/ConversionCost.cc' || echo '$(srcdir)/'`ResolvExpr/ConversionCost.cc
     1796
     1797ResolvExpr/driver_cfa_cpp-ConversionCost.obj: ResolvExpr/ConversionCost.cc
     1798@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ConversionCost.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Tpo -c -o ResolvExpr/driver_cfa_cpp-ConversionCost.obj `if test -f 'ResolvExpr/ConversionCost.cc'; then $(CYGPATH_W) 'ResolvExpr/ConversionCost.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ConversionCost.cc'; fi`
     1799@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Po
     1800@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/ConversionCost.cc' object='ResolvExpr/driver_cfa_cpp-ConversionCost.obj' libtool=no @AMDEPBACKSLASH@
     1801@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1802@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ConversionCost.obj `if test -f 'ResolvExpr/ConversionCost.cc'; then $(CYGPATH_W) 'ResolvExpr/ConversionCost.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ConversionCost.cc'; fi`
     1803
     1804ResolvExpr/driver_cfa_cpp-CastCost.o: ResolvExpr/CastCost.cc
     1805@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CastCost.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CastCost.Tpo -c -o ResolvExpr/driver_cfa_cpp-CastCost.o `test -f 'ResolvExpr/CastCost.cc' || echo '$(srcdir)/'`ResolvExpr/CastCost.cc
     1806@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CastCost.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CastCost.Po
     1807@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CastCost.cc' object='ResolvExpr/driver_cfa_cpp-CastCost.o' libtool=no @AMDEPBACKSLASH@
     1808@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1809@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CastCost.o `test -f 'ResolvExpr/CastCost.cc' || echo '$(srcdir)/'`ResolvExpr/CastCost.cc
     1810
     1811ResolvExpr/driver_cfa_cpp-CastCost.obj: ResolvExpr/CastCost.cc
     1812@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CastCost.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CastCost.Tpo -c -o ResolvExpr/driver_cfa_cpp-CastCost.obj `if test -f 'ResolvExpr/CastCost.cc'; then $(CYGPATH_W) 'ResolvExpr/CastCost.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CastCost.cc'; fi`
     1813@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CastCost.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CastCost.Po
     1814@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CastCost.cc' object='ResolvExpr/driver_cfa_cpp-CastCost.obj' libtool=no @AMDEPBACKSLASH@
     1815@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1816@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CastCost.obj `if test -f 'ResolvExpr/CastCost.cc'; then $(CYGPATH_W) 'ResolvExpr/CastCost.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CastCost.cc'; fi`
     1817
     1818ResolvExpr/driver_cfa_cpp-PtrsCastable.o: ResolvExpr/PtrsCastable.cc
     1819@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-PtrsCastable.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsCastable.Tpo -c -o ResolvExpr/driver_cfa_cpp-PtrsCastable.o `test -f 'ResolvExpr/PtrsCastable.cc' || echo '$(srcdir)/'`ResolvExpr/PtrsCastable.cc
     1820@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsCastable.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsCastable.Po
     1821@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/PtrsCastable.cc' object='ResolvExpr/driver_cfa_cpp-PtrsCastable.o' libtool=no @AMDEPBACKSLASH@
     1822@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1823@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-PtrsCastable.o `test -f 'ResolvExpr/PtrsCastable.cc' || echo '$(srcdir)/'`ResolvExpr/PtrsCastable.cc
     1824
     1825ResolvExpr/driver_cfa_cpp-PtrsCastable.obj: ResolvExpr/PtrsCastable.cc
     1826@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-PtrsCastable.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsCastable.Tpo -c -o ResolvExpr/driver_cfa_cpp-PtrsCastable.obj `if test -f 'ResolvExpr/PtrsCastable.cc'; then $(CYGPATH_W) 'ResolvExpr/PtrsCastable.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/PtrsCastable.cc'; fi`
     1827@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsCastable.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PtrsCastable.Po
     1828@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/PtrsCastable.cc' object='ResolvExpr/driver_cfa_cpp-PtrsCastable.obj' libtool=no @AMDEPBACKSLASH@
     1829@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1830@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-PtrsCastable.obj `if test -f 'ResolvExpr/PtrsCastable.cc'; then $(CYGPATH_W) 'ResolvExpr/PtrsCastable.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/PtrsCastable.cc'; fi`
     1831
     1832ResolvExpr/driver_cfa_cpp-AdjustExprType.o: ResolvExpr/AdjustExprType.cc
     1833@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-AdjustExprType.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AdjustExprType.Tpo -c -o ResolvExpr/driver_cfa_cpp-AdjustExprType.o `test -f 'ResolvExpr/AdjustExprType.cc' || echo '$(srcdir)/'`ResolvExpr/AdjustExprType.cc
     1834@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AdjustExprType.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AdjustExprType.Po
     1835@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/AdjustExprType.cc' object='ResolvExpr/driver_cfa_cpp-AdjustExprType.o' libtool=no @AMDEPBACKSLASH@
     1836@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1837@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-AdjustExprType.o `test -f 'ResolvExpr/AdjustExprType.cc' || echo '$(srcdir)/'`ResolvExpr/AdjustExprType.cc
     1838
     1839ResolvExpr/driver_cfa_cpp-AdjustExprType.obj: ResolvExpr/AdjustExprType.cc
     1840@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-AdjustExprType.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AdjustExprType.Tpo -c -o ResolvExpr/driver_cfa_cpp-AdjustExprType.obj `if test -f 'ResolvExpr/AdjustExprType.cc'; then $(CYGPATH_W) 'ResolvExpr/AdjustExprType.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/AdjustExprType.cc'; fi`
     1841@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AdjustExprType.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AdjustExprType.Po
     1842@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/AdjustExprType.cc' object='ResolvExpr/driver_cfa_cpp-AdjustExprType.obj' libtool=no @AMDEPBACKSLASH@
     1843@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1844@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-AdjustExprType.obj `if test -f 'ResolvExpr/AdjustExprType.cc'; then $(CYGPATH_W) 'ResolvExpr/AdjustExprType.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/AdjustExprType.cc'; fi`
     1845
     1846ResolvExpr/driver_cfa_cpp-AlternativePrinter.o: ResolvExpr/AlternativePrinter.cc
     1847@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-AlternativePrinter.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativePrinter.Tpo -c -o ResolvExpr/driver_cfa_cpp-AlternativePrinter.o `test -f 'ResolvExpr/AlternativePrinter.cc' || echo '$(srcdir)/'`ResolvExpr/AlternativePrinter.cc
     1848@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativePrinter.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativePrinter.Po
     1849@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/AlternativePrinter.cc' object='ResolvExpr/driver_cfa_cpp-AlternativePrinter.o' libtool=no @AMDEPBACKSLASH@
     1850@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1851@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-AlternativePrinter.o `test -f 'ResolvExpr/AlternativePrinter.cc' || echo '$(srcdir)/'`ResolvExpr/AlternativePrinter.cc
     1852
     1853ResolvExpr/driver_cfa_cpp-AlternativePrinter.obj: ResolvExpr/AlternativePrinter.cc
     1854@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-AlternativePrinter.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativePrinter.Tpo -c -o ResolvExpr/driver_cfa_cpp-AlternativePrinter.obj `if test -f 'ResolvExpr/AlternativePrinter.cc'; then $(CYGPATH_W) 'ResolvExpr/AlternativePrinter.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/AlternativePrinter.cc'; fi`
     1855@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativePrinter.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-AlternativePrinter.Po
     1856@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/AlternativePrinter.cc' object='ResolvExpr/driver_cfa_cpp-AlternativePrinter.obj' libtool=no @AMDEPBACKSLASH@
     1857@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1858@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-AlternativePrinter.obj `if test -f 'ResolvExpr/AlternativePrinter.cc'; then $(CYGPATH_W) 'ResolvExpr/AlternativePrinter.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/AlternativePrinter.cc'; fi`
     1859
     1860ResolvExpr/driver_cfa_cpp-Resolver.o: ResolvExpr/Resolver.cc
     1861@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Resolver.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Resolver.Tpo -c -o ResolvExpr/driver_cfa_cpp-Resolver.o `test -f 'ResolvExpr/Resolver.cc' || echo '$(srcdir)/'`ResolvExpr/Resolver.cc
     1862@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Resolver.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Resolver.Po
     1863@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Resolver.cc' object='ResolvExpr/driver_cfa_cpp-Resolver.o' libtool=no @AMDEPBACKSLASH@
     1864@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1865@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Resolver.o `test -f 'ResolvExpr/Resolver.cc' || echo '$(srcdir)/'`ResolvExpr/Resolver.cc
     1866
     1867ResolvExpr/driver_cfa_cpp-Resolver.obj: ResolvExpr/Resolver.cc
     1868@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Resolver.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Resolver.Tpo -c -o ResolvExpr/driver_cfa_cpp-Resolver.obj `if test -f 'ResolvExpr/Resolver.cc'; then $(CYGPATH_W) 'ResolvExpr/Resolver.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Resolver.cc'; fi`
     1869@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Resolver.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Resolver.Po
     1870@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Resolver.cc' object='ResolvExpr/driver_cfa_cpp-Resolver.obj' libtool=no @AMDEPBACKSLASH@
     1871@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1872@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Resolver.obj `if test -f 'ResolvExpr/Resolver.cc'; then $(CYGPATH_W) 'ResolvExpr/Resolver.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Resolver.cc'; fi`
     1873
     1874ResolvExpr/driver_cfa_cpp-ResolveTypeof.o: ResolvExpr/ResolveTypeof.cc
     1875@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ResolveTypeof.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ResolveTypeof.Tpo -c -o ResolvExpr/driver_cfa_cpp-ResolveTypeof.o `test -f 'ResolvExpr/ResolveTypeof.cc' || echo '$(srcdir)/'`ResolvExpr/ResolveTypeof.cc
     1876@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ResolveTypeof.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ResolveTypeof.Po
     1877@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/ResolveTypeof.cc' object='ResolvExpr/driver_cfa_cpp-ResolveTypeof.o' libtool=no @AMDEPBACKSLASH@
     1878@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1879@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ResolveTypeof.o `test -f 'ResolvExpr/ResolveTypeof.cc' || echo '$(srcdir)/'`ResolvExpr/ResolveTypeof.cc
     1880
     1881ResolvExpr/driver_cfa_cpp-ResolveTypeof.obj: ResolvExpr/ResolveTypeof.cc
     1882@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ResolveTypeof.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ResolveTypeof.Tpo -c -o ResolvExpr/driver_cfa_cpp-ResolveTypeof.obj `if test -f 'ResolvExpr/ResolveTypeof.cc'; then $(CYGPATH_W) 'ResolvExpr/ResolveTypeof.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ResolveTypeof.cc'; fi`
     1883@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ResolveTypeof.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ResolveTypeof.Po
     1884@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/ResolveTypeof.cc' object='ResolvExpr/driver_cfa_cpp-ResolveTypeof.obj' libtool=no @AMDEPBACKSLASH@
     1885@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1886@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ResolveTypeof.obj `if test -f 'ResolvExpr/ResolveTypeof.cc'; then $(CYGPATH_W) 'ResolvExpr/ResolveTypeof.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ResolveTypeof.cc'; fi`
     1887
     1888ResolvExpr/driver_cfa_cpp-RenameVars.o: ResolvExpr/RenameVars.cc
     1889@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-RenameVars.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-RenameVars.Tpo -c -o ResolvExpr/driver_cfa_cpp-RenameVars.o `test -f 'ResolvExpr/RenameVars.cc' || echo '$(srcdir)/'`ResolvExpr/RenameVars.cc
     1890@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-RenameVars.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-RenameVars.Po
     1891@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/RenameVars.cc' object='ResolvExpr/driver_cfa_cpp-RenameVars.o' libtool=no @AMDEPBACKSLASH@
     1892@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1893@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-RenameVars.o `test -f 'ResolvExpr/RenameVars.cc' || echo '$(srcdir)/'`ResolvExpr/RenameVars.cc
     1894
     1895ResolvExpr/driver_cfa_cpp-RenameVars.obj: ResolvExpr/RenameVars.cc
     1896@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-RenameVars.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-RenameVars.Tpo -c -o ResolvExpr/driver_cfa_cpp-RenameVars.obj `if test -f 'ResolvExpr/RenameVars.cc'; then $(CYGPATH_W) 'ResolvExpr/RenameVars.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/RenameVars.cc'; fi`
     1897@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-RenameVars.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-RenameVars.Po
     1898@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/RenameVars.cc' object='ResolvExpr/driver_cfa_cpp-RenameVars.obj' libtool=no @AMDEPBACKSLASH@
     1899@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1900@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-RenameVars.obj `if test -f 'ResolvExpr/RenameVars.cc'; then $(CYGPATH_W) 'ResolvExpr/RenameVars.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/RenameVars.cc'; fi`
     1901
     1902ResolvExpr/driver_cfa_cpp-FindOpenVars.o: ResolvExpr/FindOpenVars.cc
     1903@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-FindOpenVars.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Tpo -c -o ResolvExpr/driver_cfa_cpp-FindOpenVars.o `test -f 'ResolvExpr/FindOpenVars.cc' || echo '$(srcdir)/'`ResolvExpr/FindOpenVars.cc
     1904@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Po
     1905@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/FindOpenVars.cc' object='ResolvExpr/driver_cfa_cpp-FindOpenVars.o' libtool=no @AMDEPBACKSLASH@
     1906@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1907@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-FindOpenVars.o `test -f 'ResolvExpr/FindOpenVars.cc' || echo '$(srcdir)/'`ResolvExpr/FindOpenVars.cc
     1908
     1909ResolvExpr/driver_cfa_cpp-FindOpenVars.obj: ResolvExpr/FindOpenVars.cc
     1910@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-FindOpenVars.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Tpo -c -o ResolvExpr/driver_cfa_cpp-FindOpenVars.obj `if test -f 'ResolvExpr/FindOpenVars.cc'; then $(CYGPATH_W) 'ResolvExpr/FindOpenVars.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/FindOpenVars.cc'; fi`
     1911@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Po
     1912@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/FindOpenVars.cc' object='ResolvExpr/driver_cfa_cpp-FindOpenVars.obj' libtool=no @AMDEPBACKSLASH@
     1913@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1914@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-FindOpenVars.obj `if test -f 'ResolvExpr/FindOpenVars.cc'; then $(CYGPATH_W) 'ResolvExpr/FindOpenVars.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/FindOpenVars.cc'; fi`
     1915
     1916ResolvExpr/driver_cfa_cpp-PolyCost.o: ResolvExpr/PolyCost.cc
     1917@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-PolyCost.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PolyCost.Tpo -c -o ResolvExpr/driver_cfa_cpp-PolyCost.o `test -f 'ResolvExpr/PolyCost.cc' || echo '$(srcdir)/'`ResolvExpr/PolyCost.cc
     1918@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PolyCost.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PolyCost.Po
     1919@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/PolyCost.cc' object='ResolvExpr/driver_cfa_cpp-PolyCost.o' libtool=no @AMDEPBACKSLASH@
     1920@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1921@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-PolyCost.o `test -f 'ResolvExpr/PolyCost.cc' || echo '$(srcdir)/'`ResolvExpr/PolyCost.cc
     1922
     1923ResolvExpr/driver_cfa_cpp-PolyCost.obj: ResolvExpr/PolyCost.cc
     1924@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-PolyCost.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PolyCost.Tpo -c -o ResolvExpr/driver_cfa_cpp-PolyCost.obj `if test -f 'ResolvExpr/PolyCost.cc'; then $(CYGPATH_W) 'ResolvExpr/PolyCost.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/PolyCost.cc'; fi`
     1925@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PolyCost.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-PolyCost.Po
     1926@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/PolyCost.cc' object='ResolvExpr/driver_cfa_cpp-PolyCost.obj' libtool=no @AMDEPBACKSLASH@
     1927@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1928@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-PolyCost.obj `if test -f 'ResolvExpr/PolyCost.cc'; then $(CYGPATH_W) 'ResolvExpr/PolyCost.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/PolyCost.cc'; fi`
     1929
     1930ResolvExpr/driver_cfa_cpp-Occurs.o: ResolvExpr/Occurs.cc
     1931@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Occurs.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Tpo -c -o ResolvExpr/driver_cfa_cpp-Occurs.o `test -f 'ResolvExpr/Occurs.cc' || echo '$(srcdir)/'`ResolvExpr/Occurs.cc
     1932@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Po
     1933@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Occurs.cc' object='ResolvExpr/driver_cfa_cpp-Occurs.o' libtool=no @AMDEPBACKSLASH@
     1934@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1935@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Occurs.o `test -f 'ResolvExpr/Occurs.cc' || echo '$(srcdir)/'`ResolvExpr/Occurs.cc
     1936
     1937ResolvExpr/driver_cfa_cpp-Occurs.obj: ResolvExpr/Occurs.cc
     1938@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-Occurs.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Tpo -c -o ResolvExpr/driver_cfa_cpp-Occurs.obj `if test -f 'ResolvExpr/Occurs.cc'; then $(CYGPATH_W) 'ResolvExpr/Occurs.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Occurs.cc'; fi`
     1939@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Po
     1940@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/Occurs.cc' object='ResolvExpr/driver_cfa_cpp-Occurs.obj' libtool=no @AMDEPBACKSLASH@
     1941@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1942@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-Occurs.obj `if test -f 'ResolvExpr/Occurs.cc'; then $(CYGPATH_W) 'ResolvExpr/Occurs.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/Occurs.cc'; fi`
     1943
     1944ResolvExpr/driver_cfa_cpp-TypeEnvironment.o: ResolvExpr/TypeEnvironment.cc
     1945@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-TypeEnvironment.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Tpo -c -o ResolvExpr/driver_cfa_cpp-TypeEnvironment.o `test -f 'ResolvExpr/TypeEnvironment.cc' || echo '$(srcdir)/'`ResolvExpr/TypeEnvironment.cc
     1946@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Po
     1947@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/TypeEnvironment.cc' object='ResolvExpr/driver_cfa_cpp-TypeEnvironment.o' libtool=no @AMDEPBACKSLASH@
     1948@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1949@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-TypeEnvironment.o `test -f 'ResolvExpr/TypeEnvironment.cc' || echo '$(srcdir)/'`ResolvExpr/TypeEnvironment.cc
     1950
     1951ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj: ResolvExpr/TypeEnvironment.cc
     1952@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Tpo -c -o ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj `if test -f 'ResolvExpr/TypeEnvironment.cc'; then $(CYGPATH_W) 'ResolvExpr/TypeEnvironment.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/TypeEnvironment.cc'; fi`
     1953@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Po
     1954@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/TypeEnvironment.cc' object='ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj' libtool=no @AMDEPBACKSLASH@
     1955@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1956@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj `if test -f 'ResolvExpr/TypeEnvironment.cc'; then $(CYGPATH_W) 'ResolvExpr/TypeEnvironment.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/TypeEnvironment.cc'; fi`
     1957
     1958ResolvExpr/driver_cfa_cpp-CurrentObject.o: ResolvExpr/CurrentObject.cc
     1959@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CurrentObject.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.o `test -f 'ResolvExpr/CurrentObject.cc' || echo '$(srcdir)/'`ResolvExpr/CurrentObject.cc
     1960@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po
     1961@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CurrentObject.cc' object='ResolvExpr/driver_cfa_cpp-CurrentObject.o' libtool=no @AMDEPBACKSLASH@
     1962@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1963@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.o `test -f 'ResolvExpr/CurrentObject.cc' || echo '$(srcdir)/'`ResolvExpr/CurrentObject.cc
     1964
     1965ResolvExpr/driver_cfa_cpp-CurrentObject.obj: ResolvExpr/CurrentObject.cc
     1966@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-CurrentObject.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.obj `if test -f 'ResolvExpr/CurrentObject.cc'; then $(CYGPATH_W) 'ResolvExpr/CurrentObject.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CurrentObject.cc'; fi`
     1967@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po
     1968@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/CurrentObject.cc' object='ResolvExpr/driver_cfa_cpp-CurrentObject.obj' libtool=no @AMDEPBACKSLASH@
     1969@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1970@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.obj `if test -f 'ResolvExpr/CurrentObject.cc'; then $(CYGPATH_W) 'ResolvExpr/CurrentObject.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CurrentObject.cc'; fi`
     1971
     1972ResolvExpr/driver_cfa_cpp-ExplodedActual.o: ResolvExpr/ExplodedActual.cc
     1973@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ExplodedActual.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.o `test -f 'ResolvExpr/ExplodedActual.cc' || echo '$(srcdir)/'`ResolvExpr/ExplodedActual.cc
     1974@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po
     1975@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/ExplodedActual.cc' object='ResolvExpr/driver_cfa_cpp-ExplodedActual.o' libtool=no @AMDEPBACKSLASH@
     1976@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1977@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.o `test -f 'ResolvExpr/ExplodedActual.cc' || echo '$(srcdir)/'`ResolvExpr/ExplodedActual.cc
     1978
     1979ResolvExpr/driver_cfa_cpp-ExplodedActual.obj: ResolvExpr/ExplodedActual.cc
     1980@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ExplodedActual.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.obj `if test -f 'ResolvExpr/ExplodedActual.cc'; then $(CYGPATH_W) 'ResolvExpr/ExplodedActual.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ExplodedActual.cc'; fi`
     1981@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po
     1982@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='ResolvExpr/ExplodedActual.cc' object='ResolvExpr/driver_cfa_cpp-ExplodedActual.obj' libtool=no @AMDEPBACKSLASH@
     1983@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1984@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.obj `if test -f 'ResolvExpr/ExplodedActual.cc'; then $(CYGPATH_W) 'ResolvExpr/ExplodedActual.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ExplodedActual.cc'; fi`
     1985
     1986SymTab/driver_cfa_cpp-Indexer.o: SymTab/Indexer.cc
     1987@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Indexer.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Tpo -c -o SymTab/driver_cfa_cpp-Indexer.o `test -f 'SymTab/Indexer.cc' || echo '$(srcdir)/'`SymTab/Indexer.cc
     1988@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Po
     1989@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Indexer.cc' object='SymTab/driver_cfa_cpp-Indexer.o' libtool=no @AMDEPBACKSLASH@
     1990@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1991@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Indexer.o `test -f 'SymTab/Indexer.cc' || echo '$(srcdir)/'`SymTab/Indexer.cc
     1992
     1993SymTab/driver_cfa_cpp-Indexer.obj: SymTab/Indexer.cc
     1994@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Indexer.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Tpo -c -o SymTab/driver_cfa_cpp-Indexer.obj `if test -f 'SymTab/Indexer.cc'; then $(CYGPATH_W) 'SymTab/Indexer.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Indexer.cc'; fi`
     1995@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Po
     1996@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Indexer.cc' object='SymTab/driver_cfa_cpp-Indexer.obj' libtool=no @AMDEPBACKSLASH@
     1997@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     1998@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Indexer.obj `if test -f 'SymTab/Indexer.cc'; then $(CYGPATH_W) 'SymTab/Indexer.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Indexer.cc'; fi`
     1999
     2000SymTab/driver_cfa_cpp-Mangler.o: SymTab/Mangler.cc
     2001@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Mangler.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Tpo -c -o SymTab/driver_cfa_cpp-Mangler.o `test -f 'SymTab/Mangler.cc' || echo '$(srcdir)/'`SymTab/Mangler.cc
     2002@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Po
     2003@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Mangler.cc' object='SymTab/driver_cfa_cpp-Mangler.o' libtool=no @AMDEPBACKSLASH@
     2004@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2005@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Mangler.o `test -f 'SymTab/Mangler.cc' || echo '$(srcdir)/'`SymTab/Mangler.cc
     2006
     2007SymTab/driver_cfa_cpp-Mangler.obj: SymTab/Mangler.cc
     2008@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Mangler.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Tpo -c -o SymTab/driver_cfa_cpp-Mangler.obj `if test -f 'SymTab/Mangler.cc'; then $(CYGPATH_W) 'SymTab/Mangler.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Mangler.cc'; fi`
     2009@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Po
     2010@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Mangler.cc' object='SymTab/driver_cfa_cpp-Mangler.obj' libtool=no @AMDEPBACKSLASH@
     2011@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2012@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Mangler.obj `if test -f 'SymTab/Mangler.cc'; then $(CYGPATH_W) 'SymTab/Mangler.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Mangler.cc'; fi`
     2013
     2014SymTab/driver_cfa_cpp-Validate.o: SymTab/Validate.cc
     2015@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Validate.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Tpo -c -o SymTab/driver_cfa_cpp-Validate.o `test -f 'SymTab/Validate.cc' || echo '$(srcdir)/'`SymTab/Validate.cc
     2016@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Po
     2017@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Validate.cc' object='SymTab/driver_cfa_cpp-Validate.o' libtool=no @AMDEPBACKSLASH@
     2018@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2019@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Validate.o `test -f 'SymTab/Validate.cc' || echo '$(srcdir)/'`SymTab/Validate.cc
     2020
     2021SymTab/driver_cfa_cpp-Validate.obj: SymTab/Validate.cc
     2022@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Validate.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Tpo -c -o SymTab/driver_cfa_cpp-Validate.obj `if test -f 'SymTab/Validate.cc'; then $(CYGPATH_W) 'SymTab/Validate.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Validate.cc'; fi`
     2023@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Po
     2024@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Validate.cc' object='SymTab/driver_cfa_cpp-Validate.obj' libtool=no @AMDEPBACKSLASH@
     2025@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2026@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Validate.obj `if test -f 'SymTab/Validate.cc'; then $(CYGPATH_W) 'SymTab/Validate.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Validate.cc'; fi`
     2027
     2028SymTab/driver_cfa_cpp-FixFunction.o: SymTab/FixFunction.cc
     2029@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-FixFunction.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Tpo -c -o SymTab/driver_cfa_cpp-FixFunction.o `test -f 'SymTab/FixFunction.cc' || echo '$(srcdir)/'`SymTab/FixFunction.cc
     2030@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po
     2031@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/FixFunction.cc' object='SymTab/driver_cfa_cpp-FixFunction.o' libtool=no @AMDEPBACKSLASH@
     2032@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2033@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-FixFunction.o `test -f 'SymTab/FixFunction.cc' || echo '$(srcdir)/'`SymTab/FixFunction.cc
     2034
     2035SymTab/driver_cfa_cpp-FixFunction.obj: SymTab/FixFunction.cc
     2036@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-FixFunction.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Tpo -c -o SymTab/driver_cfa_cpp-FixFunction.obj `if test -f 'SymTab/FixFunction.cc'; then $(CYGPATH_W) 'SymTab/FixFunction.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/FixFunction.cc'; fi`
     2037@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po
     2038@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/FixFunction.cc' object='SymTab/driver_cfa_cpp-FixFunction.obj' libtool=no @AMDEPBACKSLASH@
     2039@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2040@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-FixFunction.obj `if test -f 'SymTab/FixFunction.cc'; then $(CYGPATH_W) 'SymTab/FixFunction.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/FixFunction.cc'; fi`
     2041
     2042SymTab/driver_cfa_cpp-Autogen.o: SymTab/Autogen.cc
     2043@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Autogen.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo -c -o SymTab/driver_cfa_cpp-Autogen.o `test -f 'SymTab/Autogen.cc' || echo '$(srcdir)/'`SymTab/Autogen.cc
     2044@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po
     2045@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Autogen.cc' object='SymTab/driver_cfa_cpp-Autogen.o' libtool=no @AMDEPBACKSLASH@
     2046@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2047@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Autogen.o `test -f 'SymTab/Autogen.cc' || echo '$(srcdir)/'`SymTab/Autogen.cc
     2048
     2049SymTab/driver_cfa_cpp-Autogen.obj: SymTab/Autogen.cc
     2050@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Autogen.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo -c -o SymTab/driver_cfa_cpp-Autogen.obj `if test -f 'SymTab/Autogen.cc'; then $(CYGPATH_W) 'SymTab/Autogen.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Autogen.cc'; fi`
     2051@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po
     2052@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SymTab/Autogen.cc' object='SymTab/driver_cfa_cpp-Autogen.obj' libtool=no @AMDEPBACKSLASH@
     2053@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2054@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Autogen.obj `if test -f 'SymTab/Autogen.cc'; then $(CYGPATH_W) 'SymTab/Autogen.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Autogen.cc'; fi`
     2055
     2056SynTree/driver_cfa_cpp-Type.o: SynTree/Type.cc
     2057@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Type.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Type.Tpo -c -o SynTree/driver_cfa_cpp-Type.o `test -f 'SynTree/Type.cc' || echo '$(srcdir)/'`SynTree/Type.cc
     2058@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Type.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Type.Po
     2059@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Type.cc' object='SynTree/driver_cfa_cpp-Type.o' libtool=no @AMDEPBACKSLASH@
     2060@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2061@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Type.o `test -f 'SynTree/Type.cc' || echo '$(srcdir)/'`SynTree/Type.cc
     2062
     2063SynTree/driver_cfa_cpp-Type.obj: SynTree/Type.cc
     2064@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Type.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Type.Tpo -c -o SynTree/driver_cfa_cpp-Type.obj `if test -f 'SynTree/Type.cc'; then $(CYGPATH_W) 'SynTree/Type.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Type.cc'; fi`
     2065@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Type.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Type.Po
     2066@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Type.cc' object='SynTree/driver_cfa_cpp-Type.obj' libtool=no @AMDEPBACKSLASH@
     2067@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2068@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Type.obj `if test -f 'SynTree/Type.cc'; then $(CYGPATH_W) 'SynTree/Type.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Type.cc'; fi`
     2069
     2070SynTree/driver_cfa_cpp-VoidType.o: SynTree/VoidType.cc
     2071@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VoidType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Tpo -c -o SynTree/driver_cfa_cpp-VoidType.o `test -f 'SynTree/VoidType.cc' || echo '$(srcdir)/'`SynTree/VoidType.cc
     2072@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po
     2073@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/VoidType.cc' object='SynTree/driver_cfa_cpp-VoidType.o' libtool=no @AMDEPBACKSLASH@
     2074@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2075@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-VoidType.o `test -f 'SynTree/VoidType.cc' || echo '$(srcdir)/'`SynTree/VoidType.cc
     2076
     2077SynTree/driver_cfa_cpp-VoidType.obj: SynTree/VoidType.cc
     2078@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VoidType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Tpo -c -o SynTree/driver_cfa_cpp-VoidType.obj `if test -f 'SynTree/VoidType.cc'; then $(CYGPATH_W) 'SynTree/VoidType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VoidType.cc'; fi`
     2079@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po
     2080@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/VoidType.cc' object='SynTree/driver_cfa_cpp-VoidType.obj' libtool=no @AMDEPBACKSLASH@
     2081@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2082@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-VoidType.obj `if test -f 'SynTree/VoidType.cc'; then $(CYGPATH_W) 'SynTree/VoidType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VoidType.cc'; fi`
     2083
     2084SynTree/driver_cfa_cpp-BasicType.o: SynTree/BasicType.cc
     2085@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-BasicType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Tpo -c -o SynTree/driver_cfa_cpp-BasicType.o `test -f 'SynTree/BasicType.cc' || echo '$(srcdir)/'`SynTree/BasicType.cc
     2086@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Po
     2087@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/BasicType.cc' object='SynTree/driver_cfa_cpp-BasicType.o' libtool=no @AMDEPBACKSLASH@
     2088@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2089@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-BasicType.o `test -f 'SynTree/BasicType.cc' || echo '$(srcdir)/'`SynTree/BasicType.cc
     2090
     2091SynTree/driver_cfa_cpp-BasicType.obj: SynTree/BasicType.cc
     2092@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-BasicType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Tpo -c -o SynTree/driver_cfa_cpp-BasicType.obj `if test -f 'SynTree/BasicType.cc'; then $(CYGPATH_W) 'SynTree/BasicType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/BasicType.cc'; fi`
     2093@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Po
     2094@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/BasicType.cc' object='SynTree/driver_cfa_cpp-BasicType.obj' libtool=no @AMDEPBACKSLASH@
     2095@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2096@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-BasicType.obj `if test -f 'SynTree/BasicType.cc'; then $(CYGPATH_W) 'SynTree/BasicType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/BasicType.cc'; fi`
     2097
     2098SynTree/driver_cfa_cpp-PointerType.o: SynTree/PointerType.cc
     2099@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-PointerType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Tpo -c -o SynTree/driver_cfa_cpp-PointerType.o `test -f 'SynTree/PointerType.cc' || echo '$(srcdir)/'`SynTree/PointerType.cc
     2100@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Po
     2101@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/PointerType.cc' object='SynTree/driver_cfa_cpp-PointerType.o' libtool=no @AMDEPBACKSLASH@
     2102@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2103@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-PointerType.o `test -f 'SynTree/PointerType.cc' || echo '$(srcdir)/'`SynTree/PointerType.cc
     2104
     2105SynTree/driver_cfa_cpp-PointerType.obj: SynTree/PointerType.cc
     2106@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-PointerType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Tpo -c -o SynTree/driver_cfa_cpp-PointerType.obj `if test -f 'SynTree/PointerType.cc'; then $(CYGPATH_W) 'SynTree/PointerType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/PointerType.cc'; fi`
     2107@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-PointerType.Po
     2108@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/PointerType.cc' object='SynTree/driver_cfa_cpp-PointerType.obj' libtool=no @AMDEPBACKSLASH@
     2109@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2110@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-PointerType.obj `if test -f 'SynTree/PointerType.cc'; then $(CYGPATH_W) 'SynTree/PointerType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/PointerType.cc'; fi`
     2111
     2112SynTree/driver_cfa_cpp-ArrayType.o: SynTree/ArrayType.cc
     2113@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ArrayType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Tpo -c -o SynTree/driver_cfa_cpp-ArrayType.o `test -f 'SynTree/ArrayType.cc' || echo '$(srcdir)/'`SynTree/ArrayType.cc
     2114@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Po
     2115@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ArrayType.cc' object='SynTree/driver_cfa_cpp-ArrayType.o' libtool=no @AMDEPBACKSLASH@
     2116@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2117@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ArrayType.o `test -f 'SynTree/ArrayType.cc' || echo '$(srcdir)/'`SynTree/ArrayType.cc
     2118
     2119SynTree/driver_cfa_cpp-ArrayType.obj: SynTree/ArrayType.cc
     2120@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ArrayType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Tpo -c -o SynTree/driver_cfa_cpp-ArrayType.obj `if test -f 'SynTree/ArrayType.cc'; then $(CYGPATH_W) 'SynTree/ArrayType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ArrayType.cc'; fi`
     2121@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Po
     2122@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ArrayType.cc' object='SynTree/driver_cfa_cpp-ArrayType.obj' libtool=no @AMDEPBACKSLASH@
     2123@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2124@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ArrayType.obj `if test -f 'SynTree/ArrayType.cc'; then $(CYGPATH_W) 'SynTree/ArrayType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ArrayType.cc'; fi`
     2125
     2126SynTree/driver_cfa_cpp-ReferenceType.o: SynTree/ReferenceType.cc
     2127@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc
     2128@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po
     2129@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.o' libtool=no @AMDEPBACKSLASH@
     2130@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2131@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.o `test -f 'SynTree/ReferenceType.cc' || echo '$(srcdir)/'`SynTree/ReferenceType.cc
     2132
     2133SynTree/driver_cfa_cpp-ReferenceType.obj: SynTree/ReferenceType.cc
     2134@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi`
     2135@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceType.Po
     2136@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ReferenceType.cc' object='SynTree/driver_cfa_cpp-ReferenceType.obj' libtool=no @AMDEPBACKSLASH@
     2137@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2138@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceType.obj `if test -f 'SynTree/ReferenceType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceType.cc'; fi`
     2139
     2140SynTree/driver_cfa_cpp-FunctionType.o: SynTree/FunctionType.cc
     2141@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-FunctionType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Tpo -c -o SynTree/driver_cfa_cpp-FunctionType.o `test -f 'SynTree/FunctionType.cc' || echo '$(srcdir)/'`SynTree/FunctionType.cc
     2142@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Po
     2143@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/FunctionType.cc' object='SynTree/driver_cfa_cpp-FunctionType.o' libtool=no @AMDEPBACKSLASH@
     2144@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2145@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-FunctionType.o `test -f 'SynTree/FunctionType.cc' || echo '$(srcdir)/'`SynTree/FunctionType.cc
     2146
     2147SynTree/driver_cfa_cpp-FunctionType.obj: SynTree/FunctionType.cc
     2148@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-FunctionType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Tpo -c -o SynTree/driver_cfa_cpp-FunctionType.obj `if test -f 'SynTree/FunctionType.cc'; then $(CYGPATH_W) 'SynTree/FunctionType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/FunctionType.cc'; fi`
     2149@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Po
     2150@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/FunctionType.cc' object='SynTree/driver_cfa_cpp-FunctionType.obj' libtool=no @AMDEPBACKSLASH@
     2151@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2152@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-FunctionType.obj `if test -f 'SynTree/FunctionType.cc'; then $(CYGPATH_W) 'SynTree/FunctionType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/FunctionType.cc'; fi`
     2153
     2154SynTree/driver_cfa_cpp-ReferenceToType.o: SynTree/ReferenceToType.cc
     2155@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceToType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceToType.o `test -f 'SynTree/ReferenceToType.cc' || echo '$(srcdir)/'`SynTree/ReferenceToType.cc
     2156@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Po
     2157@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ReferenceToType.cc' object='SynTree/driver_cfa_cpp-ReferenceToType.o' libtool=no @AMDEPBACKSLASH@
     2158@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2159@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceToType.o `test -f 'SynTree/ReferenceToType.cc' || echo '$(srcdir)/'`SynTree/ReferenceToType.cc
     2160
     2161SynTree/driver_cfa_cpp-ReferenceToType.obj: SynTree/ReferenceToType.cc
     2162@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ReferenceToType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Tpo -c -o SynTree/driver_cfa_cpp-ReferenceToType.obj `if test -f 'SynTree/ReferenceToType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceToType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceToType.cc'; fi`
     2163@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ReferenceToType.Po
     2164@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ReferenceToType.cc' object='SynTree/driver_cfa_cpp-ReferenceToType.obj' libtool=no @AMDEPBACKSLASH@
     2165@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2166@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ReferenceToType.obj `if test -f 'SynTree/ReferenceToType.cc'; then $(CYGPATH_W) 'SynTree/ReferenceToType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ReferenceToType.cc'; fi`
     2167
     2168SynTree/driver_cfa_cpp-TupleType.o: SynTree/TupleType.cc
     2169@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TupleType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TupleType.Tpo -c -o SynTree/driver_cfa_cpp-TupleType.o `test -f 'SynTree/TupleType.cc' || echo '$(srcdir)/'`SynTree/TupleType.cc
     2170@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TupleType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TupleType.Po
     2171@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TupleType.cc' object='SynTree/driver_cfa_cpp-TupleType.o' libtool=no @AMDEPBACKSLASH@
     2172@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2173@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TupleType.o `test -f 'SynTree/TupleType.cc' || echo '$(srcdir)/'`SynTree/TupleType.cc
     2174
     2175SynTree/driver_cfa_cpp-TupleType.obj: SynTree/TupleType.cc
     2176@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TupleType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TupleType.Tpo -c -o SynTree/driver_cfa_cpp-TupleType.obj `if test -f 'SynTree/TupleType.cc'; then $(CYGPATH_W) 'SynTree/TupleType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TupleType.cc'; fi`
     2177@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TupleType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TupleType.Po
     2178@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TupleType.cc' object='SynTree/driver_cfa_cpp-TupleType.obj' libtool=no @AMDEPBACKSLASH@
     2179@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2180@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TupleType.obj `if test -f 'SynTree/TupleType.cc'; then $(CYGPATH_W) 'SynTree/TupleType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TupleType.cc'; fi`
     2181
     2182SynTree/driver_cfa_cpp-TypeofType.o: SynTree/TypeofType.cc
     2183@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeofType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Tpo -c -o SynTree/driver_cfa_cpp-TypeofType.o `test -f 'SynTree/TypeofType.cc' || echo '$(srcdir)/'`SynTree/TypeofType.cc
     2184@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Po
     2185@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeofType.cc' object='SynTree/driver_cfa_cpp-TypeofType.o' libtool=no @AMDEPBACKSLASH@
     2186@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2187@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeofType.o `test -f 'SynTree/TypeofType.cc' || echo '$(srcdir)/'`SynTree/TypeofType.cc
     2188
     2189SynTree/driver_cfa_cpp-TypeofType.obj: SynTree/TypeofType.cc
     2190@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeofType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Tpo -c -o SynTree/driver_cfa_cpp-TypeofType.obj `if test -f 'SynTree/TypeofType.cc'; then $(CYGPATH_W) 'SynTree/TypeofType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeofType.cc'; fi`
     2191@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Po
     2192@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeofType.cc' object='SynTree/driver_cfa_cpp-TypeofType.obj' libtool=no @AMDEPBACKSLASH@
     2193@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2194@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeofType.obj `if test -f 'SynTree/TypeofType.cc'; then $(CYGPATH_W) 'SynTree/TypeofType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeofType.cc'; fi`
     2195
     2196SynTree/driver_cfa_cpp-AttrType.o: SynTree/AttrType.cc
     2197@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AttrType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Tpo -c -o SynTree/driver_cfa_cpp-AttrType.o `test -f 'SynTree/AttrType.cc' || echo '$(srcdir)/'`SynTree/AttrType.cc
     2198@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Po
     2199@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AttrType.cc' object='SynTree/driver_cfa_cpp-AttrType.o' libtool=no @AMDEPBACKSLASH@
     2200@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2201@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AttrType.o `test -f 'SynTree/AttrType.cc' || echo '$(srcdir)/'`SynTree/AttrType.cc
     2202
     2203SynTree/driver_cfa_cpp-AttrType.obj: SynTree/AttrType.cc
     2204@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AttrType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Tpo -c -o SynTree/driver_cfa_cpp-AttrType.obj `if test -f 'SynTree/AttrType.cc'; then $(CYGPATH_W) 'SynTree/AttrType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AttrType.cc'; fi`
     2205@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Po
     2206@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AttrType.cc' object='SynTree/driver_cfa_cpp-AttrType.obj' libtool=no @AMDEPBACKSLASH@
     2207@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2208@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AttrType.obj `if test -f 'SynTree/AttrType.cc'; then $(CYGPATH_W) 'SynTree/AttrType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AttrType.cc'; fi`
     2209
     2210SynTree/driver_cfa_cpp-VarArgsType.o: SynTree/VarArgsType.cc
     2211@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VarArgsType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Tpo -c -o SynTree/driver_cfa_cpp-VarArgsType.o `test -f 'SynTree/VarArgsType.cc' || echo '$(srcdir)/'`SynTree/VarArgsType.cc
     2212@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Po
     2213@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/VarArgsType.cc' object='SynTree/driver_cfa_cpp-VarArgsType.o' libtool=no @AMDEPBACKSLASH@
     2214@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2215@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-VarArgsType.o `test -f 'SynTree/VarArgsType.cc' || echo '$(srcdir)/'`SynTree/VarArgsType.cc
     2216
     2217SynTree/driver_cfa_cpp-VarArgsType.obj: SynTree/VarArgsType.cc
     2218@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VarArgsType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Tpo -c -o SynTree/driver_cfa_cpp-VarArgsType.obj `if test -f 'SynTree/VarArgsType.cc'; then $(CYGPATH_W) 'SynTree/VarArgsType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VarArgsType.cc'; fi`
     2219@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Po
     2220@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/VarArgsType.cc' object='SynTree/driver_cfa_cpp-VarArgsType.obj' libtool=no @AMDEPBACKSLASH@
     2221@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2222@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-VarArgsType.obj `if test -f 'SynTree/VarArgsType.cc'; then $(CYGPATH_W) 'SynTree/VarArgsType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VarArgsType.cc'; fi`
     2223
     2224SynTree/driver_cfa_cpp-ZeroOneType.o: SynTree/ZeroOneType.cc
     2225@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ZeroOneType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Tpo -c -o SynTree/driver_cfa_cpp-ZeroOneType.o `test -f 'SynTree/ZeroOneType.cc' || echo '$(srcdir)/'`SynTree/ZeroOneType.cc
     2226@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Po
     2227@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ZeroOneType.cc' object='SynTree/driver_cfa_cpp-ZeroOneType.o' libtool=no @AMDEPBACKSLASH@
     2228@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2229@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ZeroOneType.o `test -f 'SynTree/ZeroOneType.cc' || echo '$(srcdir)/'`SynTree/ZeroOneType.cc
     2230
     2231SynTree/driver_cfa_cpp-ZeroOneType.obj: SynTree/ZeroOneType.cc
     2232@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ZeroOneType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Tpo -c -o SynTree/driver_cfa_cpp-ZeroOneType.obj `if test -f 'SynTree/ZeroOneType.cc'; then $(CYGPATH_W) 'SynTree/ZeroOneType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ZeroOneType.cc'; fi`
     2233@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Po
     2234@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ZeroOneType.cc' object='SynTree/driver_cfa_cpp-ZeroOneType.obj' libtool=no @AMDEPBACKSLASH@
     2235@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2236@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ZeroOneType.obj `if test -f 'SynTree/ZeroOneType.cc'; then $(CYGPATH_W) 'SynTree/ZeroOneType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ZeroOneType.cc'; fi`
     2237
     2238SynTree/driver_cfa_cpp-Constant.o: SynTree/Constant.cc
     2239@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Constant.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Tpo -c -o SynTree/driver_cfa_cpp-Constant.o `test -f 'SynTree/Constant.cc' || echo '$(srcdir)/'`SynTree/Constant.cc
     2240@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Po
     2241@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Constant.cc' object='SynTree/driver_cfa_cpp-Constant.o' libtool=no @AMDEPBACKSLASH@
     2242@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2243@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Constant.o `test -f 'SynTree/Constant.cc' || echo '$(srcdir)/'`SynTree/Constant.cc
     2244
     2245SynTree/driver_cfa_cpp-Constant.obj: SynTree/Constant.cc
     2246@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Constant.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Tpo -c -o SynTree/driver_cfa_cpp-Constant.obj `if test -f 'SynTree/Constant.cc'; then $(CYGPATH_W) 'SynTree/Constant.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Constant.cc'; fi`
     2247@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Po
     2248@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Constant.cc' object='SynTree/driver_cfa_cpp-Constant.obj' libtool=no @AMDEPBACKSLASH@
     2249@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2250@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Constant.obj `if test -f 'SynTree/Constant.cc'; then $(CYGPATH_W) 'SynTree/Constant.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Constant.cc'; fi`
     2251
     2252SynTree/driver_cfa_cpp-Expression.o: SynTree/Expression.cc
     2253@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Expression.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Expression.Tpo -c -o SynTree/driver_cfa_cpp-Expression.o `test -f 'SynTree/Expression.cc' || echo '$(srcdir)/'`SynTree/Expression.cc
     2254@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Expression.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Expression.Po
     2255@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Expression.cc' object='SynTree/driver_cfa_cpp-Expression.o' libtool=no @AMDEPBACKSLASH@
     2256@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2257@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Expression.o `test -f 'SynTree/Expression.cc' || echo '$(srcdir)/'`SynTree/Expression.cc
     2258
     2259SynTree/driver_cfa_cpp-Expression.obj: SynTree/Expression.cc
     2260@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Expression.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Expression.Tpo -c -o SynTree/driver_cfa_cpp-Expression.obj `if test -f 'SynTree/Expression.cc'; then $(CYGPATH_W) 'SynTree/Expression.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Expression.cc'; fi`
     2261@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Expression.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Expression.Po
     2262@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Expression.cc' object='SynTree/driver_cfa_cpp-Expression.obj' libtool=no @AMDEPBACKSLASH@
     2263@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2264@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Expression.obj `if test -f 'SynTree/Expression.cc'; then $(CYGPATH_W) 'SynTree/Expression.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Expression.cc'; fi`
     2265
     2266SynTree/driver_cfa_cpp-TupleExpr.o: SynTree/TupleExpr.cc
     2267@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TupleExpr.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Tpo -c -o SynTree/driver_cfa_cpp-TupleExpr.o `test -f 'SynTree/TupleExpr.cc' || echo '$(srcdir)/'`SynTree/TupleExpr.cc
     2268@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Po
     2269@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TupleExpr.cc' object='SynTree/driver_cfa_cpp-TupleExpr.o' libtool=no @AMDEPBACKSLASH@
     2270@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2271@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TupleExpr.o `test -f 'SynTree/TupleExpr.cc' || echo '$(srcdir)/'`SynTree/TupleExpr.cc
     2272
     2273SynTree/driver_cfa_cpp-TupleExpr.obj: SynTree/TupleExpr.cc
     2274@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TupleExpr.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Tpo -c -o SynTree/driver_cfa_cpp-TupleExpr.obj `if test -f 'SynTree/TupleExpr.cc'; then $(CYGPATH_W) 'SynTree/TupleExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TupleExpr.cc'; fi`
     2275@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TupleExpr.Po
     2276@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TupleExpr.cc' object='SynTree/driver_cfa_cpp-TupleExpr.obj' libtool=no @AMDEPBACKSLASH@
     2277@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2278@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TupleExpr.obj `if test -f 'SynTree/TupleExpr.cc'; then $(CYGPATH_W) 'SynTree/TupleExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TupleExpr.cc'; fi`
     2279
     2280SynTree/driver_cfa_cpp-CommaExpr.o: SynTree/CommaExpr.cc
     2281@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-CommaExpr.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Tpo -c -o SynTree/driver_cfa_cpp-CommaExpr.o `test -f 'SynTree/CommaExpr.cc' || echo '$(srcdir)/'`SynTree/CommaExpr.cc
     2282@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Po
     2283@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/CommaExpr.cc' object='SynTree/driver_cfa_cpp-CommaExpr.o' libtool=no @AMDEPBACKSLASH@
     2284@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2285@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-CommaExpr.o `test -f 'SynTree/CommaExpr.cc' || echo '$(srcdir)/'`SynTree/CommaExpr.cc
     2286
     2287SynTree/driver_cfa_cpp-CommaExpr.obj: SynTree/CommaExpr.cc
     2288@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-CommaExpr.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Tpo -c -o SynTree/driver_cfa_cpp-CommaExpr.obj `if test -f 'SynTree/CommaExpr.cc'; then $(CYGPATH_W) 'SynTree/CommaExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/CommaExpr.cc'; fi`
     2289@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Po
     2290@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/CommaExpr.cc' object='SynTree/driver_cfa_cpp-CommaExpr.obj' libtool=no @AMDEPBACKSLASH@
     2291@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2292@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-CommaExpr.obj `if test -f 'SynTree/CommaExpr.cc'; then $(CYGPATH_W) 'SynTree/CommaExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/CommaExpr.cc'; fi`
     2293
     2294SynTree/driver_cfa_cpp-TypeExpr.o: SynTree/TypeExpr.cc
     2295@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeExpr.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeExpr.Tpo -c -o SynTree/driver_cfa_cpp-TypeExpr.o `test -f 'SynTree/TypeExpr.cc' || echo '$(srcdir)/'`SynTree/TypeExpr.cc
     2296@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeExpr.Po
     2297@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeExpr.cc' object='SynTree/driver_cfa_cpp-TypeExpr.o' libtool=no @AMDEPBACKSLASH@
     2298@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2299@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeExpr.o `test -f 'SynTree/TypeExpr.cc' || echo '$(srcdir)/'`SynTree/TypeExpr.cc
     2300
     2301SynTree/driver_cfa_cpp-TypeExpr.obj: SynTree/TypeExpr.cc
     2302@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeExpr.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeExpr.Tpo -c -o SynTree/driver_cfa_cpp-TypeExpr.obj `if test -f 'SynTree/TypeExpr.cc'; then $(CYGPATH_W) 'SynTree/TypeExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeExpr.cc'; fi`
     2303@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeExpr.Po
     2304@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeExpr.cc' object='SynTree/driver_cfa_cpp-TypeExpr.obj' libtool=no @AMDEPBACKSLASH@
     2305@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2306@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeExpr.obj `if test -f 'SynTree/TypeExpr.cc'; then $(CYGPATH_W) 'SynTree/TypeExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeExpr.cc'; fi`
     2307
     2308SynTree/driver_cfa_cpp-ApplicationExpr.o: SynTree/ApplicationExpr.cc
     2309@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ApplicationExpr.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ApplicationExpr.Tpo -c -o SynTree/driver_cfa_cpp-ApplicationExpr.o `test -f 'SynTree/ApplicationExpr.cc' || echo '$(srcdir)/'`SynTree/ApplicationExpr.cc
     2310@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ApplicationExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ApplicationExpr.Po
     2311@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ApplicationExpr.cc' object='SynTree/driver_cfa_cpp-ApplicationExpr.o' libtool=no @AMDEPBACKSLASH@
     2312@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2313@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ApplicationExpr.o `test -f 'SynTree/ApplicationExpr.cc' || echo '$(srcdir)/'`SynTree/ApplicationExpr.cc
     2314
     2315SynTree/driver_cfa_cpp-ApplicationExpr.obj: SynTree/ApplicationExpr.cc
     2316@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ApplicationExpr.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ApplicationExpr.Tpo -c -o SynTree/driver_cfa_cpp-ApplicationExpr.obj `if test -f 'SynTree/ApplicationExpr.cc'; then $(CYGPATH_W) 'SynTree/ApplicationExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ApplicationExpr.cc'; fi`
     2317@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ApplicationExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ApplicationExpr.Po
     2318@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ApplicationExpr.cc' object='SynTree/driver_cfa_cpp-ApplicationExpr.obj' libtool=no @AMDEPBACKSLASH@
     2319@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2320@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ApplicationExpr.obj `if test -f 'SynTree/ApplicationExpr.cc'; then $(CYGPATH_W) 'SynTree/ApplicationExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ApplicationExpr.cc'; fi`
     2321
     2322SynTree/driver_cfa_cpp-AddressExpr.o: SynTree/AddressExpr.cc
     2323@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddressExpr.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Tpo -c -o SynTree/driver_cfa_cpp-AddressExpr.o `test -f 'SynTree/AddressExpr.cc' || echo '$(srcdir)/'`SynTree/AddressExpr.cc
     2324@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po
     2325@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AddressExpr.cc' object='SynTree/driver_cfa_cpp-AddressExpr.o' libtool=no @AMDEPBACKSLASH@
     2326@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2327@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddressExpr.o `test -f 'SynTree/AddressExpr.cc' || echo '$(srcdir)/'`SynTree/AddressExpr.cc
     2328
     2329SynTree/driver_cfa_cpp-AddressExpr.obj: SynTree/AddressExpr.cc
     2330@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddressExpr.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Tpo -c -o SynTree/driver_cfa_cpp-AddressExpr.obj `if test -f 'SynTree/AddressExpr.cc'; then $(CYGPATH_W) 'SynTree/AddressExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddressExpr.cc'; fi`
     2331@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po
     2332@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AddressExpr.cc' object='SynTree/driver_cfa_cpp-AddressExpr.obj' libtool=no @AMDEPBACKSLASH@
     2333@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2334@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddressExpr.obj `if test -f 'SynTree/AddressExpr.cc'; then $(CYGPATH_W) 'SynTree/AddressExpr.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddressExpr.cc'; fi`
     2335
     2336SynTree/driver_cfa_cpp-Statement.o: SynTree/Statement.cc
     2337@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Statement.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Tpo -c -o SynTree/driver_cfa_cpp-Statement.o `test -f 'SynTree/Statement.cc' || echo '$(srcdir)/'`SynTree/Statement.cc
     2338@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Po
     2339@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Statement.cc' object='SynTree/driver_cfa_cpp-Statement.o' libtool=no @AMDEPBACKSLASH@
     2340@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2341@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Statement.o `test -f 'SynTree/Statement.cc' || echo '$(srcdir)/'`SynTree/Statement.cc
     2342
     2343SynTree/driver_cfa_cpp-Statement.obj: SynTree/Statement.cc
     2344@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Statement.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Tpo -c -o SynTree/driver_cfa_cpp-Statement.obj `if test -f 'SynTree/Statement.cc'; then $(CYGPATH_W) 'SynTree/Statement.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Statement.cc'; fi`
     2345@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Statement.Po
     2346@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Statement.cc' object='SynTree/driver_cfa_cpp-Statement.obj' libtool=no @AMDEPBACKSLASH@
     2347@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2348@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Statement.obj `if test -f 'SynTree/Statement.cc'; then $(CYGPATH_W) 'SynTree/Statement.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Statement.cc'; fi`
     2349
     2350SynTree/driver_cfa_cpp-CompoundStmt.o: SynTree/CompoundStmt.cc
     2351@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-CompoundStmt.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Tpo -c -o SynTree/driver_cfa_cpp-CompoundStmt.o `test -f 'SynTree/CompoundStmt.cc' || echo '$(srcdir)/'`SynTree/CompoundStmt.cc
     2352@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Po
     2353@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/CompoundStmt.cc' object='SynTree/driver_cfa_cpp-CompoundStmt.o' libtool=no @AMDEPBACKSLASH@
     2354@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2355@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-CompoundStmt.o `test -f 'SynTree/CompoundStmt.cc' || echo '$(srcdir)/'`SynTree/CompoundStmt.cc
     2356
     2357SynTree/driver_cfa_cpp-CompoundStmt.obj: SynTree/CompoundStmt.cc
     2358@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-CompoundStmt.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Tpo -c -o SynTree/driver_cfa_cpp-CompoundStmt.obj `if test -f 'SynTree/CompoundStmt.cc'; then $(CYGPATH_W) 'SynTree/CompoundStmt.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/CompoundStmt.cc'; fi`
     2359@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Po
     2360@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/CompoundStmt.cc' object='SynTree/driver_cfa_cpp-CompoundStmt.obj' libtool=no @AMDEPBACKSLASH@
     2361@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2362@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-CompoundStmt.obj `if test -f 'SynTree/CompoundStmt.cc'; then $(CYGPATH_W) 'SynTree/CompoundStmt.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/CompoundStmt.cc'; fi`
     2363
     2364SynTree/driver_cfa_cpp-DeclStmt.o: SynTree/DeclStmt.cc
     2365@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclStmt.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Tpo -c -o SynTree/driver_cfa_cpp-DeclStmt.o `test -f 'SynTree/DeclStmt.cc' || echo '$(srcdir)/'`SynTree/DeclStmt.cc
     2366@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Po
     2367@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclStmt.cc' object='SynTree/driver_cfa_cpp-DeclStmt.o' libtool=no @AMDEPBACKSLASH@
     2368@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2369@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclStmt.o `test -f 'SynTree/DeclStmt.cc' || echo '$(srcdir)/'`SynTree/DeclStmt.cc
     2370
     2371SynTree/driver_cfa_cpp-DeclStmt.obj: SynTree/DeclStmt.cc
     2372@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclStmt.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Tpo -c -o SynTree/driver_cfa_cpp-DeclStmt.obj `if test -f 'SynTree/DeclStmt.cc'; then $(CYGPATH_W) 'SynTree/DeclStmt.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclStmt.cc'; fi`
     2373@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Po
     2374@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclStmt.cc' object='SynTree/driver_cfa_cpp-DeclStmt.obj' libtool=no @AMDEPBACKSLASH@
     2375@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2376@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclStmt.obj `if test -f 'SynTree/DeclStmt.cc'; then $(CYGPATH_W) 'SynTree/DeclStmt.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclStmt.cc'; fi`
     2377
     2378SynTree/driver_cfa_cpp-Declaration.o: SynTree/Declaration.cc
     2379@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Declaration.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Tpo -c -o SynTree/driver_cfa_cpp-Declaration.o `test -f 'SynTree/Declaration.cc' || echo '$(srcdir)/'`SynTree/Declaration.cc
     2380@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Po
     2381@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Declaration.cc' object='SynTree/driver_cfa_cpp-Declaration.o' libtool=no @AMDEPBACKSLASH@
     2382@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2383@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Declaration.o `test -f 'SynTree/Declaration.cc' || echo '$(srcdir)/'`SynTree/Declaration.cc
     2384
     2385SynTree/driver_cfa_cpp-Declaration.obj: SynTree/Declaration.cc
     2386@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Declaration.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Tpo -c -o SynTree/driver_cfa_cpp-Declaration.obj `if test -f 'SynTree/Declaration.cc'; then $(CYGPATH_W) 'SynTree/Declaration.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Declaration.cc'; fi`
     2387@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Po
     2388@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Declaration.cc' object='SynTree/driver_cfa_cpp-Declaration.obj' libtool=no @AMDEPBACKSLASH@
     2389@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2390@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Declaration.obj `if test -f 'SynTree/Declaration.cc'; then $(CYGPATH_W) 'SynTree/Declaration.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Declaration.cc'; fi`
     2391
     2392SynTree/driver_cfa_cpp-DeclarationWithType.o: SynTree/DeclarationWithType.cc
     2393@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclarationWithType.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclarationWithType.Tpo -c -o SynTree/driver_cfa_cpp-DeclarationWithType.o `test -f 'SynTree/DeclarationWithType.cc' || echo '$(srcdir)/'`SynTree/DeclarationWithType.cc
     2394@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclarationWithType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclarationWithType.Po
     2395@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclarationWithType.cc' object='SynTree/driver_cfa_cpp-DeclarationWithType.o' libtool=no @AMDEPBACKSLASH@
     2396@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2397@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclarationWithType.o `test -f 'SynTree/DeclarationWithType.cc' || echo '$(srcdir)/'`SynTree/DeclarationWithType.cc
     2398
     2399SynTree/driver_cfa_cpp-DeclarationWithType.obj: SynTree/DeclarationWithType.cc
     2400@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclarationWithType.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclarationWithType.Tpo -c -o SynTree/driver_cfa_cpp-DeclarationWithType.obj `if test -f 'SynTree/DeclarationWithType.cc'; then $(CYGPATH_W) 'SynTree/DeclarationWithType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclarationWithType.cc'; fi`
     2401@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclarationWithType.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclarationWithType.Po
     2402@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclarationWithType.cc' object='SynTree/driver_cfa_cpp-DeclarationWithType.obj' libtool=no @AMDEPBACKSLASH@
     2403@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2404@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclarationWithType.obj `if test -f 'SynTree/DeclarationWithType.cc'; then $(CYGPATH_W) 'SynTree/DeclarationWithType.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclarationWithType.cc'; fi`
     2405
     2406SynTree/driver_cfa_cpp-ObjectDecl.o: SynTree/ObjectDecl.cc
     2407@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ObjectDecl.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Tpo -c -o SynTree/driver_cfa_cpp-ObjectDecl.o `test -f 'SynTree/ObjectDecl.cc' || echo '$(srcdir)/'`SynTree/ObjectDecl.cc
     2408@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Po
     2409@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ObjectDecl.cc' object='SynTree/driver_cfa_cpp-ObjectDecl.o' libtool=no @AMDEPBACKSLASH@
     2410@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2411@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ObjectDecl.o `test -f 'SynTree/ObjectDecl.cc' || echo '$(srcdir)/'`SynTree/ObjectDecl.cc
     2412
     2413SynTree/driver_cfa_cpp-ObjectDecl.obj: SynTree/ObjectDecl.cc
     2414@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-ObjectDecl.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Tpo -c -o SynTree/driver_cfa_cpp-ObjectDecl.obj `if test -f 'SynTree/ObjectDecl.cc'; then $(CYGPATH_W) 'SynTree/ObjectDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ObjectDecl.cc'; fi`
     2415@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Po
     2416@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/ObjectDecl.cc' object='SynTree/driver_cfa_cpp-ObjectDecl.obj' libtool=no @AMDEPBACKSLASH@
     2417@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2418@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-ObjectDecl.obj `if test -f 'SynTree/ObjectDecl.cc'; then $(CYGPATH_W) 'SynTree/ObjectDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/ObjectDecl.cc'; fi`
     2419
     2420SynTree/driver_cfa_cpp-FunctionDecl.o: SynTree/FunctionDecl.cc
     2421@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-FunctionDecl.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionDecl.Tpo -c -o SynTree/driver_cfa_cpp-FunctionDecl.o `test -f 'SynTree/FunctionDecl.cc' || echo '$(srcdir)/'`SynTree/FunctionDecl.cc
     2422@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionDecl.Po
     2423@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/FunctionDecl.cc' object='SynTree/driver_cfa_cpp-FunctionDecl.o' libtool=no @AMDEPBACKSLASH@
     2424@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2425@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-FunctionDecl.o `test -f 'SynTree/FunctionDecl.cc' || echo '$(srcdir)/'`SynTree/FunctionDecl.cc
     2426
     2427SynTree/driver_cfa_cpp-FunctionDecl.obj: SynTree/FunctionDecl.cc
     2428@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-FunctionDecl.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionDecl.Tpo -c -o SynTree/driver_cfa_cpp-FunctionDecl.obj `if test -f 'SynTree/FunctionDecl.cc'; then $(CYGPATH_W) 'SynTree/FunctionDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/FunctionDecl.cc'; fi`
     2429@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionDecl.Po
     2430@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/FunctionDecl.cc' object='SynTree/driver_cfa_cpp-FunctionDecl.obj' libtool=no @AMDEPBACKSLASH@
     2431@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2432@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-FunctionDecl.obj `if test -f 'SynTree/FunctionDecl.cc'; then $(CYGPATH_W) 'SynTree/FunctionDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/FunctionDecl.cc'; fi`
     2433
     2434SynTree/driver_cfa_cpp-AggregateDecl.o: SynTree/AggregateDecl.cc
     2435@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AggregateDecl.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Tpo -c -o SynTree/driver_cfa_cpp-AggregateDecl.o `test -f 'SynTree/AggregateDecl.cc' || echo '$(srcdir)/'`SynTree/AggregateDecl.cc
     2436@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Po
     2437@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AggregateDecl.cc' object='SynTree/driver_cfa_cpp-AggregateDecl.o' libtool=no @AMDEPBACKSLASH@
     2438@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2439@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AggregateDecl.o `test -f 'SynTree/AggregateDecl.cc' || echo '$(srcdir)/'`SynTree/AggregateDecl.cc
     2440
     2441SynTree/driver_cfa_cpp-AggregateDecl.obj: SynTree/AggregateDecl.cc
     2442@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AggregateDecl.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Tpo -c -o SynTree/driver_cfa_cpp-AggregateDecl.obj `if test -f 'SynTree/AggregateDecl.cc'; then $(CYGPATH_W) 'SynTree/AggregateDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AggregateDecl.cc'; fi`
     2443@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Po
     2444@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AggregateDecl.cc' object='SynTree/driver_cfa_cpp-AggregateDecl.obj' libtool=no @AMDEPBACKSLASH@
     2445@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2446@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AggregateDecl.obj `if test -f 'SynTree/AggregateDecl.cc'; then $(CYGPATH_W) 'SynTree/AggregateDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AggregateDecl.cc'; fi`
     2447
     2448SynTree/driver_cfa_cpp-NamedTypeDecl.o: SynTree/NamedTypeDecl.cc
     2449@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-NamedTypeDecl.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Tpo -c -o SynTree/driver_cfa_cpp-NamedTypeDecl.o `test -f 'SynTree/NamedTypeDecl.cc' || echo '$(srcdir)/'`SynTree/NamedTypeDecl.cc
     2450@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Po
     2451@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/NamedTypeDecl.cc' object='SynTree/driver_cfa_cpp-NamedTypeDecl.o' libtool=no @AMDEPBACKSLASH@
     2452@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2453@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-NamedTypeDecl.o `test -f 'SynTree/NamedTypeDecl.cc' || echo '$(srcdir)/'`SynTree/NamedTypeDecl.cc
     2454
     2455SynTree/driver_cfa_cpp-NamedTypeDecl.obj: SynTree/NamedTypeDecl.cc
     2456@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-NamedTypeDecl.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Tpo -c -o SynTree/driver_cfa_cpp-NamedTypeDecl.obj `if test -f 'SynTree/NamedTypeDecl.cc'; then $(CYGPATH_W) 'SynTree/NamedTypeDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/NamedTypeDecl.cc'; fi`
     2457@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Po
     2458@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/NamedTypeDecl.cc' object='SynTree/driver_cfa_cpp-NamedTypeDecl.obj' libtool=no @AMDEPBACKSLASH@
     2459@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2460@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-NamedTypeDecl.obj `if test -f 'SynTree/NamedTypeDecl.cc'; then $(CYGPATH_W) 'SynTree/NamedTypeDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/NamedTypeDecl.cc'; fi`
     2461
     2462SynTree/driver_cfa_cpp-TypeDecl.o: SynTree/TypeDecl.cc
     2463@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeDecl.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeDecl.Tpo -c -o SynTree/driver_cfa_cpp-TypeDecl.o `test -f 'SynTree/TypeDecl.cc' || echo '$(srcdir)/'`SynTree/TypeDecl.cc
     2464@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeDecl.Po
     2465@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeDecl.cc' object='SynTree/driver_cfa_cpp-TypeDecl.o' libtool=no @AMDEPBACKSLASH@
     2466@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2467@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeDecl.o `test -f 'SynTree/TypeDecl.cc' || echo '$(srcdir)/'`SynTree/TypeDecl.cc
     2468
     2469SynTree/driver_cfa_cpp-TypeDecl.obj: SynTree/TypeDecl.cc
     2470@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeDecl.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeDecl.Tpo -c -o SynTree/driver_cfa_cpp-TypeDecl.obj `if test -f 'SynTree/TypeDecl.cc'; then $(CYGPATH_W) 'SynTree/TypeDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeDecl.cc'; fi`
     2471@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeDecl.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeDecl.Po
     2472@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeDecl.cc' object='SynTree/driver_cfa_cpp-TypeDecl.obj' libtool=no @AMDEPBACKSLASH@
     2473@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2474@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeDecl.obj `if test -f 'SynTree/TypeDecl.cc'; then $(CYGPATH_W) 'SynTree/TypeDecl.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeDecl.cc'; fi`
     2475
     2476SynTree/driver_cfa_cpp-Initializer.o: SynTree/Initializer.cc
     2477@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Initializer.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Tpo -c -o SynTree/driver_cfa_cpp-Initializer.o `test -f 'SynTree/Initializer.cc' || echo '$(srcdir)/'`SynTree/Initializer.cc
     2478@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Po
     2479@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Initializer.cc' object='SynTree/driver_cfa_cpp-Initializer.o' libtool=no @AMDEPBACKSLASH@
     2480@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2481@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Initializer.o `test -f 'SynTree/Initializer.cc' || echo '$(srcdir)/'`SynTree/Initializer.cc
     2482
     2483SynTree/driver_cfa_cpp-Initializer.obj: SynTree/Initializer.cc
     2484@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Initializer.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Tpo -c -o SynTree/driver_cfa_cpp-Initializer.obj `if test -f 'SynTree/Initializer.cc'; then $(CYGPATH_W) 'SynTree/Initializer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Initializer.cc'; fi`
     2485@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Po
     2486@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Initializer.cc' object='SynTree/driver_cfa_cpp-Initializer.obj' libtool=no @AMDEPBACKSLASH@
     2487@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2488@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Initializer.obj `if test -f 'SynTree/Initializer.cc'; then $(CYGPATH_W) 'SynTree/Initializer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Initializer.cc'; fi`
     2489
     2490SynTree/driver_cfa_cpp-TypeSubstitution.o: SynTree/TypeSubstitution.cc
     2491@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeSubstitution.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeSubstitution.Tpo -c -o SynTree/driver_cfa_cpp-TypeSubstitution.o `test -f 'SynTree/TypeSubstitution.cc' || echo '$(srcdir)/'`SynTree/TypeSubstitution.cc
     2492@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeSubstitution.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeSubstitution.Po
     2493@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeSubstitution.cc' object='SynTree/driver_cfa_cpp-TypeSubstitution.o' libtool=no @AMDEPBACKSLASH@
     2494@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2495@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeSubstitution.o `test -f 'SynTree/TypeSubstitution.cc' || echo '$(srcdir)/'`SynTree/TypeSubstitution.cc
     2496
     2497SynTree/driver_cfa_cpp-TypeSubstitution.obj: SynTree/TypeSubstitution.cc
     2498@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-TypeSubstitution.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-TypeSubstitution.Tpo -c -o SynTree/driver_cfa_cpp-TypeSubstitution.obj `if test -f 'SynTree/TypeSubstitution.cc'; then $(CYGPATH_W) 'SynTree/TypeSubstitution.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeSubstitution.cc'; fi`
     2499@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-TypeSubstitution.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-TypeSubstitution.Po
     2500@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/TypeSubstitution.cc' object='SynTree/driver_cfa_cpp-TypeSubstitution.obj' libtool=no @AMDEPBACKSLASH@
     2501@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2502@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeSubstitution.obj `if test -f 'SynTree/TypeSubstitution.cc'; then $(CYGPATH_W) 'SynTree/TypeSubstitution.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeSubstitution.cc'; fi`
     2503
     2504SynTree/driver_cfa_cpp-Attribute.o: SynTree/Attribute.cc
     2505@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Attribute.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo -c -o SynTree/driver_cfa_cpp-Attribute.o `test -f 'SynTree/Attribute.cc' || echo '$(srcdir)/'`SynTree/Attribute.cc
     2506@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po
     2507@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Attribute.cc' object='SynTree/driver_cfa_cpp-Attribute.o' libtool=no @AMDEPBACKSLASH@
     2508@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2509@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.o `test -f 'SynTree/Attribute.cc' || echo '$(srcdir)/'`SynTree/Attribute.cc
     2510
     2511SynTree/driver_cfa_cpp-Attribute.obj: SynTree/Attribute.cc
     2512@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Attribute.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi`
     2513@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po
     2514@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Attribute.cc' object='SynTree/driver_cfa_cpp-Attribute.obj' libtool=no @AMDEPBACKSLASH@
     2515@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2516@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi`
     2517
     2518SynTree/driver_cfa_cpp-DeclReplacer.o: SynTree/DeclReplacer.cc
     2519@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclReplacer.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo -c -o SynTree/driver_cfa_cpp-DeclReplacer.o `test -f 'SynTree/DeclReplacer.cc' || echo '$(srcdir)/'`SynTree/DeclReplacer.cc
     2520@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Po
     2521@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclReplacer.cc' object='SynTree/driver_cfa_cpp-DeclReplacer.o' libtool=no @AMDEPBACKSLASH@
     2522@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2523@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclReplacer.o `test -f 'SynTree/DeclReplacer.cc' || echo '$(srcdir)/'`SynTree/DeclReplacer.cc
     2524
     2525SynTree/driver_cfa_cpp-DeclReplacer.obj: SynTree/DeclReplacer.cc
     2526@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclReplacer.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo -c -o SynTree/driver_cfa_cpp-DeclReplacer.obj `if test -f 'SynTree/DeclReplacer.cc'; then $(CYGPATH_W) 'SynTree/DeclReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclReplacer.cc'; fi`
     2527@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Po
     2528@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclReplacer.cc' object='SynTree/driver_cfa_cpp-DeclReplacer.obj' libtool=no @AMDEPBACKSLASH@
     2529@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2530@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclReplacer.obj `if test -f 'SynTree/DeclReplacer.cc'; then $(CYGPATH_W) 'SynTree/DeclReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclReplacer.cc'; fi`
     2531
     2532Tuples/driver_cfa_cpp-TupleAssignment.o: Tuples/TupleAssignment.cc
     2533@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-TupleAssignment.o -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Tpo -c -o Tuples/driver_cfa_cpp-TupleAssignment.o `test -f 'Tuples/TupleAssignment.cc' || echo '$(srcdir)/'`Tuples/TupleAssignment.cc
     2534@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Po
     2535@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Tuples/TupleAssignment.cc' object='Tuples/driver_cfa_cpp-TupleAssignment.o' libtool=no @AMDEPBACKSLASH@
     2536@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2537@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-TupleAssignment.o `test -f 'Tuples/TupleAssignment.cc' || echo '$(srcdir)/'`Tuples/TupleAssignment.cc
     2538
     2539Tuples/driver_cfa_cpp-TupleAssignment.obj: Tuples/TupleAssignment.cc
     2540@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-TupleAssignment.obj -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Tpo -c -o Tuples/driver_cfa_cpp-TupleAssignment.obj `if test -f 'Tuples/TupleAssignment.cc'; then $(CYGPATH_W) 'Tuples/TupleAssignment.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/TupleAssignment.cc'; fi`
     2541@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Po
     2542@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Tuples/TupleAssignment.cc' object='Tuples/driver_cfa_cpp-TupleAssignment.obj' libtool=no @AMDEPBACKSLASH@
     2543@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2544@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-TupleAssignment.obj `if test -f 'Tuples/TupleAssignment.cc'; then $(CYGPATH_W) 'Tuples/TupleAssignment.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/TupleAssignment.cc'; fi`
     2545
     2546Tuples/driver_cfa_cpp-TupleExpansion.o: Tuples/TupleExpansion.cc
     2547@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-TupleExpansion.o -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo -c -o Tuples/driver_cfa_cpp-TupleExpansion.o `test -f 'Tuples/TupleExpansion.cc' || echo '$(srcdir)/'`Tuples/TupleExpansion.cc
     2548@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Po
     2549@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Tuples/TupleExpansion.cc' object='Tuples/driver_cfa_cpp-TupleExpansion.o' libtool=no @AMDEPBACKSLASH@
     2550@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2551@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-TupleExpansion.o `test -f 'Tuples/TupleExpansion.cc' || echo '$(srcdir)/'`Tuples/TupleExpansion.cc
     2552
     2553Tuples/driver_cfa_cpp-TupleExpansion.obj: Tuples/TupleExpansion.cc
     2554@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-TupleExpansion.obj -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo -c -o Tuples/driver_cfa_cpp-TupleExpansion.obj `if test -f 'Tuples/TupleExpansion.cc'; then $(CYGPATH_W) 'Tuples/TupleExpansion.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/TupleExpansion.cc'; fi`
     2555@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Po
     2556@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Tuples/TupleExpansion.cc' object='Tuples/driver_cfa_cpp-TupleExpansion.obj' libtool=no @AMDEPBACKSLASH@
     2557@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2558@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-TupleExpansion.obj `if test -f 'Tuples/TupleExpansion.cc'; then $(CYGPATH_W) 'Tuples/TupleExpansion.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/TupleExpansion.cc'; fi`
     2559
     2560Tuples/driver_cfa_cpp-Explode.o: Tuples/Explode.cc
     2561@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-Explode.o -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo -c -o Tuples/driver_cfa_cpp-Explode.o `test -f 'Tuples/Explode.cc' || echo '$(srcdir)/'`Tuples/Explode.cc
     2562@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Po
     2563@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Tuples/Explode.cc' object='Tuples/driver_cfa_cpp-Explode.o' libtool=no @AMDEPBACKSLASH@
     2564@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2565@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-Explode.o `test -f 'Tuples/Explode.cc' || echo '$(srcdir)/'`Tuples/Explode.cc
     2566
     2567Tuples/driver_cfa_cpp-Explode.obj: Tuples/Explode.cc
     2568@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-Explode.obj -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo -c -o Tuples/driver_cfa_cpp-Explode.obj `if test -f 'Tuples/Explode.cc'; then $(CYGPATH_W) 'Tuples/Explode.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/Explode.cc'; fi`
     2569@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Po
     2570@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Tuples/Explode.cc' object='Tuples/driver_cfa_cpp-Explode.obj' libtool=no @AMDEPBACKSLASH@
     2571@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2572@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-Explode.obj `if test -f 'Tuples/Explode.cc'; then $(CYGPATH_W) 'Tuples/Explode.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/Explode.cc'; fi`
     2573
     2574Virtual/driver_cfa_cpp-ExpandCasts.o: Virtual/ExpandCasts.cc
     2575@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Virtual/driver_cfa_cpp-ExpandCasts.o -MD -MP -MF Virtual/$(DEPDIR)/driver_cfa_cpp-ExpandCasts.Tpo -c -o Virtual/driver_cfa_cpp-ExpandCasts.o `test -f 'Virtual/ExpandCasts.cc' || echo '$(srcdir)/'`Virtual/ExpandCasts.cc
     2576@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Virtual/$(DEPDIR)/driver_cfa_cpp-ExpandCasts.Tpo Virtual/$(DEPDIR)/driver_cfa_cpp-ExpandCasts.Po
     2577@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Virtual/ExpandCasts.cc' object='Virtual/driver_cfa_cpp-ExpandCasts.o' libtool=no @AMDEPBACKSLASH@
     2578@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2579@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Virtual/driver_cfa_cpp-ExpandCasts.o `test -f 'Virtual/ExpandCasts.cc' || echo '$(srcdir)/'`Virtual/ExpandCasts.cc
     2580
     2581Virtual/driver_cfa_cpp-ExpandCasts.obj: Virtual/ExpandCasts.cc
     2582@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Virtual/driver_cfa_cpp-ExpandCasts.obj -MD -MP -MF Virtual/$(DEPDIR)/driver_cfa_cpp-ExpandCasts.Tpo -c -o Virtual/driver_cfa_cpp-ExpandCasts.obj `if test -f 'Virtual/ExpandCasts.cc'; then $(CYGPATH_W) 'Virtual/ExpandCasts.cc'; else $(CYGPATH_W) '$(srcdir)/Virtual/ExpandCasts.cc'; fi`
     2583@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) Virtual/$(DEPDIR)/driver_cfa_cpp-ExpandCasts.Tpo Virtual/$(DEPDIR)/driver_cfa_cpp-ExpandCasts.Po
     2584@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='Virtual/ExpandCasts.cc' object='Virtual/driver_cfa_cpp-ExpandCasts.obj' libtool=no @AMDEPBACKSLASH@
     2585@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2586@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Virtual/driver_cfa_cpp-ExpandCasts.obj `if test -f 'Virtual/ExpandCasts.cc'; then $(CYGPATH_W) 'Virtual/ExpandCasts.cc'; else $(CYGPATH_W) '$(srcdir)/Virtual/ExpandCasts.cc'; fi`
    14022587
    14032588.ll.cc:
     
    14062591.yy.cc:
    14072592        $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
    1408 
    1409 mostlyclean-libtool:
    1410         -rm -f *.lo
    1411 
    1412 clean-libtool:
    1413         -rm -rf .libs _libs
    1414         -rm -rf ../driver/.libs ../driver/_libs
    14152593
    14162594ID: $(am__tagged_files)
     
    14992677check: $(BUILT_SOURCES)
    15002678        $(MAKE) $(AM_MAKEFLAGS) check-am
    1501 all-am: Makefile $(LIBRARIES) $(PROGRAMS)
     2679all-am: Makefile $(PROGRAMS)
    15022680installdirs:
    15032681        for dir in "$(DESTDIR)$(cfa_cpplibdir)"; do \
     
    15252703        fi
    15262704mostlyclean-generic:
    1527         -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
    15282705
    15292706clean-generic:
     
    15322709        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
    15332710        -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
    1534         -rm -f ../driver/$(am__dirstamp)
    1535         -rm -f AST/$(DEPDIR)/$(am__dirstamp)
    1536         -rm -f AST/$(am__dirstamp)
    15372711        -rm -f CodeGen/$(DEPDIR)/$(am__dirstamp)
    15382712        -rm -f CodeGen/$(am__dirstamp)
     
    15412715        -rm -f Common/$(DEPDIR)/$(am__dirstamp)
    15422716        -rm -f Common/$(am__dirstamp)
    1543         -rm -f Common/Stats/$(DEPDIR)/$(am__dirstamp)
    1544         -rm -f Common/Stats/$(am__dirstamp)
    15452717        -rm -f Concurrency/$(DEPDIR)/$(am__dirstamp)
    15462718        -rm -f Concurrency/$(am__dirstamp)
     
    15612733        -rm -f Tuples/$(DEPDIR)/$(am__dirstamp)
    15622734        -rm -f Tuples/$(am__dirstamp)
    1563         -rm -f Validate/$(DEPDIR)/$(am__dirstamp)
    1564         -rm -f Validate/$(am__dirstamp)
    15652735        -rm -f Virtual/$(DEPDIR)/$(am__dirstamp)
    15662736        -rm -f Virtual/$(am__dirstamp)
     2737        -rm -f driver/$(am__dirstamp)
    15672738
    15682739maintainer-clean-generic:
     
    15762747clean: clean-am
    15772748
    1578 clean-am: clean-cfa_cpplibPROGRAMS clean-generic clean-libtool \
    1579         clean-noinstLIBRARIES mostlyclean-am
     2749clean-am: clean-cfa_cpplibPROGRAMS clean-generic mostlyclean-am
    15802750
    15812751distclean: distclean-am
    1582         -rm -rf ./$(DEPDIR) AST/$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Common/Stats/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Validate/$(DEPDIR) Virtual/$(DEPDIR)
     2752        -rm -rf ./$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Virtual/$(DEPDIR)
    15832753        -rm -f Makefile
    15842754distclean-am: clean-am distclean-compile distclean-generic \
     
    16262796
    16272797maintainer-clean: maintainer-clean-am
    1628         -rm -rf ./$(DEPDIR) AST/$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Common/Stats/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Validate/$(DEPDIR) Virtual/$(DEPDIR)
     2798        -rm -rf ./$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Virtual/$(DEPDIR)
    16292799        -rm -f Makefile
    16302800maintainer-clean-am: distclean-am maintainer-clean-generic
     
    16322802mostlyclean: mostlyclean-am
    16332803
    1634 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
    1635         mostlyclean-libtool
     2804mostlyclean-am: mostlyclean-compile mostlyclean-generic
    16362805
    16372806pdf: pdf-am
     
    16482817
    16492818.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
    1650         clean-cfa_cpplibPROGRAMS clean-generic clean-libtool \
    1651         clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
    1652         distclean-compile distclean-generic distclean-libtool \
     2819        clean-cfa_cpplibPROGRAMS clean-generic cscopelist-am ctags \
     2820        ctags-am distclean distclean-compile distclean-generic \
    16532821        distclean-tags distdir dvi dvi-am html html-am info info-am \
    16542822        install install-am install-cfa_cpplibPROGRAMS install-data \
     
    16592827        installcheck-am installdirs maintainer-clean \
    16602828        maintainer-clean-generic mostlyclean mostlyclean-compile \
    1661         mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
    1662         tags tags-am uninstall uninstall-am \
    1663         uninstall-cfa_cpplibPROGRAMS
     2829        mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
     2830        uninstall-am uninstall-cfa_cpplibPROGRAMS
    16642831
    16652832.PRECIOUS: Makefile
    16662833
    1667 
    1668 $(addprefix $(srcdir)/, ResolvExpr/ConversionCost.cc ResolvExpr/CommonType.cc SymTab/ManglerCommon.cc) : $(srcdir)/SynTree/Type.h
    1669 
    1670 $(srcdir)/AST/Type.hpp : BasicTypes-gen.cc
    1671         ${AM_V_GEN}${CXXCOMPILE} $< -o BasicTypes-gen -Wall -Wextra
    1672         @./BasicTypes-gen
    1673         @rm BasicTypes-gen
    16742834
    16752835# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • src/Parser/DeclarationNode.cc

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 25 22:17:10 2019
    13 // Update Count     : 1116
     12// Last Modified On : Thu Jun  7 12:08:55 2018
     13// Update Count     : 1079
    1414//
    1515
     
    4141
    4242// These must harmonize with the corresponding DeclarationNode enumerations.
    43 const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "int128",
    44                                                                                                    "float", "double", "long double", "float80", "float128",
    45                                                                                                    "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" };
    46 const char * DeclarationNode::complexTypeNames[] = { "_Complex", "NoComplexTypeNames", "_Imaginary" }; // Imaginary unsupported => parse, but make invisible and print error message
     43const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "float", "double", "long double", "int128", "float80", "float128", "NoBasicTypeNames" };
     44const char * DeclarationNode::complexTypeNames[] = { "_Complex", "_Imaginary", "NoComplexTypeNames" };
    4745const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" };
    4846const char * DeclarationNode::lengthNames[] = { "short", "long", "long long", "NoLengthNames" };
    4947const char * DeclarationNode::aggregateNames[] = { "struct", "union", "trait", "coroutine", "monitor", "thread", "NoAggregateNames" };
    5048const char * DeclarationNode::typeClassNames[] = { "otype", "dtype", "ftype", "NoTypeClassNames" };
    51 const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" };
     49const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "zero_t", "one_t", "NoBuiltinTypeNames" };
    5250
    5351UniqueName DeclarationNode::anonymous( "__anonymous" );
     
    5654
    5755DeclarationNode::DeclarationNode() :
    58         linkage( ::linkage ) {
     56                builtin( NoBuiltinType ),
     57                type( nullptr ),
     58                bitfieldWidth( nullptr ),
     59                hasEllipsis( false ),
     60                linkage( ::linkage ),
     61                asmName( nullptr ),
     62                initializer( nullptr ),
     63                extension( false ),
     64                asmStmt( nullptr ) {
    5965
    6066//      variable.name = nullptr;
     
    98104        newnode->builtin = NoBuiltinType;
    99105        newnode->type = maybeClone( type );
    100         newnode->inLine = inLine;
    101106        newnode->storageClasses = storageClasses;
    102107        newnode->funcSpecs = funcSpecs;
     
    126131} // DeclarationNode::clone
    127132
    128 void DeclarationNode::print( std::ostream & os, int indent ) const {
     133void DeclarationNode::print( std::ostream &os, int indent ) const {
    129134        os << string( indent, ' ' );
    130135        if ( name ) {
     
    162167}
    163168
    164 void DeclarationNode::printList( std::ostream & os, int indent ) const {
     169void DeclarationNode::printList( std::ostream &os, int indent ) const {
    165170        ParseNode::printList( os, indent );
    166171        if ( hasEllipsis ) {
     
    249254} // DeclarationNode::newFromTypedef
    250255
    251 DeclarationNode * DeclarationNode::newFromGlobalScope() {
    252         DeclarationNode * newnode = new DeclarationNode;
    253         newnode->type = new TypeData( TypeData::GlobalScope );
    254         return newnode;
    255 }
    256 
    257 DeclarationNode * DeclarationNode::newQualifiedType( DeclarationNode * parent, DeclarationNode * child) {
    258         DeclarationNode * newnode = new DeclarationNode;
    259         newnode->type = new TypeData( TypeData::Qualified );
    260         newnode->type->qualified.parent = parent->type;
    261         newnode->type->qualified.child = child->type;
    262         parent->type = nullptr;
    263         child->type = nullptr;
    264         delete parent;
    265         delete child;
    266         return newnode;
    267 }
    268 
    269256DeclarationNode * DeclarationNode::newAggregate( Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
     257        assert( name );
    270258        DeclarationNode * newnode = new DeclarationNode;
    271259        newnode->type = new TypeData( TypeData::Aggregate );
    272260        newnode->type->aggregate.kind = kind;
    273         newnode->type->aggregate.name =  name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
     261        newnode->type->aggregate.name = name;
    274262        newnode->type->aggregate.actuals = actuals;
    275263        newnode->type->aggregate.fields = fields;
     
    277265        newnode->type->aggregate.tagged = false;
    278266        newnode->type->aggregate.parent = nullptr;
    279         newnode->type->aggregate.anon = name == nullptr;
    280267        return newnode;
    281268} // DeclarationNode::newAggregate
    282269
    283270DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body ) {
     271        assert( name );
    284272        DeclarationNode * newnode = new DeclarationNode;
    285273        newnode->type = new TypeData( TypeData::Enum );
    286         newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
     274        newnode->type->enumeration.name = name;
    287275        newnode->type->enumeration.constants = constants;
    288276        newnode->type->enumeration.body = body;
    289         newnode->type->enumeration.anon = name == nullptr;
    290277        return newnode;
    291278} // DeclarationNode::newEnum
     
    404391}
    405392
    406 DeclarationNode * DeclarationNode::newTypeof( ExpressionNode * expr, bool basetypeof ) {
    407         DeclarationNode * newnode = new DeclarationNode;
    408         newnode->type = new TypeData( basetypeof ? TypeData::Basetypeof : TypeData::Typeof );
     393DeclarationNode * DeclarationNode::newTypeof( ExpressionNode * expr ) {
     394        DeclarationNode * newnode = new DeclarationNode;
     395        newnode->type = new TypeData( TypeData::Typeof );
    409396        newnode->type->typeexpr = expr;
    410397        return newnode;
     
    418405        return newnode;
    419406} // DeclarationNode::newBuiltinType
     407
     408DeclarationNode * DeclarationNode::newAttr( const string * name, ExpressionNode * expr ) {
     409        DeclarationNode * newnode = new DeclarationNode;
     410        newnode->type = nullptr;
     411//      newnode->attr.name = name;
     412        newnode->name = name;
     413        newnode->attr.expr = expr;
     414        return newnode;
     415}
     416
     417DeclarationNode * DeclarationNode::newAttr( const string * name, DeclarationNode * type ) {
     418        DeclarationNode * newnode = new DeclarationNode;
     419        newnode->type = nullptr;
     420//      newnode->attr.name = name;
     421        newnode->name = name;
     422        newnode->attr.type = type;
     423        return newnode;
     424}
    420425
    421426DeclarationNode * DeclarationNode::newAttribute( const string * name, ExpressionNode * expr ) {
     
    498503} // DeclarationNode::copySpecifiers
    499504
    500 static void addQualifiersToType( TypeData *& src, TypeData * dst ) {
     505static void addQualifiersToType( TypeData *&src, TypeData * dst ) {
     506        if ( src->forall && dst->kind == TypeData::Function ) {
     507                if ( dst->forall ) {
     508                        dst->forall->appendList( src->forall );
     509                } else {
     510                        dst->forall = src->forall;
     511                } // if
     512                src->forall = nullptr;
     513        } // if
    501514        if ( dst->base ) {
    502515                addQualifiersToType( src, dst->base );
     
    551564} // addQualifiers
    552565
    553 static void addTypeToType( TypeData *& src, TypeData *& dst ) {
     566static void addTypeToType( TypeData *&src, TypeData *&dst ) {
    554567        if ( src->forall && dst->kind == TypeData::Function ) {
    555568                if ( dst->forall ) {
     
    942955}
    943956
    944 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) {
     957void buildList( const DeclarationNode * firstNode, std::list< Declaration * > &outputList ) {
    945958        SemanticErrorException errors;
    946959        std::back_insert_iterator< std::list< Declaration * > > out( outputList );
     
    948961        for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
    949962                try {
    950                         bool extracted = false;
    951                         bool anon = false;
    952963                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    953964                                // handle the case where a structure declaration is contained within an object or type declaration
    954965                                Declaration * decl = extr->build();
    955966                                if ( decl ) {
    956                                         // hoist the structure declaration
    957967                                        decl->location = cur->location;
    958968                                        * out++ = decl;
    959 
    960                                         // need to remember the cases where a declaration contains an anonymous aggregate definition
    961                                         extracted = true;
    962                                         assert( extr->type );
    963                                         if ( extr->type->kind == TypeData::Aggregate ) {
    964                                                 anon = extr->type->aggregate.anon;
    965                                         } else if ( extr->type->kind == TypeData::Enum ) {
    966                                                 // xxx - is it useful to have an implicit anonymous enum member?
    967                                                 anon = extr->type->enumeration.anon;
    968                                         }
    969969                                } // if
    970970                                delete extr;
     
    973973                        Declaration * decl = cur->build();
    974974                        if ( decl ) {
    975                                 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.:
    976                                 // struct S {
    977                                 //   struct T { int x; }; // no anonymous member
    978                                 //   struct { int y; };   // anonymous member
    979                                 //   struct T;            // anonymous member
    980                                 // };
    981                                 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) {
    982                                         if ( decl->name == "" ) {
    983                                                 if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>( decl ) ) {
    984                                                         if ( ReferenceToType * aggr = dynamic_cast<ReferenceToType *>( dwt->get_type() ) ) {
    985                                                                 if ( aggr->name.find("anonymous") == std::string::npos ) {
    986                                                                         if ( ! cur->get_inLine() ) {
    987                                                                                 // temporary: warn about anonymous member declarations of named types, since
    988                                                                                 // this conflicts with the syntax for the forward declaration of an anonymous type
    989                                                                                 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() );
    990                                                                         } // if
    991                                                                 } // if
    992                                                         } // if
    993                                                 } // if
    994                                         } // if
    995                                         decl->location = cur->location;
    996                                         *out++ = decl;
     975                                decl->location = cur->location;
     976                                * out++ = decl;
     977                        } // if
     978                } catch( SemanticErrorException &e ) {
     979                        errors.append( e );
     980                } // try
     981        } // while
     982
     983        if ( ! errors.isEmpty() ) {
     984                throw errors;
     985        } // if
     986} // buildList
     987
     988void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > &outputList ) {
     989        SemanticErrorException errors;
     990        std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );
     991
     992        for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
     993                try {
     994                        Declaration * decl = cur->build();
     995                        if ( decl ) {
     996                                if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
     997                                        dwt->location = cur->location;
     998                                        * out++ = dwt;
     999                                } else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
     1000                                        StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->get_name() );
     1001                                        auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
     1002                                        obj->location = cur->location;
     1003                                        * out++ = obj;
     1004                                        delete agg;
     1005                                } else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
     1006                                        UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->get_name() );
     1007                                        auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
     1008                                        obj->location = cur->location;
     1009                                        * out++ = obj;
    9971010                                } // if
    9981011                        } // if
    999                 } catch( SemanticErrorException & e ) {
     1012                } catch( SemanticErrorException &e ) {
    10001013                        errors.append( e );
    10011014                } // try
     
    10071020} // buildList
    10081021
    1009 // currently only builds assertions, function parameters, and return values
    1010 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList ) {
    1011         SemanticErrorException errors;
    1012         std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );
    1013 
    1014         for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
    1015                 try {
    1016                         Declaration * decl = cur->build();
    1017                         assert( decl );
    1018                         if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    1019                                 dwt->location = cur->location;
    1020                                 * out++ = dwt;
    1021                         } else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
    1022                                 // e.g., int foo(struct S) {}
    1023                                 StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->name );
    1024                                 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    1025                                 obj->location = cur->location;
    1026                                 * out++ = obj;
    1027                                 delete agg;
    1028                         } else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
    1029                                 // e.g., int foo(union U) {}
    1030                                 UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->name );
    1031                                 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    1032                                 obj->location = cur->location;
    1033                                 * out++ = obj;
    1034                         } else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) {
    1035                                 // e.g., int foo(enum E) {}
    1036                                 EnumInstType * inst = new EnumInstType( Type::Qualifiers(), agg->name );
    1037                                 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    1038                                 obj->location = cur->location;
    1039                                 * out++ = obj;
    1040                         } // if
    1041                 } catch( SemanticErrorException & e ) {
    1042                         errors.append( e );
    1043                 } // try
    1044         } // for
    1045 
    1046         if ( ! errors.isEmpty() ) {
    1047                 throw errors;
    1048         } // if
    1049 } // buildList
    1050 
    1051 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) {
     1022void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > &outputList ) {
    10521023        SemanticErrorException errors;
    10531024        std::back_insert_iterator< std::list< Type * > > out( outputList );
     
    10571028                try {
    10581029                        * out++ = cur->buildType();
    1059                 } catch( SemanticErrorException & e ) {
     1030                } catch( SemanticErrorException &e ) {
    10601031                        errors.append( e );
    10611032                } // try
     
    10931064                if ( type->kind != TypeData::Function && funcSpecs.any() ) {
    10941065                        SemanticError( this, "invalid function specifier for " );
    1095                 } // if
    1096                 // Forall qualifier can only appear on a function/aggregate definition/declaration.
    1097                 //
    1098                 //    forall int f();                                   // allowed
    1099                 //    forall int g( int i );                    // allowed
    1100                 //    forall int i;                                             // disallowed
    1101                 if ( type->kind != TypeData::Function && type->forall ) {
    1102                         SemanticError( this, "invalid type qualifier for " );
    11031066                } // if
    11041067                bool isDelete = initializer && initializer->get_isDelete();
  • src/Parser/ExpressionNode.cc

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  4 20:57:55 2019
    13 // Update Count     : 978
     12// Last Modified On : Mon Jun  4 21:24:45 2018
     13// Update Count     : 802
    1414//
    1515
     
    5151extern const Type::Qualifiers noQualifiers;                             // no qualifiers on constants
    5252
    53 // static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
    54 // static inline bool checkZ( char c ) { return c == 'z' || c == 'Z'; }
    55 // static inline bool checkU( char c ) { return c == 'u' || c == 'U'; }
     53static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
     54static inline bool checkL( char c ) { return c == 'l' || c == 'L'; }
     55static inline bool checkZ( char c ) { return c == 'z' || c == 'Z'; }
     56static inline bool checkU( char c ) { return c == 'u' || c == 'U'; }
    5657static inline bool checkF( char c ) { return c == 'f' || c == 'F'; }
    5758static inline bool checkD( char c ) { return c == 'd' || c == 'D'; }
    58 static inline bool checkF80( char c ) { return c == 'w' || c == 'W'; }
    59 static inline bool checkF128( char c ) { return c == 'q' || c == 'Q'; }
    60 static inline bool checkL( char c ) { return c == 'l' || c == 'L'; }
    6159static inline bool checkI( char c ) { return c == 'i' || c == 'I'; }
    6260static inline bool checkB( char c ) { return c == 'b' || c == 'B'; }
    6361static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
    64 // static inline bool checkN( char c ) { return c == 'n' || c == 'N'; }
    65 
    66 void lnthSuffix( string & str, int & type, int & ltype ) {
    67         string::size_type posn = str.find_last_of( "lL" );
    68 
    69         if ( posn == string::npos ) return;                                     // no suffix
    70         if ( posn == str.length() - 1 ) { type = 3; return; } // no length => long
    71 
    72         string::size_type next = posn + 1;                                      // advance to length
    73         if ( str[next] == '3' ) {                                                       // 32
    74                 type = ltype = 2;
    75         } else if ( str[next] == '6' ) {                                        // 64
    76                 type = ltype = 3;
    77         } else if ( str[next] == '8' ) {                                        // 8
    78                 type = ltype = 1;
    79         } else if ( str[next] == '1' ) {
    80                 if ( str[next + 1] == '6' ) {                                   // 16
    81                         type = ltype = 0;
     62
     63static const char * lnthsInt[2][6] = {
     64        { "int8_t", "int16_t", "int32_t", "int64_t", "size_t", },
     65        { "uint8_t", "uint16_t", "uint32_t", "uint64_t", "size_t", }
     66}; // lnthsInt
     67
     68static inline void checkLNInt( string & str, int & lnth, int & size ) {
     69        string::size_type posn = str.find_first_of( "lL" ), start = posn;
     70  if ( posn == string::npos ) return;
     71        size = 4;                                                                                       // assume largest size
     72        posn += 1;                                                                                      // advance to size
     73        if ( str[posn] == '8' ) {                                                       // 8
     74                lnth = 0;
     75        } else if ( str[posn] == '1' ) {
     76                posn += 1;
     77                if ( str[posn] == '6' ) {                                               // 16
     78                        lnth = 1;
    8279                } else {                                                                                // 128
    83                         type = 5; ltype = 6;
    84                 } // if
    85         } // if
    86         // remove "lL" for these cases because it may not imply long
    87         str.erase( posn );                                                                      // remove length
    88 } // lnthSuffix
    89 
    90 void valueToType( unsigned long long int & v, bool dec, int & type, bool & Unsigned ) {
    91         // use value to determine type
    92         if ( v <= INT_MAX ) {                                                           // signed int
    93                 type = 2;
    94         } else if ( v <= UINT_MAX && ! dec ) {                          // unsigned int
    95                 type = 2;
    96                 Unsigned = true;                                                                // unsigned
    97         } else if ( v <= LONG_MAX ) {                                           // signed long int
    98                 type = 3;
    99         } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int
    100                 type = 3;
    101                 Unsigned = true;                                                                // unsigned long int
    102         } else if ( v <= LLONG_MAX ) {                                          // signed long long int
    103                 type = 4;
    104         } else {                                                                                        // unsigned long long int
    105                 type = 4;
    106                 Unsigned = true;                                                                // unsigned long long int
    107         } // if
    108 } // valueToType
     80                        posn += 1;
     81                        lnth = 5;
     82                } // if
     83        } else {
     84                if ( str[posn] == '3' ) {                                               // 32
     85                        lnth = 2;
     86                } else if ( str[posn] == '6' ) {                                // 64
     87                        lnth = 3;
     88                } else {
     89                        assertf( false, "internal error, bad integral length %s", str.c_str() );
     90                } // if
     91                posn += 1;
     92        } // if
     93        str.erase( start, posn - start + 1 );                           // remove length suffix
     94} // checkLNInt
    10995
    11096Expression * build_constantInteger( string & str ) {
    11197        static const BasicType::Kind kind[2][6] = {
    112                 // short (h) must be before char (hh) because shorter type has the longer suffix
     98                // short (h) must be before char (hh)
    11399                { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },
    114100                { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt128, },
    115101        };
    116102
    117         static const char * lnthsInt[2][6] = {
    118                 { "int16_t",  "int8_t",  "int32_t",  "int64_t",  "size_t",  "uintptr_t", },
    119                 { "uint16_t", "uint8_t", "uint32_t", "uint64_t", "size_t",  "uintptr_t", },
    120         }; // lnthsInt
     103        bool dec = true, Unsigned = false;                                      // decimal, unsigned constant
     104        int size;                                                                                       // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     105        int lnth = -1;                                                                          // literal length
    121106
    122107        unsigned long long int v;                                                       // converted integral value
    123108        size_t last = str.length() - 1;                                         // last subscript of constant
    124109        Expression * ret;
    125         //string fred( str );
    126 
    127         int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
    128         int ltype = -1;                                                                         // 0 => 16 bits, 1 => 8 bits, 2 => 32 bits, 3 => 64 bits, 4 => size_t, 5 => intptr, 6 => pointer
    129         bool dec = true, Unsigned = false;                                      // decimal, unsigned constant
    130110
    131111        // special constants
     
    139119        } // if
    140120
    141         // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
     121        // Cannot be "0"
    142122
    143123        if ( str[0] == '0' ) {                                                          // radix character ?
     
    147127                        //printf( "%llx %llu\n", v, v );
    148128                } else if ( checkB( str[1] ) ) {                                // binary constant ?
    149                         v = 0;                                                                          // compute value
    150                         for ( unsigned int i = 2;; ) {                          // ignore prefix
     129                        v = 0;
     130                        for ( unsigned int i = 2;; i += 1 ) {           // compute value
    151131                                if ( str[i] == '1' ) v |= 1;
    152                                 i += 1;
    153                           if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
     132                          if ( i == last ) break;
    154133                                v <<= 1;
    155134                        } // for
    156                         //printf( "%#llx %llu\n", v, v );
     135                        //printf( "%llx %llu\n", v, v );
    157136                } else {                                                                                // octal constant
    158137                        sscanf( (char *)str.c_str(), "%llo", &v );
    159                         //printf( "%#llo %llu\n", v, v );
     138                        //printf( "%llo %llu\n", v, v );
    160139                } // if
    161140        } else {                                                                                        // decimal constant ?
    162141                sscanf( (char *)str.c_str(), "%llu", &v );
    163                 //printf( "%llu\n", v );
    164         } // if
    165 
    166         string::size_type posn;
    167 
    168         if ( isdigit( str[last] ) ) {                                           // no suffix ?
    169                 lnthSuffix( str, type, ltype );                                 // could have length suffix
    170                 if ( type == -1 ) {                                                             // no suffix
    171                         valueToType( v, dec, type, Unsigned );
    172                 } // if
    173         } else {
    174                 // At least one digit in integer constant, so safe to backup while looking for suffix.
    175 
    176                 posn = str.find_last_of( "pP" );
    177                 if ( posn != string::npos ) { valueToType( v, dec, type, Unsigned ); ltype = 5; str.erase( posn, 1 ); goto FINI; }
    178 
    179                 posn = str.find_last_of( "zZ" );
    180                 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
    181 
    182                 // 'u' can appear before or after length suffix
    183                 if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
    184 
    185                 posn = str.rfind( "hh" );
    186                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    187 
    188                 posn = str.rfind( "HH" );
    189                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    190 
    191                 posn = str.find_last_of( "hH" );
    192                 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; }
    193 
    194                 posn = str.find_last_of( "nN" );
    195                 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
    196 
    197                 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
    198 
    199                 lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
    200                 if ( type == -1 ) {                                                             // only 'u' suffix ?
    201                         valueToType( v, dec, type, Unsigned );
    202                 } // if
    203           FINI: ;
    204         } // if
    205 
    206         //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
    207         assert( 0 <= type && type <= 6 );
    208 
     142                //printf( "%llu %llu\n", v, v );
     143        } // if
     144
     145        if ( v <= INT_MAX ) {                                                           // signed int
     146                size = 2;
     147        } else if ( v <= UINT_MAX && ! dec ) {                          // unsigned int
     148                size = 2;
     149                Unsigned = true;                                                                // unsigned
     150        } else if ( v <= LONG_MAX ) {                                           // signed long int
     151                size = 3;
     152        } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int
     153                size = 3;
     154                Unsigned = true;                                                                // unsigned long int
     155        } else if ( v <= LLONG_MAX ) {                                          // signed long long int
     156                size = 4;
     157        } else {                                                                                        // unsigned long long int
     158                size = 4;
     159                Unsigned = true;                                                                // unsigned long long int
     160        } // if
     161
     162        // At least one digit in integer constant, so safe to backup while looking for suffix.
     163
     164        if ( checkU( str[last] ) ) {                                            // suffix 'u' ?
     165                Unsigned = true;
     166                if ( checkL( str[last - 1] ) ) {                                // suffix 'l' ?
     167                        size = 3;
     168                        if ( checkL( str[last - 2] ) ) {                        // suffix "ll" ?
     169                                size = 4;
     170                        } // if
     171                } else if ( checkH( str[last - 1] ) ) {                 // suffix 'h' ?
     172                        size = 0;
     173                        if ( checkH( str[last - 2] ) ) {                        // suffix "hh" ?
     174                                size = 1;
     175                        } // if
     176                        str.erase( last - size - 1, size + 1 );         // remove 'h'/"hh"
     177                } else {                                                                                // suffix "ln" ?
     178                        checkLNInt( str, lnth, size );
     179                } // if
     180        } else if ( checkL( str[ last ] ) ) {                           // suffix 'l' ?
     181                size = 3;
     182                if ( checkL( str[last - 1] ) ) {                                // suffix 'll' ?
     183                        size = 4;
     184                        if ( checkU( str[last - 2] ) ) {                        // suffix 'u' ?
     185                                Unsigned = true;
     186                        } // if
     187                } else if ( checkU( str[last - 1] ) ) {                 // suffix 'u' ?
     188                        Unsigned = true;
     189                } // if
     190        } else if ( checkH( str[ last ] ) ) {                           // suffix 'h' ?
     191                size = 0;
     192                if ( checkH( str[last - 1] ) ) {                                // suffix "hh" ?
     193                        size = 1;
     194                        if ( checkU( str[last - 2] ) ) {                        // suffix 'u' ?
     195                                Unsigned = true;
     196                        } // if
     197                } else if ( checkU( str[last - 1] ) ) {                 // suffix 'u' ?
     198                        Unsigned = true;
     199                } // if
     200                str.erase( last - size, size + 1 );                             // remove 'h'/"hh"
     201        } else if ( checkZ( str[last] ) ) {                                     // suffix 'z' ?
     202                lnth = 4;
     203                str.erase( last, 1 );                                                   // remove 'z'
     204        } else {                                                                                        // suffix "ln" ?
     205                checkLNInt( str, lnth, size );
     206        } // if
     207
     208        assert( 0 <= size && size < 6 );
    209209        // Constant type is correct for overload resolving.
    210         ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][type] ), str, v ) );
    211         if ( Unsigned && type < 2 ) {                                           // hh or h, less than int ?
     210        ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][size] ), str, v ) );
     211        if ( Unsigned && size < 2 ) {                                           // hh or h, less than int ?
    212212                // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
    213                 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
    214         } else if ( ltype != -1 ) {                                                     // explicit length ?
    215                 if ( ltype == 6 ) {                                                             // int128, (int128)constant
    216                         ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
    217                 } else {                                                                                // explicit length, (length_type)constant
    218                         ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
    219                         if ( ltype == 5 ) {                                                     // pointer, intptr( (uintptr_t)constant )
    220                                 ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) );
    221                         } // if
    222                 } // if
    223         } // if
    224 
    225   CLEANUP: ;
     213                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][size] ), false );
     214        } else if ( lnth != -1 ) {                                                      // explicit length ?
     215                if ( lnth == 5 ) {                                                              // int128 ?
     216                        size = 5;
     217                        ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][size] ), false );
     218                } else {
     219                        ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][lnth], false ), false );
     220                } // if
     221        } // if
     222  CLEANUP:
     223
    226224        delete &str;                                                                            // created by lex
    227225        return ret;
     
    229227
    230228
    231 static inline void checkFnxFloat( string & str, size_t last, bool & explnth, int & type ) {
    232         string::size_type posn;
    233         // floating-point constant has minimum of 2 characters, 1. or .1, so safe to look ahead
    234         if ( str[1] == 'x' ) {                                                          // hex ?
    235                 posn = str.find_last_of( "pP" );                                // back for exponent (must have)
    236                 posn = str.find_first_of( "fF", posn + 1 );             // forward for size (fF allowed in hex constant)
    237         } else {
    238                 posn = str.find_last_of( "fF" );                                // back for size (fF not allowed)
    239         } // if
     229static inline void checkLNFloat( string & str, int & lnth, int & size ) {
     230        string::size_type posn = str.find_first_of( "lL" ), start = posn;
    240231  if ( posn == string::npos ) return;
    241         explnth = true;
     232        size = 2;                                                                                       // assume largest size
     233        lnth = 0;
    242234        posn += 1;                                                                                      // advance to size
    243235        if ( str[posn] == '3' ) {                                                       // 32
    244                 if ( str[last] != 'x' ) type = 6;
    245                 else type = 7;
     236                size = 0;
    246237        } else if ( str[posn] == '6' ) {                                        // 64
    247                 if ( str[last] != 'x' ) type = 8;
    248                 else type = 9;
    249         } else if ( str[posn] == '8' ) {                                        // 80
    250                 type = 3;
    251         } else if ( str[posn] == '1' ) {                                        // 16/128
    252                 if ( str[posn + 1] == '6' ) {                                   // 16
    253                         type = 5;
    254                 } else {                                                                                // 128
    255                         if ( str[last] != 'x' ) type = 10;
    256                         else type = 11;
    257                 } // if
     238                size = 1;
     239        } else if ( str[posn] == '8' || str[posn] == '1' ) { // 80, 128
     240                size = 2;
     241                if ( str[posn] == '1' ) posn += 1;
    258242        } else {
    259243                assertf( false, "internal error, bad floating point length %s", str.c_str() );
    260244        } // if
    261 } // checkFnxFloat
     245        posn += 1;
     246        str.erase( start, posn - start + 1 );                           // remove length suffix
     247} // checkLNFloat
    262248
    263249
    264250Expression * build_constantFloat( string & str ) {
    265         static const BasicType::Kind kind[2][12] = {
    266                 { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x },
    267                 { 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 },
     251        static const BasicType::Kind kind[2][3] = {
     252                { BasicType::Float, BasicType::Double, BasicType::LongDouble },
     253                { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex },
    268254        };
    269255
    270         // floating-point constant has minimum of 2 characters 1. or .1
     256        bool complx = false;                                                            // real, complex
     257        int size = 1;                                                                           // 0 => float, 1 => double, 2 => long double
     258        int lnth = -1;                                                                          // literal length
     259        // floating-point constant has minimum of 2 characters: 1. or .1
    271260        size_t last = str.length() - 1;
    272261        double v;
    273         int type;                                                                                       // 0 => float, 1 => double, 3 => long double, ...
    274         bool complx = false;                                                            // real, complex
    275         bool explnth = false;                                                           // explicit literal length
    276262
    277263        sscanf( str.c_str(), "%lg", &v );
     
    283269
    284270        if ( checkF( str[last] ) ) {                                            // float ?
    285                 type = 0;
     271                size = 0;
    286272        } else if ( checkD( str[last] ) ) {                                     // double ?
    287                 type = 1;
     273                size = 1;
    288274        } else if ( checkL( str[last] ) ) {                                     // long double ?
    289                 type = 2;
    290         } else if ( checkF80( str[last] ) ) {                           // __float80 ?
    291                 type = 3;
    292         } else if ( checkF128( str[last] ) ) {                          // __float128 ?
    293                 type = 4;
     275                size = 2;
    294276        } else {
    295                 type = 1;                                                                               // double (default if no suffix)
    296                 checkFnxFloat( str, last, explnth, type );
    297         } // if
    298 
     277                size = 1;                                                                               // double (default)
     278                checkLNFloat( str, lnth, size );
     279        } // if
    299280        if ( ! complx && checkI( str[last - 1] ) ) {            // imaginary ?
    300281                complx = true;
    301282        } // if
    302283
    303         assert( 0 <= type && type < 12 );
    304         Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][type] ), str, v ) );
    305         if ( explnth ) {                                                                        // explicit length ?
    306                 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][type] ), false );
     284        assert( 0 <= size && size < 3 );
     285        Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][size] ), str, v ) );
     286        if ( lnth != -1 ) {                                                                     // explicit length ?
     287                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][size] ), false );
    307288        } // if
    308289
     
    357338                                                                        new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
    358339                                                                        false, false );
    359         Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) );
     340        Expression * ret = new ConstantExpr( Constant( at, str, (unsigned long long int)0 ) ); // constant 0 is ignored for pure string value
    360341        if ( units.length() != 0 ) {
    361342                ret = new UntypedExpr( new NameExpr( units ), { ret } );
  • src/Parser/LinkageSpec.cc

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 13:22:09 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Spt 12 15:59:00 2018
    13 // Update Count     : 26
     12// Last Modified On : Fri Jul  7 11:11:00 2017
     13// Update Count     : 25
    1414//
    1515
     
    2323
    2424namespace LinkageSpec {
     25
     26Spec linkageCheck( CodeLocation location, const string * spec ) {
     27        assert( spec );
     28        unique_ptr<const string> guard( spec ); // allocated by lexer
     29        if ( *spec == "\"Cforall\"" ) {
     30                return Cforall;
     31        } else if ( *spec == "\"C\"" ) {
     32                return C;
     33        } else if ( *spec == "\"BuiltinC\"" ) {
     34                return BuiltinC;
     35        } else {
     36                SemanticError( location, "Invalid linkage specifier " + *spec );
     37        } // if
     38}
    2539
    2640Spec linkageUpdate( CodeLocation location, Spec old_spec, const string * cmd ) {
  • src/Parser/LinkageSpec.h

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 13:24:28 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 10 16:02:34 2019
    13 // Update Count     : 18
     12// Last Modified On : Sat Jul 22 09:32:16 2017
     13// Update Count     : 14
    1414//
    1515
     
    2222namespace LinkageSpec {
    2323        // All linkage specs are some combination of these flags:
    24         enum { Mangle = 1 << 0, Generate = 1 << 1, Overrideable = 1 << 2, Builtin = 1 << 3, GccBuiltin = 1 << 4, NoOfSpecs = 1 << 5, };
     24        enum {
     25                Mangle = 1 << 0,
     26                Generate = 1 << 1,
     27                Overrideable = 1 << 2,
     28                Builtin = 1 << 3,
     29                GccBuiltin = 1 << 4,
     30
     31                NoOfSpecs = 1 << 5,
     32        };
    2533
    2634        union Spec {
     
    3442                };
    3543                constexpr Spec( unsigned int val ) : val( val ) {}
    36                 constexpr Spec( Spec const & other ) : val( other.val ) {}
    37                 constexpr Spec & operator=( const Spec & ) = default;
     44                constexpr Spec( Spec const &other ) : val( other.val ) {}
    3845                // Operators may go here.
    3946                // Supports == and !=
    40                 constexpr operator unsigned int() const { return val; }
     47                constexpr operator unsigned int () const { return val; }
    4148        };
    4249
    4350
     51        Spec linkageCheck( CodeLocation location, const std::string * );
     52        // Returns the Spec with the given name (limited to C, Cforall & BuiltinC)
    4453        Spec linkageUpdate( CodeLocation location, Spec old_spec, const std::string * cmd );
    4554        /* If cmd = "C" returns a Spec that is old_spec with is_mangled = false
  • src/Parser/ParseNode.h

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 25 22:17:10 2019
    13 // Update Count     : 876
     12// Last Modified On : Wed Jun  6 16:17:18 2018
     13// Update Count     : 843
    1414//
    1515
     
    6868        }
    6969
    70         virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
    71         virtual void printList( std::ostream & os, int indent = 0 ) const {
     70        virtual void print( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const {}
     71        virtual void printList( std::ostream &os, int indent = 0 ) const {
    7272                print( os, indent );
    7373                if ( next ) next->print( os, indent );
     
    103103        InitializerNode * next_init() const { return kids; }
    104104
    105         void print( std::ostream & os, int indent = 0 ) const;
     105        void print( std::ostream &os, int indent = 0 ) const;
    106106        void printOneLine( std::ostream & ) const;
    107107
     
    127127        ExpressionNode * set_extension( bool exten ) { extension = exten; return this; }
    128128
    129         virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {
    130                 os << expr.get();
    131         }
    132         void printOneLine( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
     129        virtual void print( std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {
     130                os << expr.get() << std::endl;
     131        }
     132        void printOneLine( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const {}
    133133
    134134        template<typename T>
     
    136136
    137137        Expression * build() const { return const_cast<ExpressionNode *>(this)->expr.release(); }
    138 
    139         std::unique_ptr<Expression> expr;                                       // public because of lifetime implications
    140138  private:
    141139        bool extension = false;
     140        std::unique_ptr<Expression> expr;
    142141}; // ExpressionNode
    143142
     
    206205class DeclarationNode : public ParseNode {
    207206  public:
    208         // These enumerations must harmonize with their names in DeclarationNode.cc.
    209         enum BasicType { Void, Bool, Char, Int, Int128,
    210                                          Float, Double, LongDouble, uuFloat80, uuFloat128,
    211                                          uFloat16, uFloat32, uFloat32x, uFloat64, uFloat64x, uFloat128, uFloat128x, NoBasicType };
     207        // These enumerations must harmonize with their names.
     208        enum BasicType { Void, Bool, Char, Int, Float, Double, LongDouble, Int128, Float80, Float128, NoBasicType };
    212209        static const char * basicTypeNames[];
    213         enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message
     210        enum ComplexType { Complex, Imaginary, NoComplexType };
    214211        static const char * complexTypeNames[];
    215212        enum Signedness { Signed, Unsigned, NoSignedness };
     
    221218        enum TypeClass { Otype, Dtype, Ftype, Ttype, NoTypeClass };
    222219        static const char * typeClassNames[];
    223         enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };
     220        enum BuiltinType { Valist, Zero, One, NoBuiltinType };
    224221        static const char * builtinTypeNames[];
    225222
     
    234231        static DeclarationNode * newForall( DeclarationNode * );
    235232        static DeclarationNode * newFromTypedef( const std::string * );
    236         static DeclarationNode * newFromGlobalScope();
    237         static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );
    238233        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    239234        static DeclarationNode * newAggregate( Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
     
    251246        static DeclarationNode * newBitfield( ExpressionNode * size );
    252247        static DeclarationNode * newTuple( DeclarationNode * members );
    253         static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );
     248        static DeclarationNode * newTypeof( ExpressionNode * expr );
     249        static DeclarationNode * newAttr( const std::string *, ExpressionNode * expr ); // @ attributes
     250        static DeclarationNode * newAttr( const std::string *, DeclarationNode * type ); // @ attributes
    254251        static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    255252        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
     
    291288        }
    292289
    293         virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
    294         virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
     290        virtual void print( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const override;
     291        virtual void printList( __attribute__((unused)) std::ostream &os, __attribute__((unused)) int indent = 0 ) const override;
    295292
    296293        Declaration * build() const;
     
    304301        bool get_extension() const { return extension; }
    305302        DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }
    306 
    307         bool get_inLine() const { return inLine; }
    308         DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }
    309303  public:
    310304        DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
     
    331325        StaticAssert_t assert;
    332326
    333         BuiltinType builtin = NoBuiltinType;
    334 
    335         TypeData * type = nullptr;
    336 
    337         bool inLine = false;
     327        BuiltinType builtin;
     328
     329        TypeData * type;
     330
    338331        Type::FuncSpecifiers funcSpecs;
    339332        Type::StorageClasses storageClasses;
    340333
    341         ExpressionNode * bitfieldWidth = nullptr;
     334        ExpressionNode * bitfieldWidth;
    342335        std::unique_ptr<ExpressionNode> enumeratorValue;
    343         bool hasEllipsis = false;
     336        bool hasEllipsis;
    344337        LinkageSpec::Spec linkage;
    345         Expression * asmName = nullptr;
     338        Expression * asmName;
    346339        std::list< Attribute * > attributes;
    347         InitializerNode * initializer = nullptr;
     340        InitializerNode * initializer;
    348341        bool extension = false;
    349342        std::string error;
    350         StatementNode * asmStmt = nullptr;
     343        StatementNode * asmStmt;
    351344
    352345        static UniqueName anonymous;
     
    382375        virtual StatementNode * append_last_case( StatementNode * );
    383376
    384         virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {
     377        virtual void print( std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {
    385378                os << stmt.get() << std::endl;
    386379        }
     
    391384Statement * build_expr( ExpressionNode * ctl );
    392385
    393 struct IfCtrl {
    394         IfCtrl( DeclarationNode * decl, ExpressionNode * condition ) :
     386struct IfCtl {
     387        IfCtl( DeclarationNode * decl, ExpressionNode * condition ) :
    395388                init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}
    396389
     
    399392};
    400393
    401 struct ForCtrl {
    402         ForCtrl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :
     394struct ForCtl {
     395        ForCtl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :
    403396                init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {}
    404         ForCtrl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :
     397        ForCtl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :
    405398                init( new StatementNode( decl ) ), condition( condition ), change( change ) {}
    406399
     
    410403};
    411404
    412 Expression * build_if_control( IfCtrl * ctl, std::list< Statement * > & init );
    413 Statement * build_if( IfCtrl * ctl, StatementNode * then_stmt, StatementNode * else_stmt );
     405Expression * build_if_control( IfCtl * ctl, std::list< Statement * > & init );
     406Statement * build_if( IfCtl * ctl, StatementNode * then_stmt, StatementNode * else_stmt );
    414407Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
    415408Statement * build_case( ExpressionNode * ctl );
    416409Statement * build_default();
    417 Statement * build_while( IfCtrl * ctl, StatementNode * stmt );
     410Statement * build_while( IfCtl * ctl, StatementNode * stmt );
    418411Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt );
    419 Statement * build_for( ForCtrl * forctl, StatementNode * stmt );
     412Statement * build_for( ForCtl * forctl, StatementNode * stmt );
    420413Statement * build_branch( BranchStmt::Type kind );
    421414Statement * build_branch( std::string * identifier, BranchStmt::Type kind );
     
    435428WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );
    436429WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
    437 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
     430WithStmt * build_with( ExpressionNode * exprs, StatementNode * stmt );
    438431
    439432//##############################################################################
    440433
    441434template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >
    442 void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > & outputList ) {
     435void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > &outputList ) {
    443436        SemanticErrorException errors;
    444437        std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );
     
    454447                                assertf(false, "buildList unknown type");
    455448                        } // if
    456                 } catch( SemanticErrorException & e ) {
     449                } catch( SemanticErrorException &e ) {
    457450                        errors.append( e );
    458451                } // try
     
    465458
    466459// in DeclarationNode.cc
    467 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList );
    468 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList );
    469 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList );
     460void buildList( const DeclarationNode * firstNode, std::list< Declaration * > &outputList );
     461void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > &outputList );
     462void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > &outputList );
    470463
    471464template< typename SynTreeType, typename NodeType >
    472 void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > & outputList ) {
     465void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > &outputList ) {
    473466        buildList( firstNode, outputList );
    474467        delete firstNode;
  • src/Parser/StatementNode.cc

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 14:59:41 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  4 09:39:25 2018
    13 // Update Count     : 363
     12// Last Modified On : Tue Jun  5 08:58:34 2018
     13// Update Count     : 362
    1414//
    1515
     
    7878} // build_expr
    7979
    80 Expression * build_if_control( IfCtrl * ctl, std::list< Statement * > & init ) {
     80Expression * build_if_control( IfCtl * ctl, std::list< Statement * > & init ) {
    8181        if ( ctl->init != 0 ) {
    8282                buildMoveList( ctl->init, init );
     
    100100} // build_if_control
    101101
    102 Statement * build_if( IfCtrl * ctl, StatementNode * then_stmt, StatementNode * else_stmt ) {
     102Statement * build_if( IfCtl * ctl, StatementNode * then_stmt, StatementNode * else_stmt ) {
    103103        Statement * thenb, * elseb = nullptr;
    104104        std::list< Statement * > branches;
     
    145145} // build_default
    146146
    147 Statement * build_while( IfCtrl * ctl, StatementNode * stmt ) {
     147Statement * build_while( IfCtl * ctl, StatementNode * stmt ) {
    148148        std::list< Statement * > branches;
    149149        buildMoveList< Statement, StatementNode >( stmt, branches );
     
    164164} // build_do_while
    165165
    166 Statement * build_for( ForCtrl * forctl, StatementNode * stmt ) {
     166Statement * build_for( ForCtl * forctl, StatementNode * stmt ) {
    167167        std::list< Statement * > branches;
    168168        buildMoveList< Statement, StatementNode >( stmt, branches );
     
    317317} // build_waitfor_timeout
    318318
    319 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
     319WithStmt * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
    320320        std::list< Expression * > e;
    321321        buildMoveList( exprs, e );
    322322        Statement * s = maybeMoveBuild<Statement>( stmt );
    323         return new DeclStmt( new WithStmt( e, s ) );
     323        return new WithStmt( e, s );
    324324} // build_with
    325325
  • src/Parser/TypeData.cc

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 13 18:16:23 2019
    13 // Update Count     : 649
     12// Last Modified On : Wed Jun  6 17:40:33 2018
     13// Update Count     : 604
    1414//
    1515
     
    3737          case Reference:
    3838          case EnumConstant:
    39           case GlobalScope:
    4039                // nothing else to initialize
    4140                break;
     
    6362                enumeration.constants = nullptr;
    6463                enumeration.body = false;
    65                 enumeration.anon = false;
    6664                break;
    6765          case Aggregate:
     
    7573                aggregate.tagged = false;
    7674                aggregate.parent = nullptr;
    77                 aggregate.anon = false;
    7875                break;
    7976          case AggregateInst:
     
    8178                aggInst.aggregate = nullptr;
    8279                aggInst.params = nullptr;
    83                 aggInst.hoistType = false;
     80                aggInst.hoistType = false;;
    8481                break;
    8582          case Symbolic:
     
    9693                break;
    9794          case Typeof:
    98           case Basetypeof:
    9995                // typeexpr = new Typeof_t;
    10096                typeexpr = nullptr;
     
    10298          case Builtin:
    10399                // builtin = new Builtin_t;
    104                 case Qualified:
    105                 qualified.parent = nullptr;
    106                 qualified.child = nullptr;
    107100                break;
    108101        } // switch
     
    119112          case Reference:
    120113          case EnumConstant:
    121           case GlobalScope:
    122114                // nothing to destroy
    123115                break;
     
    167159                break;
    168160          case Typeof:
    169           case Basetypeof:
    170161                // delete typeexpr->expr;
    171162                delete typeexpr;
     
    174165                // delete builtin;
    175166                break;
    176           case Qualified:
    177                 delete qualified.parent;
    178                 delete qualified.child;
    179167        } // switch
    180168} // TypeData::~TypeData
     
    192180          case Pointer:
    193181          case Reference:
    194           case GlobalScope:
    195182                // nothing else to copy
    196183                break;
     
    220207                newtype->aggregate.fields = maybeClone( aggregate.fields );
    221208                newtype->aggregate.body = aggregate.body;
    222                 newtype->aggregate.anon = aggregate.anon;
    223209                newtype->aggregate.tagged = aggregate.tagged;
    224210                newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;
     
    233219                newtype->enumeration.constants = maybeClone( enumeration.constants );
    234220                newtype->enumeration.body = enumeration.body;
    235                 newtype->enumeration.anon = enumeration.anon;
    236221                break;
    237222          case Symbolic:
     
    247232                break;
    248233          case Typeof:
    249           case Basetypeof:
    250234                newtype->typeexpr = maybeClone( typeexpr );
    251235                break;
     
    253237                assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One );
    254238                newtype->builtintype = builtintype;
    255                 break;
    256                 case Qualified:
    257                 newtype->qualified.parent = maybeClone( qualified.parent );
    258                 newtype->qualified.child = maybeClone( qualified.child );
    259239                break;
    260240        } // switch
     
    274254
    275255        switch ( kind ) {
    276           case Basic:
    277                 if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " ";
    278                 if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " ";
    279                 if ( complextype == DeclarationNode::NoComplexType ) { // basic type
    280                         assert( basictype != DeclarationNode::NoBasicType );
    281                         os << DeclarationNode::basicTypeNames[ basictype ] << " ";
    282                 } else {                                                                                // complex type
    283                         // handle double _Complex
    284                         if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " ";
    285                         os << DeclarationNode::complexTypeNames[ complextype ] << " ";
    286                 } // if
     256          case Unknown:
     257                os << "entity of unknown type ";
    287258                break;
    288259          case Pointer:
     
    293264                } // if
    294265                break;
    295           case Reference:
    296                 os << "reference ";
    297                 if ( base ) {
    298                         os << "to ";
    299                         base->print( os, indent );
    300                 } // if
     266          case EnumConstant:
     267                os << "enumeration constant ";
     268                break;
     269          case Basic:
     270                if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " ";
     271                if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " ";
     272                assert( basictype != DeclarationNode::NoBasicType );
     273                os << DeclarationNode::basicTypeNames[ basictype ] << " ";
     274                if ( complextype != DeclarationNode::NoComplexType ) os << DeclarationNode::complexTypeNames[ complextype ] << " ";
    301275                break;
    302276          case Array:
     
    322296                        function.params->printList( os, indent + 4 );
    323297                } else {
    324                         os << string( indent + 2, ' ' ) << "with no parameters" << endl;
     298                        os << string( indent + 2, ' ' ) << "with no parameters " << endl;
    325299                } // if
    326300                if ( function.idList ) {
     
    347321                os << DeclarationNode::aggregateNames[ aggregate.kind ] << ' ' << *aggregate.name << endl;
    348322                if ( aggregate.params ) {
    349                         os << string( indent + 2, ' ' ) << "with type parameters" << endl;
     323                        os << string( indent + 2, ' ' ) << "with type parameters " << endl;
    350324                        aggregate.params->printList( os, indent + 4 );
    351325                } // if
    352326                if ( aggregate.actuals ) {
    353                         os << string( indent + 2, ' ' ) << "instantiated with actual parameters" << endl;
     327                        os << string( indent + 2, ' ' ) << "instantiated with actual parameters " << endl;
    354328                        aggregate.actuals->printList( os, indent + 4 );
    355329                } // if
    356330                if ( aggregate.fields ) {
    357                         os << string( indent + 2, ' ' ) << "with members" << endl;
     331                        os << string( indent + 2, ' ' ) << "with members " << endl;
    358332                        aggregate.fields->printList( os, indent + 4 );
    359333                } // if
    360334                if ( aggregate.body ) {
    361                         os << string( indent + 2, ' ' ) << " with body" << endl;
     335                        os << string( indent + 2, ' ' ) << " with body " << endl;
    362336                } // if
    363337                break;
     
    370344                } // if
    371345                if ( aggInst.params ) {
    372                         os << string( indent + 2, ' ' ) << "with parameters" << endl;
     346                        os << string( indent + 2, ' ' ) << "with parameters " << endl;
    373347                        aggInst.params->printList( os, indent + 2 );
    374348                } // if
     
    381355                } // if
    382356                if ( enumeration.body ) {
    383                         os << string( indent + 2, ' ' ) << " with body" << endl;
    384                 } // if
    385                 break;
    386           case EnumConstant:
    387                 os << "enumeration constant ";
     357                        os << string( indent + 2, ' ' ) << " with body " << endl;
     358                } // if
     359                break;
     360          case SymbolicInst:
     361                os << "instance of type " << *symbolic.name;
     362                if ( symbolic.actuals ) {
     363                        os << " with parameters" << endl;
     364                        symbolic.actuals->printList( os, indent + 2 );
     365                } // if
    388366                break;
    389367          case Symbolic:
     
    407385                } // if
    408386                break;
    409           case SymbolicInst:
    410                 os << *symbolic.name;
    411                 if ( symbolic.actuals ) {
    412                         os << "(";
    413                         symbolic.actuals->printList( os, indent + 2 );
    414                         os << ")";
    415                 } // if
    416                 break;
    417387          case Tuple:
    418388                os << "tuple ";
    419389                if ( tuple ) {
    420                         os << "with members" << endl;
     390                        os << "with members " << endl;
    421391                        tuple->printList( os, indent + 2 );
    422392                } // if
    423393                break;
    424           case Basetypeof:
    425                 os << "base-";
    426                 #if defined(__GNUC__) && __GNUC__ >= 7
    427                         __attribute__((fallthrough));
    428                 #endif
    429394          case Typeof:
    430395                os << "type-of expression ";
     
    435400          case Builtin:
    436401                os << DeclarationNode::builtinTypeNames[builtintype];
    437                 break;
    438           case GlobalScope:
    439                 break;
    440           case Qualified:
    441                 qualified.parent->print( os );
    442                 os << ".";
    443                 qualified.child->print( os );
    444                 break;
    445           case Unknown:
    446                 os << "entity of unknown type ";
    447402                break;
    448403          default:
     
    451406        } // switch
    452407} // TypeData::print
    453 
    454 const std::string * TypeData::leafName() const {
    455         switch ( kind ) {
    456           case Unknown:
    457           case Pointer:
    458           case Reference:
    459           case EnumConstant:
    460           case GlobalScope:
    461           case Array:
    462           case Basic:
    463           case Function:
    464           case AggregateInst:
    465           case Tuple:
    466           case Typeof:
    467           case Basetypeof:
    468           case Builtin:
    469                 assertf(false, "Tried to get leaf name from kind without a name: %d", kind);
    470                 break;
    471           case Aggregate:
    472                 return aggregate.name;
    473           case Enum:
    474                 return enumeration.name;
    475           case Symbolic:
    476           case SymbolicInst:
    477                 return symbolic.name;
    478           case Qualified:
    479                 return qualified.child->leafName();
    480         } // switch
    481         assert(false);
    482 }
    483408
    484409
     
    522447        switch ( td->kind ) {
    523448          case TypeData::Unknown:
    524                         // fill in implicit int
    525                         return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
     449                // fill in implicit int
     450                return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
    526451          case TypeData::Basic:
    527                         return buildBasicType( td );
     452                return buildBasicType( td );
    528453          case TypeData::Pointer:
    529                         return buildPointer( td );
     454                return buildPointer( td );
    530455          case TypeData::Array:
    531                         return buildArray( td );
     456                return buildArray( td );
    532457          case TypeData::Reference:
    533                         return buildReference( td );
     458                return buildReference( td );
    534459          case TypeData::Function:
    535                         return buildFunction( td );
     460                return buildFunction( td );
    536461          case TypeData::AggregateInst:
    537                         return buildAggInst( td );
     462                return buildAggInst( td );
    538463          case TypeData::EnumConstant:
    539                         // the name gets filled in later -- by SymTab::Validate
    540                         return new EnumInstType( buildQualifiers( td ), "" );
     464                // the name gets filled in later -- by SymTab::Validate
     465                return new EnumInstType( buildQualifiers( td ), "" );
    541466          case TypeData::SymbolicInst:
    542                         return buildSymbolicInst( td );
     467                return buildSymbolicInst( td );;
    543468          case TypeData::Tuple:
    544                         return buildTuple( td );
     469                return buildTuple( td );
    545470          case TypeData::Typeof:
    546           case TypeData::Basetypeof:
    547                         return buildTypeof( td );
     471                return buildTypeof( td );
    548472          case TypeData::Builtin:
    549                         if (td->builtintype == DeclarationNode::Zero) {
    550                                 return new ZeroType( noQualifiers );
    551                         }
    552                         else if (td->builtintype == DeclarationNode::One) {
    553                                 return new OneType( noQualifiers );
    554                         }
    555                         else {
    556                                 return new VarArgsType( buildQualifiers( td ) );
    557                         }
    558           case TypeData::GlobalScope:
    559                         return new GlobalScopeType();
    560                 case TypeData::Qualified:
    561                         return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) );
     473                if(td->builtintype == DeclarationNode::Zero) {
     474                        return new ZeroType( noQualifiers );
     475                }
     476                else if(td->builtintype == DeclarationNode::One) {
     477                        return new OneType( noQualifiers );
     478                }
     479                else {
     480                        return new VarArgsType( buildQualifiers( td ) );
     481                }
    562482          case TypeData::Symbolic:
    563483          case TypeData::Enum:
    564484          case TypeData::Aggregate:
    565                         assert( false );
     485                assert( false );
    566486        } // switch
    567 
    568487        return nullptr;
    569488} // typebuild
     
    666585
    667586          case DeclarationNode::Float:
     587          case DeclarationNode::Float80:
     588          case DeclarationNode::Float128:
    668589          case DeclarationNode::Double:
    669590          case DeclarationNode::LongDouble:                                     // not set until below
    670           case DeclarationNode::uuFloat80:
    671           case DeclarationNode::uuFloat128:
    672           case DeclarationNode::uFloat16:
    673           case DeclarationNode::uFloat32:
    674           case DeclarationNode::uFloat32x:
    675           case DeclarationNode::uFloat64:
    676           case DeclarationNode::uFloat64x:
    677           case DeclarationNode::uFloat128:
    678           case DeclarationNode::uFloat128x:
    679                 static BasicType::Kind floattype[2][12] = {
    680                         { 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, },
    681                         { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x, },
     591                static BasicType::Kind floattype[3][3] = {
     592                        { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex },
     593                        { BasicType::FloatImaginary, BasicType::DoubleImaginary, BasicType::LongDoubleImaginary },
     594                        { BasicType::Float, BasicType::Double, BasicType::LongDouble },
    682595                };
    683596
     
    692605                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    693606                } // if
    694                 if ( td->complextype == DeclarationNode::Imaginary ) {
    695                         genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
    696                 } // if
    697                 if ( (td->basictype == DeclarationNode::uuFloat80 || td->basictype == DeclarationNode::uuFloat128) && td->complextype == DeclarationNode::Complex ) { // gcc unsupported
    698                         genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
    699                 } // if
    700607                if ( td->length == DeclarationNode::Long ) {
    701608                        const_cast<TypeData *>(td)->basictype = DeclarationNode::LongDouble;
    702609                } // if
    703610
     611                if ( td->basictype == DeclarationNode::Float80 || td->basictype == DeclarationNode::Float128 ) {
     612                        // if ( td->complextype != DeclarationNode::NoComplexType ) {
     613                        //      genTSError( DeclarationNode::complexTypeNames[ td->complextype ], td->basictype );
     614                        // }
     615                        if ( td->basictype == DeclarationNode::Float80 ) ret = BasicType::Float80;
     616                        else ret = BasicType::Float128;
     617                        break;
     618                }
     619
    704620                ret = floattype[ td->complextype ][ td->basictype - DeclarationNode::Float ];
    705                 //printf( "XXXX %d %d %d %d\n", td->complextype, td->basictype, DeclarationNode::Float, ret );
    706621                break;
    707622
     
    943858
    944859TypeofType * buildTypeof( const TypeData * td ) {
    945         assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
     860        assert( td->kind == TypeData::Typeof );
    946861        assert( td->typeexpr );
    947862        // assert( td->typeexpr->expr );
    948         return new TypeofType{
    949                 buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof };
     863        return new TypeofType( buildQualifiers( td ), td->typeexpr->build() );
    950864} // buildTypeof
    951865
     
    979893        assert( td->kind == TypeData::Function );
    980894        FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis );
    981         buildList( td->function.params, ft->parameters );
    982         buildForall( td->forall, ft->forall );
     895        buildList( td->function.params, ft->get_parameters() );
     896        buildForall( td->forall, ft->get_forall() );
    983897        if ( td->base ) {
    984898                switch ( td->base->kind ) {
    985899                  case TypeData::Tuple:
    986                         buildList( td->base->tuple, ft->returnVals );
     900                        buildList( td->base->tuple, ft->get_returnVals() );
    987901                        break;
    988902                  default:
  • src/Parser/TypeData.h

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 15:18:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Nov  1 20:56:46 2018
    13 // Update Count     : 196
     12// Last Modified On : Thu Feb 22 15:21:23 2018
     13// Update Count     : 191
    1414//
    1515
     
    2626
    2727struct TypeData {
    28         enum Kind { Basic, Pointer, Reference, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
    29                                 SymbolicInst, Tuple, Typeof, Basetypeof, Builtin, GlobalScope, Qualified, Unknown };
     28        enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
     29                                SymbolicInst, Tuple, Typeof, Builtin, Unknown };
    3030
    3131        struct Aggregate_t {
    3232                DeclarationNode::Aggregate kind;
    33                 const std::string * name = nullptr;
    34                 DeclarationNode * params = nullptr;
    35                 ExpressionNode * actuals = nullptr;                                             // holds actual parameters later applied to AggInst
    36                 DeclarationNode * fields = nullptr;
     33                const std::string * name;
     34                DeclarationNode * params;
     35                ExpressionNode * actuals;                                               // holds actual parameters later applied to AggInst
     36                DeclarationNode * fields;
    3737                bool body;
    38                 bool anon;
    3938
    4039                bool tagged;
    41                 const std::string * parent = nullptr;
     40                const std::string * parent;
    4241        };
    4342
    4443        struct AggInst_t {
    45                 TypeData * aggregate = nullptr;
    46                 ExpressionNode * params = nullptr;
     44                TypeData * aggregate;
     45                ExpressionNode * params;
    4746                bool hoistType;
    4847        };
    4948
    5049        struct Array_t {
    51                 ExpressionNode * dimension = nullptr;
     50                ExpressionNode * dimension;
    5251                bool isVarLen;
    5352                bool isStatic;
     
    5554
    5655        struct Enumeration_t {
    57                 const std::string * name = nullptr;
    58                 DeclarationNode * constants = nullptr;
     56                const std::string * name;
     57                DeclarationNode * constants;
    5958                bool body;
    60                 bool anon;
    6159        };
    6260
    6361        struct Function_t {
    64                 mutable DeclarationNode * params = nullptr;                             // mutables modified in buildKRFunction
    65                 mutable DeclarationNode * idList = nullptr;                             // old-style
    66                 mutable DeclarationNode * oldDeclList = nullptr;
    67                 StatementNode * body = nullptr;
    68                 ExpressionNode * withExprs = nullptr;                                           // expressions from function's with_clause
     62                mutable DeclarationNode * params;                               // mutables modified in buildKRFunction
     63                mutable DeclarationNode * idList;                               // old-style
     64                mutable DeclarationNode * oldDeclList;
     65                StatementNode * body;
     66                ExpressionNode * withExprs;             // expressions from function's with_clause
    6967        };
    7068
    7169        struct Symbolic_t {
    72                 const std::string * name = nullptr;
     70                const std::string * name;
    7371                bool isTypedef;                                                                 // false => TYPEGENname, true => TYPEDEFname
    74                 DeclarationNode * params = nullptr;
    75                 ExpressionNode * actuals = nullptr;
    76                 DeclarationNode * assertions = nullptr;
    77         };
    78 
    79         struct Qualified_t {                                                            // qualified type S.T
    80                 TypeData * parent = nullptr;
    81                 TypeData * child = nullptr;
     72                DeclarationNode * params;
     73                ExpressionNode * actuals;
     74                DeclarationNode * assertions;
    8275        };
    8376
     
    9386
    9487        Type::Qualifiers qualifiers;
    95         DeclarationNode * forall = nullptr;
     88        DeclarationNode * forall;
    9689
     90        // Basic_t basic;
    9791        Aggregate_t aggregate;
    9892        AggInst_t aggInst;
    9993        Array_t array;
    10094        Enumeration_t enumeration;
     95        // Variable_t variable;
    10196        Function_t function;
    10297        Symbolic_t symbolic;
    103         Qualified_t qualified;
    104         DeclarationNode * tuple = nullptr;
    105         ExpressionNode * typeexpr = nullptr;
     98        DeclarationNode * tuple;
     99        ExpressionNode * typeexpr;
    106100
    107101        TypeData( Kind k = Unknown );
     
    109103        void print( std::ostream &, int indent = 0 ) const;
    110104        TypeData * clone() const;
    111 
    112         const std::string * leafName() const;
    113105};
    114106
     
    128120TupleType * buildTuple( const TypeData * );
    129121TypeofType * buildTypeof( const TypeData * );
    130 Declaration * buildDecl( const TypeData *, const std::string &, Type::StorageClasses, Expression *, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec, Expression * asmName,
    131                                                  Initializer * init = nullptr, std::list< class Attribute * > attributes = std::list< class Attribute * >() );
     122Declaration * buildDecl( const TypeData *, const std::string &, Type::StorageClasses, Expression *, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec, Expression * asmName, Initializer * init = nullptr, std::list< class Attribute * > attributes = std::list< class Attribute * >() );
    132123FunctionType * buildFunction( const TypeData * );
    133124void buildKRFunction( const TypeData::Function_t & function );
  • src/Parser/TypedefTable.cc

    rb067d9b r7951100  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // TypedefTable.cc --
     7// TypedefTable.cc -- 
    88//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat May 16 15:20:13 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 25 15:32:35 2018
    13 // Update Count     : 258
     12// Last Modified On : Thu Jun  7 13:17:56 2018
     13// Update Count     : 192
    1414//
    1515
     
    5151} // TypedefTable::exists
    5252
    53 bool TypedefTable::existsCurr( const string & identifier ) {
    54         return kindTable.findAt( kindTable.currentScope() - 1, identifier ) != kindTable.end();
    55 } // TypedefTable::exists
    56 
    5753int TypedefTable::isKind( const string & identifier ) const {
    5854        KindTable::const_iterator posn = kindTable.find( identifier );
     
    8177        auto scope = kindTable.currentScope();
    8278        debugPrint( cerr << "Adding current at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl );
    83         kindTable.insertAt( scope, identifier, kind );
     79        auto ret = kindTable.insertAt( scope, identifier, kind );
     80        if ( ! ret.second ) ret.first->second = kind;           // exists => update
    8481} // TypedefTable::addToScope
    8582
    8683void TypedefTable::addToEnclosingScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    87         auto scope = kindTable.currentScope() - 1 - kindTable.getNote( kindTable.currentScope() - 1 ).level;
    88 //      auto scope = level - kindTable.getNote( kindTable.currentScope() - 1 ).level;
    89         debugPrint( cerr << "Adding enclosing at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << " level " << level << " note " << kindTable.getNote( kindTable.currentScope() - 1 ).level << endl );
     84        assert( kindTable.currentScope() >= 1 );
     85        auto scope = kindTable.currentScope() - 1;
     86        debugPrint( cerr << "Adding enclosing at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl );
    9087        auto ret = kindTable.insertAt( scope, identifier, kind );
    91         if ( ! ret.second ) ret.first->second = kind;   // exists => update
     88        if ( ! ret.second ) ret.first->second = kind;           // exists => update
    9289} // TypedefTable::addToEnclosingScope
    9390
    9491void TypedefTable::enterScope() {
    95         kindTable.beginScope( (Note){ 0, false } );
    96         debugPrint( cerr << "Entering scope " << kindTable.currentScope() << " level " << level << endl; print() );
     92        kindTable.beginScope();
     93        debugPrint( cerr << "Entering scope " << kindTable.currentScope() << endl );
     94        debugPrint( print() );
    9795} // TypedefTable::enterScope
    9896
    9997void TypedefTable::leaveScope() {
    100         debugPrint( cerr << "Leaving scope " << kindTable.currentScope() << endl; print() );
     98        debugPrint( cerr << "Leaving scope " << kindTable.currentScope() << endl );
     99        debugPrint( print() );
    101100        kindTable.endScope();
    102101} // TypedefTable::leaveScope
    103102
    104 void TypedefTable::up( bool forall ) {
    105         level += 1;
    106         kindTable.getNote( kindTable.currentScope() ) = (Note){ level, forall || getEnclForall() };
    107         debugPrint( cerr << "Up " << " level " << level << " note " << kindTable.getNote( level ).level << ", " << kindTable.getNote( level ).forall << endl; );
    108 } // TypedefTable::up
    109 
    110 void TypedefTable::down() {
    111         level -= 1;
    112         debugPrint( cerr << "Down " << " level " << level << " note " << kindTable.getNote( level ).level << endl; );
    113 } // TypedefTable::down
    114 
    115103void TypedefTable::print( void ) const {
    116104        KindTable::size_type scope = kindTable.currentScope();
    117         debugPrint( cerr << "[" << scope << "] " << kindTable.getNote( scope ).level << ", " << kindTable.getNote( scope ).forall << ":" );
     105        debugPrint( cerr << "[" << scope << "]" );
    118106        for ( KindTable::const_iterator i = kindTable.begin(); i != kindTable.end(); i++ ) {
    119107                while ( i.get_level() != scope ) {
    120108                        --scope;
    121                         debugPrint( cerr << endl << "[" << scope << "] " << kindTable.getNote( scope ).level << ", " << kindTable.getNote( scope ).forall << ":" );
     109                        debugPrint( cerr << endl << "[" << scope << "]" );
    122110                } // while
    123111                debugPrint( cerr << " " << (*i).first << ":" << kindName( (*i).second ) );
     
    125113        while ( scope > 0 ) {
    126114                --scope;
    127                 debugPrint( cerr << endl << "[" << scope << "] " << kindTable.getNote( scope ).level << ", " << kindTable.getNote( scope ).forall << ":" );
    128         } // while
     115                debugPrint( cerr << endl << "[" << scope << "]" );
     116        }
    129117        debugPrint( cerr << endl );
    130 } // TypedefTable::print
     118}
    131119
    132120// Local Variables: //
  • src/Parser/TypedefTable.h

    rb067d9b r7951100  
    1010// Created On       : Sat May 16 15:24:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 25 15:33:55 2018
    13 // Update Count     : 114
     12// Last Modified On : Thu Jun  7 12:10:17 2018
     13// Update Count     : 85
    1414//
    1515
     
    2323
    2424class TypedefTable {
    25         struct Note { size_t level; bool forall; };
    26         typedef ScopedMap< std::string, int, Note > KindTable;
     25        typedef ScopedMap< std::string, int > KindTable;
    2726        KindTable kindTable;   
    28         unsigned int level = 0;
    2927  public:
    3028        ~TypedefTable();
    3129
    3230        bool exists( const std::string & identifier );
    33         bool existsCurr( const std::string & identifier );
    3431        int isKind( const std::string & identifier ) const;
    3532        void makeTypedef( const std::string & name, int kind = TYPEDEFname );
    3633        void addToScope( const std::string & identifier, int kind, const char * );
    3734        void addToEnclosingScope( const std::string & identifier, int kind, const char * );
    38         bool getEnclForall() { return kindTable.getNote( kindTable.currentScope() -  1 ).forall; }
    3935
    4036        void enterScope();
    4137        void leaveScope();
    42 
    43         void up( bool );
    44         void down();
    4538
    4639        void print( void ) const;
  • src/Parser/lex.ll

    rb067d9b r7951100  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Sun Aug  4 20:53:47 2019
    13  * Update Count     : 719
     12 * Last Modified On : Thu Jun  7 08:27:40 2018
     13 * Update Count     : 679
    1414 */
    1515
     
    2525//**************************** Includes and Defines ****************************
    2626
    27 // trigger before each matching rule's action
    28 #define YY_USER_ACTION \
    29         yylloc.first_line = yylineno; \
    30         yylloc.first_column = column; \
    31         column += yyleng; \
    32         yylloc.last_column = column; \
    33         yylloc.last_line = yylineno; \
    34         yylloc.filename = yyfilename ? yyfilename : "";
    3527unsigned int column = 0;                                                                // position of the end of the last token parsed
     28#define YY_USER_ACTION yylloc.first_line = yylineno; yylloc.first_column = column; column += yyleng; yylloc.last_column = column; yylloc.last_line = yylineno; yylloc.filename = yyfilename ? yyfilename : "";                          // trigger before each matching rule's action
    3629
    3730#include <string>
     
    3932using namespace std;
    4033
    41 #include "config.h"                                                                             // configure info
    4234#include "ParseNode.h"
    4335#include "TypedefTable.h"
     
    5749#define NUMERIC_RETURN(x)       rm_underscore(); RETURN_VAL( x ) // numeric constant
    5850#define KEYWORD_RETURN(x)       RETURN_CHAR( x )                        // keyword
    59 #define QKEYWORD_RETURN(x)      RETURN_VAL(x);                          // quasi-keyword
     51#define QKEYWORD_RETURN(x)      typedefTable.isKind( yytext ); RETURN_VAL(x); // quasi-keyword
    6052#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    61 
    62 #ifdef HAVE_KEYWORDS_FLOATXX                                                            // GCC >= 7 => keyword, otherwise typedef
    63 #define FLOATXX(v) KEYWORD_RETURN(v);
    64 #else
    65 #define FLOATXX(v) IDENTIFIER_RETURN();
    66 #endif // HAVE_KEYWORDS_FLOATXX
     53#define ATTRIBUTE_RETURN()      RETURN_VAL( ATTR_IDENTIFIER )
    6754
    6855void rm_underscore() {
     
    9279identifier ([a-zA-Z_$]|{universal_char})([0-9a-zA-Z_$]|{universal_char})*
    9380
     81                                // attribute identifier, GCC: $ in identifier
     82attr_identifier "@"{identifier}
     83
    9484                                // numeric constants, CFA: '_' in constant
    9585hex_quad {hex}("_"?{hex}){3}
    9686size_opt (8|16|32|64|128)?
    97                                 // CFA: explicit l8/l16/l32/l64/l128, char 'hh', short 'h', int 'n'
    98 length ("ll"|"LL"|[lL]{size_opt})|("hh"|"HH"|[hHnN])
    99                                 // CFA: size_t 'z', pointer 'p', which define a sign and length
    100 integer_suffix_opt ("_"?(([uU]({length}?[iI]?)|([iI]{length}))|([iI]({length}?[uU]?)|([uU]{length}))|({length}([iI]?[uU]?)|([uU][iI]))|[zZ]|[pP]))?
     87length ("ll"|"LL"|[lL]{size_opt})|("hh"|"HH"|[hH])
     88integer_suffix_opt ("_"?(([uU]({length}?[iI]?)|([iI]{length}))|([iI]({length}?[uU]?)|([uU]{length}))|({length}([iI]?[uU]?)|([uU][iI]))|[zZ]))?
    10189
    10290octal_digits ({octal})|({octal}({octal}|"_")*{octal})
     
    117105                                // GCC: D (double) and iI (imaginary) suffixes, and DL (long double)
    118106exponent "_"?[eE]"_"?[+-]?{decimal_digits}
    119 floating_size 16|32|32x|64|64x|80|128|128x
    120 floating_length ([fFdDlLwWqQ]|[fF]{floating_size})
     107floating_size 32|64|80|128
     108floating_length ([fFdDlL]|[lL]{floating_size})
    121109floating_suffix ({floating_length}?[iI]?)|([iI]{floating_length})
    122110floating_suffix_opt ("_"?({floating_suffix}|"DL"))?
     
    214202__attribute__   { KEYWORD_RETURN(ATTRIBUTE); }                  // GCC
    215203auto                    { KEYWORD_RETURN(AUTO); }
    216 __auto_type             { KEYWORD_RETURN(AUTO_TYPE); }
    217 basetypeof              { KEYWORD_RETURN(BASETYPEOF); }                 // CFA
    218204_Bool                   { KEYWORD_RETURN(BOOL); }                               // C99
    219205break                   { KEYWORD_RETURN(BREAK); }
     
    223209char                    { KEYWORD_RETURN(CHAR); }
    224210choose                  { KEYWORD_RETURN(CHOOSE); }                             // CFA
    225 coerce                  { KEYWORD_RETURN(COERCE); }                             // CFA
    226211_Complex                { KEYWORD_RETURN(COMPLEX); }                    // C99
    227212__complex               { KEYWORD_RETURN(COMPLEX); }                    // GCC
     
    247232finally                 { KEYWORD_RETURN(FINALLY); }                    // CFA
    248233float                   { KEYWORD_RETURN(FLOAT); }
    249 __float80               { KEYWORD_RETURN(uuFLOAT80); }                  // GCC
    250 float80                 { KEYWORD_RETURN(uuFLOAT80); }                  // GCC
    251 __float128              { KEYWORD_RETURN(uuFLOAT128); }                 // GCC
    252 float128                { KEYWORD_RETURN(uuFLOAT128); }                 // GCC
    253 _Float16                { FLOATXX(uFLOAT16); }                                  // GCC
    254 _Float32                { FLOATXX(uFLOAT32); }                                  // GCC
    255 _Float32x               { FLOATXX(uFLOAT32X); }                                 // GCC
    256 _Float64                { FLOATXX(uFLOAT64); }                                  // GCC
    257 _Float64x               { FLOATXX(uFLOAT64X); }                                 // GCC
    258 _Float128               { FLOATXX(uFLOAT128); }                                 // GCC
    259 _Float128x              { FLOATXX(uFLOAT128); }                                 // GCC
     234_Float32                { KEYWORD_RETURN(FLOAT); }                              // GCC
     235_Float32x               { KEYWORD_RETURN(FLOAT); }                              // GCC
     236_Float64                { KEYWORD_RETURN(DOUBLE); }                             // GCC
     237_Float64x               { KEYWORD_RETURN(DOUBLE); }                             // GCC
     238__float80               { KEYWORD_RETURN(FLOAT80); }                    // GCC
     239float80                 { KEYWORD_RETURN(FLOAT80); }                    // GCC
     240_Float128               { KEYWORD_RETURN(FLOAT128); }                   // GCC
     241_Float128x              { KEYWORD_RETURN(FLOAT128); }                   // GCC
     242__float128              { KEYWORD_RETURN(FLOAT128); }                   // GCC
     243float128                { KEYWORD_RETURN(FLOAT128); }                   // GCC
    260244for                             { KEYWORD_RETURN(FOR); }
    261245forall                  { KEYWORD_RETURN(FORALL); }                             // CFA
    262246fortran                 { KEYWORD_RETURN(FORTRAN); }
    263247ftype                   { KEYWORD_RETURN(FTYPE); }                              // CFA
    264 generator               { KEYWORD_RETURN(GENERATOR); }                  // CFA
    265248_Generic                { KEYWORD_RETURN(GENERIC); }                    // C11
    266249goto                    { KEYWORD_RETURN(GOTO); }
     
    273256__inline__              { KEYWORD_RETURN(INLINE); }                             // GCC
    274257int                             { KEYWORD_RETURN(INT); }
    275 int128                  { KEYWORD_RETURN(INT128); }                             // CFA
    276258__int128                { KEYWORD_RETURN(INT128); }                             // GCC
    277 __int128_t              { KEYWORD_RETURN(INT128); }                             // GCC
     259int128                  { KEYWORD_RETURN(INT128); }                             // GCC
    278260__label__               { KEYWORD_RETURN(LABEL); }                              // GCC
    279261long                    { KEYWORD_RETURN(LONG); }
     
    290272__restrict__    { KEYWORD_RETURN(RESTRICT); }                   // GCC
    291273return                  { KEYWORD_RETURN(RETURN); }
    292         /* resume                       { KEYWORD_RETURN(RESUME); }                             // CFA */
    293274short                   { KEYWORD_RETURN(SHORT); }
    294275signed                  { KEYWORD_RETURN(SIGNED); }
     
    299280_Static_assert  { KEYWORD_RETURN(STATICASSERT); }               // C11
    300281struct                  { KEYWORD_RETURN(STRUCT); }
    301         /* suspend                      { KEYWORD_RETURN(SUSPEND); }                    // CFA */
    302282switch                  { KEYWORD_RETURN(SWITCH); }
    303283thread                  { KEYWORD_RETURN(THREAD); }                             // C11
     
    314294__typeof__              { KEYWORD_RETURN(TYPEOF); }                             // GCC
    315295union                   { KEYWORD_RETURN(UNION); }
    316 __uint128_t             { KEYWORD_RETURN(UINT128); }                    // GCC
    317296unsigned                { KEYWORD_RETURN(UNSIGNED); }
    318297__builtin_va_list { KEYWORD_RETURN(VALIST); }                   // GCC
     
    334313        IDENTIFIER_RETURN();
    335314}
     315{attr_identifier} { ATTRIBUTE_RETURN(); }
    336316
    337317                                /* numeric constants */
     
    424404
    425405"@="                    { NAMEDOP_RETURN(ATassign); }                   // CFA
    426 "~="                    { NAMEDOP_RETURN(ErangeUpEq); }                 // CFA
    427 "-~"                    { NAMEDOP_RETURN(ErangeDown); }                 // CFA
    428 "-~="                   { NAMEDOP_RETURN(ErangeDownEq); }               // CFA
    429406
    430407                                /* CFA, operator identifier */
     
    480457void yyerror( const char * errmsg ) {
    481458        SemanticErrorThrow = true;
    482         cerr << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
     459        cout << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
    483460                 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
    484461}
  • src/Parser/module.mk

    rb067d9b r7951100  
    66## file "LICENCE" distributed with Cforall.
    77##
    8 ## module.mk --
     8## module.mk -- 
    99##
    1010## Author           : Peter A. Buhr
     
    3131       Parser/parserutility.cc
    3232
    33 SRCDEMANGLE += \
    34         Parser/LinkageSpec.cc
    35 
    36 
    37 MOSTLYCLEANFILES += Parser/lex.cc Parser/parser.cc Parser/parser.hh Parser/parser.output
     33MAINTAINERCLEANFILES += Parser/parser.output
  • src/Parser/parser.yy

    rb067d9b r7951100  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  4 21:48:23 2019
    13 // Update Count     : 4364
     12// Last Modified On : Thu Jun  7 10:07:12 2018
     13// Update Count     : 3527
    1414//
    1515
     
    9999        // distribute declaration_specifier across all declared variables, e.g., static, const, __attribute__.
    100100        DeclarationNode * cur = declList, * cl = (new DeclarationNode)->addType( specifier );
    101         for ( cur = dynamic_cast<DeclarationNode *>( cur->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
     101        //cur->addType( specifier );
     102        for ( cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
    102103                cl->cloneBaseType( cur );
    103104        } // for
    104105        declList->addType( cl );
     106//      delete cl;
    105107        return declList;
    106108} // distAttr
     
    112114        } // for
    113115} // distExt
    114 
    115 void distInl( DeclarationNode * declaration ) {
    116         // distribute EXTENSION across all declarations
    117         for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
    118                 iter->set_inLine( true );
    119         } // for
    120 } // distInl
    121 
    122 void distQual( DeclarationNode * declaration, DeclarationNode * qualifiers ) {
    123         // distribute qualifiers across all non-variable declarations in a distribution statemement
    124         for ( DeclarationNode * iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
    125                 // SKULLDUGGERY: Distributions are parsed inside out, so qualifiers are added to declarations inside out. Since
    126                 // addQualifiers appends to the back of the list, the forall clauses are in the wrong order (right to left). To
    127                 // get the qualifiers in the correct order and still use addQualifiers (otherwise, 90% of addQualifiers has to
    128                 // be copied to add to front), the appropriate forall pointers are interchanged before calling addQualifiers.
    129                 DeclarationNode * clone = qualifiers->clone();
    130                 if ( qualifiers->type ) {                                               // forall clause ? (handles SC)
    131                         if ( iter->type->kind == TypeData::Aggregate ) { // struct/union ?
    132                                 swap( clone->type->forall, iter->type->aggregate.params );
    133                                 iter->addQualifiers( clone );
    134                         } else if ( iter->type->kind == TypeData::AggregateInst && iter->type->aggInst.aggregate->aggregate.body ) { // struct/union ?
    135                                 // Create temporary node to hold aggregate, call addQualifiers as above, then put nodes back together.
    136                                 DeclarationNode newnode;
    137                                 swap( newnode.type, iter->type->aggInst.aggregate );
    138                                 swap( clone->type->forall, newnode.type->aggregate.params );
    139                                 newnode.addQualifiers( clone );
    140                                 swap( newnode.type, iter->type->aggInst.aggregate );
    141                         } else if ( iter->type->kind == TypeData::Function ) { // routines ?
    142                                 swap( clone->type->forall, iter->type->forall );
    143                                 iter->addQualifiers( clone );
    144                         } // if
    145                 } else {                                                                                // just SC qualifiers
    146                         iter->addQualifiers( clone );
    147                 } // if
    148         } // for
    149         delete qualifiers;
    150 } // distQual
    151116
    152117// There is an ambiguity for inline generic-routine return-types and generic routines.
     
    171136} // build_postfix_name
    172137
    173 DeclarationNode * fieldDecl( DeclarationNode * typeSpec, DeclarationNode * fieldList ) {
    174         if ( ! fieldList ) {                                                            // field declarator ?
    175                 if ( ! ( typeSpec->type && (typeSpec->type->kind == TypeData::Aggregate || typeSpec->type->kind == TypeData::Enum) ) ) {
    176                         stringstream ss;
    177                         typeSpec->type->print( ss );
    178                         SemanticWarning( yylloc, Warning::SuperfluousDecl, ss.str().c_str() );
    179                         return nullptr;
    180                 } // if
    181                 fieldList = DeclarationNode::newName( nullptr );
    182         } // if
    183         return distAttr( typeSpec, fieldList );                         // mark all fields in list
    184 } // fieldDecl
    185 
    186 ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    187         ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get());
    188         if ( constant && (constant->get_constant()->get_value() == "0" || constant->get_constant()->get_value() == "1") ) {
    189         type = new ExpressionNode( new CastExpr( maybeMoveBuild< Expression >(type), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ) );
    190         } // if
    191         return new ForCtrl(
    192                 distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
    193                 // NULL comp/inc => leave blank
    194                 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : 0,
    195                 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
    196                                                         OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : 0 );
    197 } // forCtrl
    198 
    199 ForCtrl * forCtrl( ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    200         if ( NameExpr * identifier = dynamic_cast<NameExpr *>(index->expr.get()) ) {
    201                 return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
    202         } else if ( CommaExpr * commaExpr = dynamic_cast<CommaExpr *>(index->expr.get()) ) {
    203                 if ( NameExpr * identifier = dynamic_cast<NameExpr *>(commaExpr->arg1 ) ) {
    204                         return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
    205                 } else {
    206                         SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
    207                 } // if
    208         } else {
    209                 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
    210         } // if
    211 } // forCtrl
    212 
    213 
    214 bool forall = false, yyy = false;                                               // aggregate have one or more forall qualifiers ?
     138bool forall = false, xxx = false;                                               // aggregate have one or more forall qualifiers ?
    215139
    216140// https://www.gnu.org/software/bison/manual/bison.html#Location-Type
     
    232156
    233157// Types declaration for productions
    234 %union {
     158%union
     159{
    235160        Token tok;
    236161        ParseNode * pn;
     
    242167        WaitForStmt * wfs;
    243168        Expression * constant;
    244         IfCtrl * ifctl;
    245         ForCtrl * fctl;
    246         enum OperKinds compop;
     169        IfCtl * ifctl;
     170        ForCtl * fctl;
    247171        LabelNode * label;
    248172        InitializerNode * in;
     
    265189%token RESTRICT                                                                                 // C99
    266190%token ATOMIC                                                                                   // C11
    267 %token FORALL MUTEX VIRTUAL COERCE                                              // CFA
     191%token FORALL MUTEX VIRTUAL                                                             // CFA
    268192%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
    269193%token BOOL COMPLEX IMAGINARY                                                   // C99
    270 %token INT128 UINT128 uuFLOAT80 uuFLOAT128                              // GCC
    271 %token uFLOAT16 uFLOAT32 uFLOAT32X uFLOAT64 uFLOAT64X uFLOAT128 // GCC
     194%token INT128 FLOAT80 FLOAT128                                                  // GCC
    272195%token ZERO_T ONE_T                                                                             // CFA
    273196%token VALIST                                                                                   // GCC
    274 %token AUTO_TYPE                                                                                // GCC
    275 %token TYPEOF BASETYPEOF LABEL                                                  // GCC
     197%token TYPEOF LABEL                                                                             // GCC
    276198%token ENUM STRUCT UNION
    277199%token EXCEPTION                                                                                // CFA
    278 %token GENERATOR COROUTINE MONITOR THREAD                               // CFA
     200%token COROUTINE MONITOR THREAD                                                 // CFA
    279201%token OTYPE FTYPE DTYPE TTYPE TRAIT                                    // CFA
    280202%token SIZEOF OFFSETOF
    281 // %token SUSPEND RESUME                                                                        // CFA
    282203%token ATTRIBUTE EXTENSION                                                              // GCC
    283204%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
     
    289210%token<tok> IDENTIFIER                  QUOTED_IDENTIFIER               TYPEDEFname                             TYPEGENname
    290211%token<tok> TIMEOUT                             WOR
     212%token<tok> ATTR_IDENTIFIER             ATTR_TYPEDEFname                ATTR_TYPEGENname
    291213%token<tok> INTEGERconstant             CHARACTERconstant               STRINGliteral
    292214%token<tok> DIRECTIVE
     
    309231%token ANDassign        ERassign        ORassign                                // &=   ^=      |=
    310232
    311 %token ErangeUpEq       ErangeDown      ErangeDownEq                    // ~=   -~      -~=
    312233%token ATassign                                                                                 // @=
    313234
    314 %type<tok> identifier
    315 %type<tok> identifier_or_type_name  attr_name
     235%type<tok> identifier  no_attr_identifier
     236%type<tok> identifier_or_type_name  no_attr_identifier_or_type_name  attr_name
    316237%type<tok> quasi_keyword
    317238%type<constant> string_literal
     
    331252%type<en> argument_expression_list              argument_expression                     default_initialize_opt
    332253%type<ifctl> if_control_expression
    333 %type<fctl> for_control_expression              for_control_expression_list
    334 %type<compop> inclexcl
     254%type<fctl> for_control_expression
    335255%type<en> subrange
    336256%type<decl> asm_name_opt
    337 %type<en> asm_operands_opt                              asm_operands_list                       asm_operand
     257%type<en> asm_operands_opt asm_operands_list asm_operand
    338258%type<label> label_list
    339259%type<en> asm_clobbers_list_opt
    340260%type<flag> asm_volatile_opt
    341261%type<en> handler_predicate_opt
    342 %type<genexpr> generic_association              generic_assoc_list
     262%type<genexpr> generic_association generic_assoc_list
    343263
    344264// statements
     
    384304%type<en> enumerator_value_opt
    385305
    386 %type<decl> external_definition external_definition_list external_definition_list_opt
    387 
    388 %type<decl> exception_declaration
    389 
    390 %type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract
    391 %type<en> field field_name_list field_name fraction_constants_opt
     306%type<decl> exception_declaration external_definition external_definition_list external_definition_list_no_pop_push external_definition_list_opt
     307
     308%type<decl> field_declaration field_declaration_list_opt field_declarator_opt field_declaring_list
     309%type<en> field field_list field_name fraction_constants_opt
    392310
    393311%type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
     
    402320%type<decl> cfa_array_parameter_1st_dimension
    403321
    404 %type<decl> cfa_trait_declaring_list cfa_declaration cfa_field_declaring_list cfa_field_abstract_list
     322%type<decl> cfa_trait_declaring_list cfa_declaration cfa_field_declaring_list
    405323%type<decl> cfa_function_declaration cfa_function_return cfa_function_specifier
    406324
     
    437355%type<decl> type_parameter type_parameter_list type_initializer_opt
    438356
    439 %type<en> type_parameters_opt type_list
     357%type<en> type_list
    440358
    441359%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
     
    472390//   Foo ( *fp )( int );
    473391//   `---'                                              matches start of TYPEGENname '('
    474 // must be:
     392// Must be:
    475393//   Foo( int ) ( *fp )( int );
    476 // The same problem occurs here:
    477 //   forall( otype T ) struct Foo { T v; } ( *fp )( int );
    478 // must be:
    479 //   forall( otype T ) struct Foo { T v; } ( int ) ( *fp )( int );
    480394
    481395// Order of these lines matters (low-to-high precedence).
    482396%precedence TYPEGENname
    483 %precedence '}'
    484397%precedence '('
    485 
    486 // %precedence RESUME
    487 // %precedence '{'
    488 // %precedence ')'
    489398
    490399%locations                                                                                              // support location tracking for error messages
     
    548457identifier:
    549458        IDENTIFIER
     459        | ATTR_IDENTIFIER                                                                       // CFA
    550460        | quasi_keyword
    551         | '@'                                                                                           // CFA
    552                 { Token tok = { new string( DeclarationNode::anonymous.newName() ), yylval.tok.loc }; $$ = tok; }
     461        ;
     462
     463no_attr_identifier:
     464        IDENTIFIER
     465        | quasi_keyword
    553466        ;
    554467
     
    589502        | '(' comma_expression ')' '`' IDENTIFIER                       // CFA, postfix call
    590503                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $5 ) ), $2 ) ); }
    591         | type_name '.' identifier                                                      // CFA, nested type
    592                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    593         | type_name '.' '[' field_name_list ']'                         // CFA, nested type / tuple field selector
    594                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     504        | type_name '.' no_attr_identifier                                      // CFA, nested type
     505                // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     506                { $$ = nullptr; }
     507        | type_name '.' '[' field_list ']'                                      // CFA, nested type / tuple field selector
     508                // { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     509                { $$ = nullptr; }
    595510        | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
    596511                {
     
    599514                        $$ = new ExpressionNode( $5 );
    600515                }
    601         // | RESUME '(' comma_expression ')'
    602         //      { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
    603         // | RESUME '(' comma_expression ')' compound_statement
    604         //      { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
    605516        ;
    606517
     
    642553        | postfix_expression '(' argument_expression_list ')'
    643554                { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
    644         | postfix_expression '.' identifier
     555        | postfix_expression '.' no_attr_identifier
    645556                { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
    646557        | postfix_expression '.' INTEGERconstant                        // CFA, tuple index
     
    648559        | postfix_expression FLOATING_FRACTIONconstant          // CFA, tuple index
    649560                { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
    650         | postfix_expression '.' '[' field_name_list ']'        // CFA, tuple field selector
     561        | postfix_expression '.' '[' field_list ']'                     // CFA, tuple field selector
    651562                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    652         | postfix_expression ARROW identifier
    653                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
     563        | postfix_expression ARROW no_attr_identifier
     564                {
     565                        $$ = new ExpressionNode( build_pfieldSel( $1, *$3 == "0" || *$3 == "1" ? build_constantInteger( *$3 ) : build_varref( $3 ) ) );
     566                }
    654567        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    655568                { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
    656         | postfix_expression ARROW '[' field_name_list ']'      // CFA, tuple field selector
     569        | postfix_expression ARROW '[' field_list ']'           // CFA, tuple field selector
    657570                { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
    658571        | postfix_expression ICR
     
    673586
    674587argument_expression_list:
     588        argument_expression
     589        | argument_expression_list ',' argument_expression
     590                { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
     591        ;
     592
     593argument_expression:
    675594        // empty
    676595                { $$ = nullptr; }
    677         | argument_expression
    678         | argument_expression_list ',' argument_expression
    679                 { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
    680         ;
    681 
    682 argument_expression:
    683         '@'                                                                                                     // CFA, default parameter
    684                 { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
    685                 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
     596        // | '@'                                                                                                // use default argument
     597        //      { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
    686598        | assignment_expression
    687599        ;
    688600
    689 field_name_list:                                                                                // CFA, tuple field selector
     601field_list:                                                                                             // CFA, tuple field selector
    690602        field
    691         | field_name_list ',' field                                     { $$ = (ExpressionNode *)$1->set_last( $3 ); }
     603        | field_list ',' field                                          { $$ = (ExpressionNode *)$1->set_last( $3 ); }
    692604        ;
    693605
     
    696608        | FLOATING_DECIMALconstant field
    697609                { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }
    698         | FLOATING_DECIMALconstant '[' field_name_list ']'
     610        | FLOATING_DECIMALconstant '[' field_list ']'
    699611                { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple( $3 ) ) ); }
    700612        | field_name '.' field
    701613                { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
    702         | field_name '.' '[' field_name_list ']'
     614        | field_name '.' '[' field_list ']'
    703615                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    704616        | field_name ARROW field
    705617                { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
    706         | field_name ARROW '[' field_name_list ']'
     618        | field_name ARROW '[' field_list ']'
    707619                { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
    708620        ;
     
    713625        | FLOATINGconstant fraction_constants_opt
    714626                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
    715         | identifier fraction_constants_opt
     627        | no_attr_identifier fraction_constants_opt
    716628                {
    717629                        $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     
    771683        | ALIGNOF '(' type_no_function ')'                                      // GCC, type alignment
    772684                { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); }
    773         | OFFSETOF '(' type_no_function ',' identifier ')'
     685        | OFFSETOF '(' type_no_function ',' no_attr_identifier ')'
    774686                { $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) ); }
     687        | ATTR_IDENTIFIER
     688                { $$ = new ExpressionNode( new AttrExpr( build_varref( $1 ), maybeMoveBuild< Expression >( (ExpressionNode *)nullptr ) ) ); }
     689        | ATTR_IDENTIFIER '(' argument_expression ')'
     690                { $$ = new ExpressionNode( new AttrExpr( build_varref( $1 ), maybeMoveBuild< Expression >( $3 ) ) ); }
     691        | ATTR_IDENTIFIER '(' type ')'
     692                { $$ = new ExpressionNode( new AttrExpr( build_varref( $1 ), maybeMoveBuildType( $3 ) ) ); }
    775693        ;
    776694
     
    793711        | '(' type_no_function ')' cast_expression
    794712                { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
    795                 // keyword cast cannot be grouped because of reduction in aggregate_key
    796         | '(' GENERATOR '&' ')' cast_expression                         // CFA
    797                 { $$ = new ExpressionNode( build_keyword_cast( KeywordCastExpr::Coroutine, $5 ) ); }
    798713        | '(' COROUTINE '&' ')' cast_expression                         // CFA
    799714                { $$ = new ExpressionNode( build_keyword_cast( KeywordCastExpr::Coroutine, $5 ) ); }
     
    807722        | '(' VIRTUAL type_no_function ')' cast_expression      // CFA
    808723                { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild< Expression >( $5 ), maybeMoveBuildType( $3 ) ) ); }
    809         | '(' RETURN type_no_function ')' cast_expression       // CFA
    810                 { SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; }
    811         | '(' COERCE type_no_function ')' cast_expression       // CFA
    812                 { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; }
    813         | '(' qualifier_cast_list ')' cast_expression           // CFA
    814                 { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; }
    815724//      | '(' type_no_function ')' tuple
    816725//              { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
    817         ;
    818 
    819 qualifier_cast_list:
    820         cast_modifier type_qualifier_name
    821         | cast_modifier MUTEX
    822         | qualifier_cast_list cast_modifier type_qualifier_name
    823         | qualifier_cast_list cast_modifier MUTEX
    824         ;
    825 
    826 cast_modifier:
    827         '-'
    828         | '+'
    829726        ;
    830727
     
    1007904
    1008905labeled_statement:
    1009                 // labels cannot be identifiers 0 or 1
     906                // labels cannot be identifiers 0 or 1 or ATTR_IDENTIFIER
    1010907        identifier_or_type_name ':' attribute_list_opt statement
    1011                 { $$ = $4->add_label( $1, $3 ); }
     908                {
     909                        $$ = $4->add_label( $1, $3 );
     910                }
    1012911        ;
    1013912
     
    1025924        statement_decl
    1026925        | statement_decl_list statement_decl
    1027                 { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
     926                { if ( $1 != 0 ) { $1->set_last( $2 ); $$ = $1; } }
    1028927        ;
    1029928
     
    1032931                { $$ = new StatementNode( $1 ); }
    1033932        | EXTENSION declaration                                                         // GCC
    1034                 { distExt( $2 ); $$ = new StatementNode( $2 ); }
     933                {
     934                        distExt( $2 );
     935                        $$ = new StatementNode( $2 );
     936                }
    1035937        | function_definition
    1036938                { $$ = new StatementNode( $1 ); }
    1037939        | EXTENSION function_definition                                         // GCC
    1038                 { distExt( $2 ); $$ = new StatementNode( $2 ); }
     940                {
     941                        distExt( $2 );
     942                        $$ = new StatementNode( $2 );
     943                }
    1039944        | statement
    1040945        ;
     
    1043948        statement
    1044949        | statement_list_nodecl statement
    1045                 { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
     950                { if ( $1 != 0 ) { $1->set_last( $2 ); $$ = $1; } }
    1046951        ;
    1047952
     
    1087992if_control_expression:
    1088993        comma_expression
    1089                 { $$ = new IfCtrl( nullptr, $1 ); }
     994                { $$ = new IfCtl( nullptr, $1 ); }
    1090995        | c_declaration                                                                         // no semi-colon
    1091                 { $$ = new IfCtrl( $1, nullptr ); }
     996                { $$ = new IfCtl( $1, nullptr ); }
    1092997        | cfa_declaration                                                                       // no semi-colon
    1093                 { $$ = new IfCtrl( $1, nullptr ); }
     998                { $$ = new IfCtl( $1, nullptr ); }
    1094999        | declaration comma_expression                                          // semi-colon separated
    1095                 { $$ = new IfCtrl( $1, $2 ); }
     1000                { $$ = new IfCtl( $1, $2 ); }
    10961001        ;
    10971002
     
    11491054        WHILE '(' push if_control_expression ')' statement pop
    11501055                { $$ = new StatementNode( build_while( $4, $6 ) ); }
    1151         | WHILE '(' ')' statement                                                       // CFA => while ( 1 )
    1152                 { $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), $4 ) ); }
    11531056        | DO statement WHILE '(' comma_expression ')' ';'
    11541057                { $$ = new StatementNode( build_do_while( $5, $2 ) ); }
    1155         | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    1156                 { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), $2 ) ); }
    1157         | FOR '(' push for_control_expression_list ')' statement pop
     1058        | FOR '(' push for_control_expression ')' statement pop
    11581059                { $$ = new StatementNode( build_for( $4, $6 ) ); }
    1159         | FOR '(' ')' statement                                                         // CFA => for ( ;; )
    1160                 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), $4 ) ); }
    1161         ;
    1162 
    1163 for_control_expression_list:
    1164         for_control_expression
    1165         | for_control_expression_list ':' for_control_expression
    1166                 // ForCtrl + ForCtrl:
    1167                 //    init + init => multiple declaration statements that are hoisted
    1168                 //    condition + condition => (expression) && (expression)
    1169                 //    change + change => (expression), (expression)
    1170                 {
    1171                         $1->init->set_last( $3->init );
    1172                         if ( $1->condition ) {
    1173                                 if ( $3->condition ) {
    1174                                         $1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true ) );
    1175                                 } // if
    1176                         } else $1->condition = $3->condition;
    1177                         if ( $1->change ) {
    1178                                 if ( $3->change ) {
    1179                                         $1->change->expr.reset( new CommaExpr( $1->change->expr.release(), $3->change->expr.release() ) );
    1180                                 } // if
    1181                         } else $1->change = $3->change;
    1182                         $$ = $1;
    1183                 }
    11841060        ;
    11851061
    11861062for_control_expression:
    1187         ';' comma_expression_opt ';' comma_expression_opt
    1188                 { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); }
    1189         | comma_expression ';' comma_expression_opt ';' comma_expression_opt
    1190                 { $$ = new ForCtrl( $1, $3, $5 ); }
    1191         | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';'
    1192                 { $$ = new ForCtrl( $1, $2, $4 ); }
    1193 
    1194         | comma_expression                                                                      // CFA
    1195                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    1196                                                 OperKinds::LThan, $1->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1197         | comma_expression inclexcl comma_expression            // CFA
    1198                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1199         | comma_expression inclexcl comma_expression '~' comma_expression // CFA
    1200                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, $5 ); }
    1201         | comma_expression ';' comma_expression                         // CFA
    1202                 { $$ = forCtrl( $3, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    1203                                                 OperKinds::LThan, $3->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1204         | comma_expression ';' comma_expression inclexcl comma_expression // CFA
    1205                 { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1206         | comma_expression ';' comma_expression inclexcl comma_expression '~' comma_expression // CFA
    1207                 { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, $7 ); }
    1208 
    1209                 // There is a S/R conflicit if ~ and -~ are factored out.
    1210         | comma_expression ';' comma_expression '~' '@'         // CFA
    1211                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1212         | comma_expression ';' comma_expression ErangeDown '@' // CFA
    1213                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::GThan, nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1214         | comma_expression ';' comma_expression '~' '@' '~' comma_expression // CFA
    1215                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, $7 ); }
    1216         | comma_expression ';' comma_expression ErangeDown '@' '~' comma_expression // CFA
    1217                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::GThan, nullptr, $7 ); }
    1218         | comma_expression ';' comma_expression '~' '@' '~' '@' // CFA
    1219                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, nullptr ); }
    1220         ;
    1221 
    1222 inclexcl:
    1223         '~'
    1224                 { $$ = OperKinds::LThan; }
    1225         | ErangeUpEq
    1226                 { $$ = OperKinds::LEThan; }
    1227         | ErangeDown
    1228                 { $$ = OperKinds::GThan; }
    1229         | ErangeDownEq
    1230                 { $$ = OperKinds::GEThan; }
     1063        comma_expression_opt ';' comma_expression_opt ';' comma_expression_opt
     1064                { $$ = new ForCtl( $1, $3, $5 ); }
     1065        | declaration comma_expression_opt ';' comma_expression_opt // C99
     1066                { $$ = new ForCtl( $1, $2, $4 ); }
    12311067        ;
    12321068
     
    12611097        | RETURN comma_expression_opt ';'
    12621098                { $$ = new StatementNode( build_return( $2 ) ); }
    1263         | RETURN '{' initializer_list_opt comma_opt '}' ';'
     1099        | RETURN '{' initializer_list_opt comma_opt '}'
    12641100                { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
    1265         // | SUSPEND ';'
    1266         //      { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
    1267         // | SUSPEND compound_statement ';'
    1268         //      { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
    12691101        | THROW assignment_expression_opt ';'                           // handles rethrow
    12701102                { $$ = new StatementNode( build_throw( $2 ) ); }
     
    13041136
    13051137waitfor:
    1306         WAITFOR '(' cast_expression ')'
    1307                 { $$ = $3; }
    1308         | WAITFOR '(' cast_expression ',' argument_expression_list ')'
    1309                 { $$ = (ExpressionNode *)$3->set_last( $5 ); }
     1138        WAITFOR '(' identifier ')'
     1139                {
     1140                        $$ = new ExpressionNode( new NameExpr( *$3 ) );
     1141                        delete $3;
     1142                }
     1143        | WAITFOR '(' identifier ',' argument_expression_list ')'
     1144                {
     1145                        $$ = new ExpressionNode( new NameExpr( *$3 ) );
     1146                        $$->set_last( $5 );
     1147                        delete $3;
     1148                }
    13101149        ;
    13111150
     
    13241163                { $$ = build_waitfor_timeout( nullptr, $3, $1 ); }
    13251164                // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1326         | when_clause_opt timeout statement WOR ELSE statement
    1327                 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    13281165        | when_clause_opt timeout statement WOR when_clause ELSE statement
    13291166                { $$ = build_waitfor_timeout( $2, $3, $1, $7, $5 ); }
     
    13471184
    13481185handler_clause:
    1349         handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
     1186        handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement pop
    13501187                { $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); }
    1351         | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
     1188        | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement pop
    13521189                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $5, $7, $9 ) ) ); }
    13531190        ;
     
    13751212        | type_specifier_nobody variable_abstract_declarator
    13761213                { $$ = $2->addType( $1 ); }
    1377         | cfa_abstract_declarator_tuple identifier                      // CFA
     1214        | cfa_abstract_declarator_tuple no_attr_identifier      // CFA
    13781215                { $$ = $1->addName( $2 ); }
    13791216        | cfa_abstract_declarator_tuple                                         // CFA
     
    14391276
    14401277label_list:
    1441         identifier
     1278        no_attr_identifier
    14421279                {
    14431280                        $$ = new LabelNode(); $$->labels.push_back( *$1 );
    14441281                        delete $1;                                                                      // allocated by lexer
    14451282                }
    1446         | label_list ',' identifier
     1283        | label_list ',' no_attr_identifier
    14471284                {
    14481285                        $$ = $1; $1->labels.push_back( *$3 );
     
    14891326
    14901327local_label_list:                                                                               // GCC, local label
    1491         identifier_or_type_name
    1492         | local_label_list ',' identifier_or_type_name
     1328        no_attr_identifier_or_type_name
     1329        | local_label_list ',' no_attr_identifier_or_type_name
    14931330        ;
    14941331
     
    16121449                        $$ = $2->addTypedef();
    16131450                }
    1614         | cfa_typedef_declaration pop ',' push identifier
     1451        | cfa_typedef_declaration pop ',' push no_attr_identifier
    16151452                {
    16161453                        typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "3" );
     
    16521489typedef_expression:
    16531490                // GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
    1654         TYPEDEF identifier '=' assignment_expression
     1491        TYPEDEF no_attr_identifier '=' assignment_expression
    16551492                {
    16561493                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
    16571494                        SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
    16581495                }
    1659         | typedef_expression pop ',' push identifier '=' assignment_expression
     1496        | typedef_expression pop ',' push no_attr_identifier '=' assignment_expression
    16601497                {
    16611498                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
     
    18261663        | INT128
    18271664                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 ); }
    1828         | UINT128
    1829                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ); }
    18301665        | FLOAT
    18311666                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
     1667        | FLOAT80
     1668                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float80 ); }
     1669        | FLOAT128
     1670                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float128 ); }
    18321671        | DOUBLE
    18331672                { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
    1834         | uuFLOAT80
    1835                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uuFloat80 ); }
    1836         | uuFLOAT128
    1837                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uuFloat128 ); }
    1838         | uFLOAT16
    1839                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat16 ); }
    1840         | uFLOAT32
    1841                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat32 ); }
    1842         | uFLOAT32X
    1843                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat32x ); }
    1844         | uFLOAT64
    1845                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat64 ); }
    1846         | uFLOAT64X
    1847                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat64x ); }
    1848         | uFLOAT128
    1849                 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat128 ); }
    18501673        | COMPLEX                                                                                       // C99
    18511674                { $$ = DeclarationNode::newComplexType( DeclarationNode::Complex ); }
     
    18621685        | VALIST                                                                                        // GCC, __builtin_va_list
    18631686                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Valist ); }
    1864         | AUTO_TYPE
    1865                 { $$ = DeclarationNode::newBuiltinType( DeclarationNode::AutoType ); }
    18661687        ;
    18671688
     
    18971718
    18981719indirect_type:
    1899         TYPEOF '(' type ')'                                                                     // GCC: typeof( x ) y;
     1720        TYPEOF '(' type ')'                                                                     // GCC: typeof(x) y;
    19001721                { $$ = $3; }
    1901         | TYPEOF '(' comma_expression ')'                                       // GCC: typeof( a+b ) y;
     1722        | TYPEOF '(' comma_expression ')'                                       // GCC: typeof(a+b) y;
    19021723                { $$ = DeclarationNode::newTypeof( $3 ); }
    1903         | BASETYPEOF '(' type ')'                                                       // CFA: basetypeof( x ) y;
    1904                 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ), true ); }
    1905         | BASETYPEOF '(' comma_expression ')'                           // CFA: basetypeof( a+b ) y;
    1906                 { $$ = DeclarationNode::newTypeof( $3, true ); }
     1724        | ATTR_TYPEGENname '(' type ')'                                         // CFA: e.g., @type(x) y;
     1725                { $$ = DeclarationNode::newAttr( $1, $3 ); }
     1726        | ATTR_TYPEGENname '(' comma_expression ')'                     // CFA: e.g., @type(a+b) y;
     1727                { $$ = DeclarationNode::newAttr( $1, $3 ); }
    19071728        | ZERO_T                                                                                        // CFA
    19081729                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Zero ); }
     
    19281749                { $$ = $3->addQualifiers( $1 ); }
    19291750        | sue_type_specifier type_qualifier
    1930                 {
    1931                         if ( $2->type != nullptr && $2->type->forall ) forall = true; // remember generic type
    1932                         $$ = $1->addQualifiers( $2 );
    1933                 }
     1751                { $$ = $1->addQualifiers( $2 ); }
    19341752        ;
    19351753
     
    19741792                { $$ = DeclarationNode::newFromTypedef( $1 ); }
    19751793        | '.' TYPEDEFname
    1976                 { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), DeclarationNode::newFromTypedef( $2 ) ); }
     1794                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    19771795        | type_name '.' TYPEDEFname
    1978                 { $$ = DeclarationNode::newQualifiedType( $1, DeclarationNode::newFromTypedef( $3 ) ); }
     1796                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    19791797        | typegen_name
    19801798        | '.' typegen_name
    1981                 { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), $2 ); }
     1799                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    19821800        | type_name '.' typegen_name
    1983                 { $$ = DeclarationNode::newQualifiedType( $1, $3 ); }
     1801                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    19841802        ;
    19851803
     
    20031821        ;
    20041822
    2005 fred:
    2006         // empty
    2007                 { yyy = false; }
    2008         ;
    2009 
    20101823aggregate_type:                                                                                 // struct, union
    2011         aggregate_key attribute_list_opt
    2012                 { forall = false; }                                                             // reset
    2013           '{' field_declaration_list_opt '}' type_parameters_opt
    2014                 { $$ = DeclarationNode::newAggregate( $1, nullptr, $7, $5, true )->addQualifiers( $2 ); }
    2015         | aggregate_key attribute_list_opt identifier fred
    2016                 {
    2017                         typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname ); // create typedef
     1824        aggregate_key attribute_list_opt '{' field_declaration_list_opt '}'
     1825                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), nullptr, $4, true )->addQualifiers( $2 ); }
     1826        | aggregate_key attribute_list_opt no_attr_identifier
     1827                {
     1828                        typedefTable.makeTypedef( *$3, forall ? TYPEGENname : TYPEDEFname ); // create typedef
     1829                        //if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
    20181830                        forall = false;                                                         // reset
    20191831                }
    2020           '{' field_declaration_list_opt '}' type_parameters_opt
    2021                 { $$ = DeclarationNode::newAggregate( $1, $3, $9, $7, true )->addQualifiers( $2 ); }
    2022         | aggregate_key attribute_list_opt type_name fred
    2023                 {
    2024                         // for type_name can be a qualified type name S.T, in which case only the last name in the chain needs a typedef (other names in the chain should already have one)
    2025                         typedefTable.makeTypedef( *$3->type->leafName(), forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname ); // create typedef
     1832          '{' field_declaration_list_opt '}'
     1833                { $$ = DeclarationNode::newAggregate( $1, $3, nullptr, $6, true )->addQualifiers( $2 ); }
     1834        | aggregate_key attribute_list_opt type_name
     1835                {
     1836                        typedefTable.makeTypedef( *$3->type->symbolic.name, forall ? TYPEGENname : TYPEDEFname ); // create typedef
     1837                        //if ( forall ) typedefTable.changeKind( *$3->type->symbolic.name, TYPEGENname ); // possibly update
    20261838                        forall = false;                                                         // reset
    20271839                }
    2028           '{' field_declaration_list_opt '}' type_parameters_opt
    2029                 { $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $9, $7, true )->addQualifiers( $2 ); }
     1840          '{' field_declaration_list_opt '}'
     1841                { $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, nullptr, $6, true )->addQualifiers( $2 ); }
     1842        | aggregate_key attribute_list_opt '(' type_list ')' '{' field_declaration_list_opt '}' // CFA
     1843                { $$ = DeclarationNode::newAggregate( $1, new string( DeclarationNode::anonymous.newName() ), $4, $7, false )->addQualifiers( $2 ); }
    20301844        | aggregate_type_nobody
    20311845        ;
    20321846
    2033 type_parameters_opt:
    2034         // empty
    2035                 { $$ = nullptr; }                                                               %prec '}'
    2036         | '(' type_list ')'
    2037                 { $$ = $2; }
    2038         ;
    2039 
    20401847aggregate_type_nobody:                                                                  // struct, union - {...}
    2041         aggregate_key attribute_list_opt identifier fred
    2042                 {
    2043                         typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname );
     1848        aggregate_key attribute_list_opt no_attr_identifier
     1849                {
     1850                        typedefTable.makeTypedef( *$3, forall ? TYPEGENname : TYPEDEFname );
     1851                        //if ( forall ) typedefTable.changeKind( *$3, TYPEGENname ); // possibly update
    20441852                        forall = false;                                                         // reset
    20451853                        $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
    20461854                }
    2047         | aggregate_key attribute_list_opt type_name fred
    2048                 {
    2049                         forall = false;                                                         // reset
     1855        | aggregate_key attribute_list_opt type_name
     1856                {
    20501857                        // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is
    20511858                        // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and
     
    20601867aggregate_key:
    20611868        STRUCT
    2062                 { yyy = true; $$ = DeclarationNode::Struct; }
     1869                { $$ = DeclarationNode::Struct; }
    20631870        | UNION
    2064                 { yyy = true; $$ = DeclarationNode::Union; }
     1871                { $$ = DeclarationNode::Union; }
    20651872        | EXCEPTION
    2066                 { yyy = true; $$ = DeclarationNode::Exception; }
    2067         | GENERATOR
    2068                 { yyy = true; $$ = DeclarationNode::Coroutine; }
     1873                { $$ = DeclarationNode::Exception; }
    20691874        | COROUTINE
    2070                 { yyy = true; $$ = DeclarationNode::Coroutine; }
     1875                { $$ = DeclarationNode::Coroutine; }
    20711876        | MONITOR
    2072                 { yyy = true; $$ = DeclarationNode::Monitor; }
     1877                { $$ = DeclarationNode::Monitor; }
    20731878        | THREAD
    2074                 { yyy = true; $$ = DeclarationNode::Thread; }
     1879                { $$ = DeclarationNode::Thread; }
    20751880        ;
    20761881
     
    20831888
    20841889field_declaration:
    2085         type_specifier field_declaring_list_opt ';'
    2086                 { $$ = fieldDecl( $1, $2 ); }
    2087         | EXTENSION type_specifier field_declaring_list_opt ';' // GCC
    2088                 { $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
    2089         | INLINE type_specifier field_abstract_list_opt ';'     // CFA
    2090                 {
    2091                         if ( ! $3 ) {                                                           // field declarator ?
    2092                                 $3 = DeclarationNode::newName( nullptr );
    2093                         } // if
    2094                         $3->inLine = true;
    2095                         $$ = distAttr( $2, $3 );                                        // mark all fields in list
    2096                         distInl( $3 );
    2097                 }
     1890        type_specifier field_declaring_list ';'
     1891                { $$ = distAttr( $1, $2 ); }
     1892        | EXTENSION type_specifier field_declaring_list ';'     // GCC
     1893                { distExt( $3 ); $$ = distAttr( $2, $3 ); }             // mark all fields in list
    20981894        | typedef_declaration ';'                                                       // CFA
     1895                { SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
    20991896        | cfa_field_declaring_list ';'                                          // CFA, new style field declaration
    21001897        | EXTENSION cfa_field_declaring_list ';'                        // GCC
    21011898                { distExt( $2 ); $$ = $2; }                                             // mark all fields in list
    2102         | INLINE cfa_field_abstract_list ';'                            // CFA, new style field declaration
    2103                 { $$ = $2; }                                                                    // mark all fields in list
    21041899        | cfa_typedef_declaration ';'                                           // CFA
     1900                { SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
    21051901        | static_assert                                                                         // C11
    21061902        ;
    21071903
    2108 field_declaring_list_opt:
     1904cfa_field_declaring_list:                                                               // CFA, new style field declaration
     1905        cfa_abstract_declarator_tuple                                           // CFA, no field name
     1906        | cfa_abstract_declarator_tuple no_attr_identifier_or_type_name
     1907                { $$ = $1->addName( $2 ); }
     1908        | cfa_field_declaring_list ',' no_attr_identifier_or_type_name
     1909                { $$ = $1->appendList( $1->cloneType( $3 ) ); }
     1910        | cfa_field_declaring_list ','                                          // CFA, no field name
     1911                { $$ = $1->appendList( $1->cloneType( 0 ) ); }
     1912        ;
     1913
     1914field_declaring_list:
     1915        field_declarator_opt
     1916        | field_declaring_list ',' attribute_list_opt field_declarator_opt
     1917                { $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
     1918        ;
     1919
     1920field_declarator_opt:
    21091921        // empty
    2110                 { $$ = nullptr; }
    2111         | field_declarator
    2112         | field_declaring_list_opt ',' attribute_list_opt field_declarator
    2113                 { $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
    2114         ;
    2115 
    2116 field_declarator:
    2117         bit_subrange_size                                                                       // C special case, no field name
     1922                { $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name
     1923        // '@'
     1924        //      { $$ = DeclarationNode::newName( new string( DeclarationNode::anonymous.newName() ) ); } // CFA, no field name
     1925        | bit_subrange_size                                                                     // no field name
    21181926                { $$ = DeclarationNode::newBitfield( $1 ); }
    21191927        | variable_declarator bit_subrange_size_opt
    2120                 // A semantic check is required to ensure bit_subrange only appears on integral types.
     1928                // A semantic check is required to ensure bit_subrange only appears on base type int.
    21211929                { $$ = $1->addBitfield( $2 ); }
    21221930        | variable_type_redeclarator bit_subrange_size_opt
    2123                 // A semantic check is required to ensure bit_subrange only appears on integral types.
     1931                // A semantic check is required to ensure bit_subrange only appears on base type int.
    21241932                { $$ = $1->addBitfield( $2 ); }
    2125         ;
    2126 
    2127 field_abstract_list_opt:
    2128         // empty
    2129                 { $$ = nullptr; }
    2130         | field_abstract
    2131         | field_abstract_list_opt ',' attribute_list_opt field_abstract
    2132                 { $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
    2133         ;
    2134 
    2135 field_abstract:
    2136                 //      no bit fields
    2137         variable_abstract_declarator
    2138         ;
    2139 
    2140 cfa_field_declaring_list:                                                               // CFA, new style field declaration
    2141         // bit-fields are handled by C declarations
    2142         cfa_abstract_declarator_tuple identifier_or_type_name
    2143                 { $$ = $1->addName( $2 ); }
    2144         | cfa_field_declaring_list ',' identifier_or_type_name
    2145                 { $$ = $1->appendList( $1->cloneType( $3 ) ); }
    2146         ;
    2147 
    2148 cfa_field_abstract_list:                                                                // CFA, new style field declaration
    2149         // bit-fields are handled by C declarations
    2150         cfa_abstract_declarator_tuple
    2151         | cfa_field_abstract_list ','
    2152                 { $$ = $1->appendList( $1->cloneType( 0 ) ); }
     1933        | variable_abstract_declarator                                          // CFA, no field name
    21531934        ;
    21541935
     
    21601941
    21611942bit_subrange_size:
    2162         ':' assignment_expression
     1943        ':' constant_expression
    21631944                { $$ = $2; }
    21641945        ;
     
    21661947enum_type:                                                                                              // enum
    21671948        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    2168                 { $$ = DeclarationNode::newEnum( nullptr, $4, true )->addQualifiers( $2 ); }
    2169         | ENUM attribute_list_opt identifier
     1949                { $$ = DeclarationNode::newEnum( new string( DeclarationNode::anonymous.newName() ), $4, true )->addQualifiers( $2 ); }
     1950        | ENUM attribute_list_opt no_attr_identifier
    21701951                { typedefTable.makeTypedef( *$3 ); }
    21711952          '{' enumerator_list comma_opt '}'
     
    21781959
    21791960enum_type_nobody:                                                                               // enum - {...}
    2180         ENUM attribute_list_opt identifier
     1961        ENUM attribute_list_opt no_attr_identifier
    21811962                {
    21821963                        typedefTable.makeTypedef( *$3 );
     
    21911972
    21921973enumerator_list:
    2193         identifier_or_type_name enumerator_value_opt
     1974        no_attr_identifier_or_type_name enumerator_value_opt
    21941975                { $$ = DeclarationNode::newEnumConstant( $1, $2 ); }
    2195         | enumerator_list ',' identifier_or_type_name enumerator_value_opt
     1976        | enumerator_list ',' no_attr_identifier_or_type_name enumerator_value_opt
    21961977                { $$ = $1->appendList( DeclarationNode::newEnumConstant( $3, $4 ) ); }
    21971978        ;
     
    23012082
    23022083identifier_list:                                                                                // K&R-style parameter list => no types
    2303         identifier
     2084        no_attr_identifier
    23042085                { $$ = DeclarationNode::newName( $1 ); }
    2305         | identifier_list ',' identifier
     2086        | identifier_list ',' no_attr_identifier
    23062087                { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
    23072088        ;
     
    23092090identifier_or_type_name:
    23102091        identifier
     2092        | TYPEDEFname
     2093        | TYPEGENname
     2094        ;
     2095
     2096no_attr_identifier_or_type_name:
     2097        no_attr_identifier
    23112098        | TYPEDEFname
    23122099        | TYPEGENname
     
    23632150designation:
    23642151        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    2365         | identifier ':'                                                                        // GCC, field name
     2152        | no_attr_identifier ':'                                                        // GCC, field name
    23662153                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    23672154        ;
     
    23752162
    23762163designator:
    2377         '.' identifier                                                                          // C99, field name
     2164        '.' no_attr_identifier                                                          // C99, field name
    23782165                { $$ = new ExpressionNode( build_varref( $2 ) ); }
    23792166        | '[' push assignment_expression pop ']'                        // C99, single array element
     
    23842171        | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
    23852172                { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild< Expression >( $3 ), maybeMoveBuild< Expression >( $5 ) ) ); }
    2386         | '.' '[' push field_name_list pop ']'                          // CFA, tuple field selector
     2173        | '.' '[' push field_list pop ']'                                       // CFA, tuple field selector
    23872174                { $$ = $4; }
    23882175        ;
     
    24202207
    24212208type_parameter:                                                                                 // CFA
    2422         type_class identifier_or_type_name
     2209        type_class no_attr_identifier_or_type_name
    24232210                { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
    24242211          type_initializer_opt assertion_list_opt
     
    24532240
    24542241assertion:                                                                                              // CFA
    2455         '|' identifier_or_type_name '(' type_list ')'
     2242        '|' no_attr_identifier_or_type_name '(' type_list ')'
    24562243                { $$ = DeclarationNode::newTraitUse( $2, $4 ); }
    24572244        | '|' '{' push trait_declaration_list pop '}'
     
    24652252                { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
    24662253        | assignment_expression
    2467                 { SemanticError( yylloc, toString("Expression generic parameters are currently unimplemented: ", $1->build()) ); $$ = nullptr; }
    24682254        | type_list ',' type
    24692255                { $$ = (ExpressionNode *)( $1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) ) ); }
    24702256        | type_list ',' assignment_expression
    2471                 { SemanticError( yylloc, toString("Expression generic parameters are currently unimplemented: ", $3->build()) ); $$ = nullptr; }
    2472                 // { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
     2257                { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
    24732258        ;
    24742259
     
    24902275
    24912276type_declarator_name:                                                                   // CFA
    2492         identifier_or_type_name
     2277        no_attr_identifier_or_type_name
    24932278                {
    24942279                        typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
    24952280                        $$ = DeclarationNode::newTypeDecl( $1, 0 );
    24962281                }
    2497         | identifier_or_type_name '(' type_parameter_list ')'
     2282        | no_attr_identifier_or_type_name '(' type_parameter_list ')'
    24982283                {
    24992284                        typedefTable.addToEnclosingScope( *$1, TYPEGENname, "11" );
     
    25032288
    25042289trait_specifier:                                                                                // CFA
    2505         TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
     2290        TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    25062291                { $$ = DeclarationNode::newTrait( $2, $4, 0 ); }
    2507         | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
     2292        | TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    25082293                { $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
    25092294        ;
     
    25372322
    25382323translation_unit:
    2539         // empty, input file
     2324        // empty
     2325                {}                                                                                              // empty input file
    25402326        | external_definition_list
    25412327                { parseTree = parseTree ? parseTree->appendList( $1 ) : $1;     }
     
    25452331        push external_definition pop
    25462332                { $$ = $2; }
    2547         | external_definition_list push external_definition pop
     2333        | external_definition_list
     2334                { forall = xxx; }
     2335          push external_definition pop
     2336                { $$ = $1 ? $1->appendList( $4 ) : $4; }
     2337        ;
     2338
     2339        // SKULLDUGGERY: Declarations in extern "X" and distribution need to be added to the current lexical scope.
     2340        // However, external_definition_list creates a new scope around each external_definition, but the pop loses all the
     2341        // types in the extern "X" and distribution at the end of the block. This version of external_definition_list does
     2342
     2343        // not do push/pop for declarations at the level of the extern "X" and distribution block. Any recursive uses of
     2344        // external_definition_list within the extern "X" and distribution block correctly pushes/pops for that scope level.
     2345external_definition_list_no_pop_push:
     2346        external_definition
     2347        | external_definition_list_no_pop_push
     2348                { forall = xxx; }
     2349          external_definition
    25482350                { $$ = $1 ? $1->appendList( $3 ) : $3; }
    25492351        ;
     
    25522354        // empty
    25532355                { $$ = nullptr; }
    2554         | external_definition_list
    2555         ;
    2556 
    2557 up:
    2558                 { typedefTable.up( forall ); forall = false; }
    2559         ;
    2560 
    2561 down:
    2562                 { typedefTable.down(); }
     2356        | external_definition_list_no_pop_push
    25632357        ;
    25642358
     
    25802374                        linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
    25812375                }
    2582           '{' up external_definition_list_opt down '}'
     2376          '{' external_definition_list_opt '}'
    25832377                {
    25842378                        linkage = linkageStack.top();
    25852379                        linkageStack.pop();
    2586                         $$ = $6;
     2380                        $$ = $5;
    25872381                }
    25882382        | type_qualifier_list
    2589                 {
    2590                         if ( $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    2591                         if ( $1->type->forall ) forall = true;          // remember generic type
    2592                 }
    2593           '{' up external_definition_list_opt down '}'          // CFA, namespace
    2594                 {
    2595                         distQual( $5, $1 );
    2596                         forall = false;
     2383                { if ( $1->type->forall ) xxx = forall = true; } // remember generic type
     2384          '{' external_definition_list_opt '}'                          // CFA, namespace
     2385                {
     2386                        for ( DeclarationNode * iter = $4; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     2387                                if ( isMangled( iter->linkage ) ) {             // ignore extern "C"
     2388                                        iter->addQualifiers( $1->clone() );
     2389                                } // if
     2390                        } // for
     2391                        xxx = false;
     2392                        delete $1;
     2393                        $$ = $4;
     2394                }
     2395        | declaration_qualifier_list
     2396                { if ( $1->type->forall ) xxx = forall = true; } // remember generic type
     2397          '{' external_definition_list_opt '}'                          // CFA, namespace
     2398                {
     2399                        for ( DeclarationNode * iter = $4; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     2400                                if ( isMangled( iter->linkage ) ) {             // ignore extern "C"
     2401                                        iter->addQualifiers( $1->clone() );
     2402                                } // if
     2403                        } // for
     2404                        xxx = false;
     2405                        delete $1;
     2406                        $$ = $4;
     2407                }
     2408        | declaration_qualifier_list type_qualifier_list
     2409                {
     2410                        // forall must be in the type_qualifier_list
     2411                        if ( $2->type->forall ) xxx = forall = true; // remember generic type
     2412                }
     2413          '{' external_definition_list_opt '}'                          // CFA, namespace
     2414                {
     2415                        for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
     2416                                if ( isMangled( iter->linkage ) && isMangled( $2->linkage ) ) { // ignore extern "C"
     2417                                        iter->addQualifiers( $1->clone() );
     2418                                        iter->addQualifiers( $2->clone() );
     2419                                } // if
     2420                        } // for
     2421                        xxx = false;
     2422                        delete $1;
     2423                        delete $2;
    25972424                        $$ = $5;
    2598                 }
    2599         | declaration_qualifier_list
    2600                 {
    2601                         if ( $1->type && $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    2602                         if ( $1->type && $1->type->forall ) forall = true; // remember generic type
    2603                 }
    2604           '{' up external_definition_list_opt down '}'          // CFA, namespace
    2605                 {
    2606                         distQual( $5, $1 );
    2607                         forall = false;
    2608                         $$ = $5;
    2609                 }
    2610         | declaration_qualifier_list type_qualifier_list
    2611                 {
    2612                         if ( ($1->type && $1->type->qualifiers.val) || $2->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    2613                         if ( ($1->type && $1->type->forall) || $2->type->forall ) forall = true; // remember generic type
    2614                 }
    2615           '{' up external_definition_list_opt down '}'          // CFA, namespace
    2616                 {
    2617                         distQual( $6, $1->addQualifiers( $2 ) );
    2618                         forall = false;
    2619                         $$ = $6;
    26202425                }
    26212426        ;
     
    29272732        typedef
    29282733                // hide type name in enclosing scope by variable name
    2929                 {
    2930                         // if ( ! typedefTable.existsCurr( *$1->name ) ) {
    2931                                 typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER, "ID" );
    2932                         // } else {
    2933                         //      SemanticError( yylloc, string("'") + *$1->name + "' redeclared as different kind of symbol." ); $$ = nullptr;
    2934                         // } // if
    2935                 }
     2734                { typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER, "ID" ); }
    29362735        | '(' paren_type ')'
    29372736                { $$ = $2; }
     
    29442743                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    29452744        | '(' type_ptr ')' attribute_list_opt
    2946                 { $$ = $2->addQualifiers( $4 ); }                               // redundant parenthesis
     2745                { $$ = $2->addQualifiers( $4 ); }
    29472746        ;
    29482747
  • src/ResolvExpr/AdjustExprType.cc

    rb067d9b r7951100  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // AdjustExprType_old.cc --
     7// AdjustExprType.cc --
    88//
    99// Author           : Richard C. Bilson
     
    1414//
    1515
    16 #include "AST/Node.hpp"
    17 #include "AST/Pass.hpp"
    18 #include "AST/SymbolTable.hpp"
    19 #include "AST/Type.hpp"
    20 #include "AST/TypeEnvironment.hpp"
    2116#include "Common/PassVisitor.h"
    2217#include "SymTab/Indexer.h"       // for Indexer
     
    2722
    2823namespace ResolvExpr {
    29 
    30 namespace {
    31         class AdjustExprType_old final : public WithShortCircuiting {
    32                 public:
    33                 AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer );
     24        class AdjustExprType : public WithShortCircuiting {
     25          public:
     26                AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer );
    3427                void premutate( VoidType * ) { visit_children = false; }
    3528                void premutate( BasicType * ) { visit_children = false; }
     
    4740                void premutate( OneType * ) { visit_children = false; }
    4841
    49                 Type * postmutate( ArrayType * arrayType );
    50                 Type * postmutate( FunctionType * functionType );
    51                 Type * postmutate( TypeInstType * aggregateUseType );
     42                Type * postmutate( ArrayType *arrayType );
     43                Type * postmutate( FunctionType *functionType );
     44                Type * postmutate( TypeInstType *aggregateUseType );
    5245
    53                 private:
     46          private:
    5447                const TypeEnvironment & env;
    5548                const SymTab::Indexer & indexer;
    5649        };
    5750
    58         AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer )
     51        void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     52                PassVisitor<AdjustExprType> adjuster( env, indexer );
     53                Type *newType = type->acceptMutator( adjuster );
     54                type = newType;
     55        }
     56
     57        void adjustExprType( Type *& type ) {
     58                TypeEnvironment env;
     59                SymTab::Indexer indexer;
     60                adjustExprType( type, env, indexer );
     61        }
     62
     63        AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer )
    5964                : env( env ), indexer( indexer ) {
    6065        }
    6166
    62         Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) {
    63                 PointerType * pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
     67        Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
     68                PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
    6469                arrayType->base = nullptr;
    6570                delete arrayType;
     
    6772        }
    6873
    69         Type * AdjustExprType_old::postmutate( FunctionType * functionType ) {
     74        Type * AdjustExprType::postmutate( FunctionType * functionType ) {
    7075                return new PointerType{ Type::Qualifiers(), functionType };
    7176        }
    7277
    73         Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) {
    74                 if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
     78        Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
     79                if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) {
    7580                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    7681                                return new PointerType{ Type::Qualifiers(), typeInst };
    7782                        }
    78                 } else if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
    79                         if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl * >( ntDecl ) ) {
     83                } else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
     84                        if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
    8085                                if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
    8186                                        return new PointerType{ Type::Qualifiers(), typeInst };
     
    8590                return typeInst;
    8691        }
    87 } // anonymous namespace
    88 
    89 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    90         PassVisitor<AdjustExprType_old> adjuster( env, indexer );
    91         Type * newType = type->acceptMutator( adjuster );
    92         type = newType;
    93 }
    94 
    95 void adjustExprType( Type *& type ) {
    96         TypeEnvironment env;
    97         SymTab::Indexer indexer;
    98         adjustExprType( type, env, indexer );
    99 }
    100 
    101 namespace {
    102         struct AdjustExprType_new final : public ast::WithShortCircuiting {
    103                 const ast::TypeEnvironment & tenv;
    104                 const ast::SymbolTable & symtab;
    105 
    106                 AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
    107                 : tenv( e ), symtab( syms ) {}
    108 
    109                 void premutate( const ast::VoidType * ) { visit_children = false; }
    110                 void premutate( const ast::BasicType * ) { visit_children = false; }
    111                 void premutate( const ast::PointerType * ) { visit_children = false; }
    112                 void premutate( const ast::ArrayType * ) { visit_children = false; }
    113                 void premutate( const ast::FunctionType * ) { visit_children = false; }
    114                 void premutate( const ast::StructInstType * ) { visit_children = false; }
    115                 void premutate( const ast::UnionInstType * ) { visit_children = false; }
    116                 void premutate( const ast::EnumInstType * ) { visit_children = false; }
    117                 void premutate( const ast::TraitInstType * ) { visit_children = false; }
    118                 void premutate( const ast::TypeInstType * ) { visit_children = false; }
    119                 void premutate( const ast::TupleType * ) { visit_children = false; }
    120                 void premutate( const ast::VarArgsType * ) { visit_children = false; }
    121                 void premutate( const ast::ZeroType * ) { visit_children = false; }
    122                 void premutate( const ast::OneType * ) { visit_children = false; }
    123 
    124                 const ast::Type * postmutate( const ast::ArrayType * at ) {
    125                         return new ast::PointerType{ at->base, at->qualifiers };
    126                 }
    127 
    128                 const ast::Type * postmutate( const ast::FunctionType * ft ) {
    129                         return new ast::PointerType{ ft };
    130                 }
    131 
    132                 const ast::Type * postmutate( const ast::TypeInstType * inst ) {
    133                         // replace known function-type-variables with pointer-to-function
    134                         if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
    135                                 if ( eqvClass->data.kind == ast::TypeVar::Ftype ) {
    136                                         return new ast::PointerType{ inst };
    137                                 }
    138                         } else if ( const ast::NamedTypeDecl * ntDecl = symtab.lookupType( inst->name ) ) {
    139                                 if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( ntDecl ) ) {
    140                                         if ( tyDecl->kind == ast::TypeVar::Ftype ) {
    141                                                 return new ast::PointerType{ inst };
    142                                         }
    143                                 }
    144                         }
    145                         return inst;
    146                 }
    147         };
    148 } // anonymous namespace
    149 
    150 const ast::Type * adjustExprType(
    151         const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
    152 ) {
    153         ast::Pass<AdjustExprType_new> adjuster{ env, symtab };
    154         return type->accept( adjuster );
    155 }
    156 
    15792} // namespace ResolvExpr
    15893
  • src/ResolvExpr/Alternative.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:44:23 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Thu Oct 11 10:55:00 2018
    13 // Update Count     : 3
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 23:54:23 2015
     13// Update Count     : 2
    1414//
    1515
     
    2020#include <utility>                       // for move
    2121
    22 #include "Common/utility.h"              // for cloneAll
     22#include "Common/utility.h"              // for maybeClone
    2323#include "ResolvExpr/Cost.h"             // for Cost, Cost::zero, operator<<
    2424#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     
    2727
    2828namespace ResolvExpr {
    29         Alternative::Alternative()
    30         : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {}
     29        Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {}
    3130
    32         Alternative::Alternative( Expression *expr, const TypeEnvironment &env )
    33         : cost( Cost::zero ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars(), need() {}
    34        
    35         Alternative::Alternative( const Alternative &o, Expression *expr, const Cost &cost )
    36         : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( o.env ), openVars( o.openVars ),
    37           need() { cloneAll( o.need, need ); }
     31        Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
     32                : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {}
    3833
    39         Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
    40                 const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost )
    41         : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ),
    42           need() { cloneAll( oneed, need ); }
     34        Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost )
     35                : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
    4336
    44         Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
    45                 const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost,
    46                 const Cost &cvtCost )
    47         : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ),
    48           need() { cloneAll( oneed, need ); }
    49        
    50         Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
    51                 const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost)
    52         : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ),
    53           need() { cloneAll( oneed, need ); }
    54        
    55         Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
    56                 const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost,
    57                 const Cost& cvtCost )
    58         : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ),
    59           need() { cloneAll( oneed, need ); }
    60        
    61         Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
    62                 AssertionSet &&needSet, const Cost &cost )
    63         : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( std::move(env) ),
    64           openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
    65        
    66         Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
    67                 AssertionSet &&needSet, const Cost &cost, const Cost &cvtCost )
    68         : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( std::move(env) ),
    69           openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
    70 
    71         Alternative::Alternative( const Alternative &other )
    72         : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ),
    73           env( other.env ), openVars( other.openVars ), need() { cloneAll( other.need, need ); }
     37        Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
     38        }
    7439
    7540        Alternative &Alternative::operator=( const Alternative &other ) {
     
    8045                expr = maybeClone( other.expr );
    8146                env = other.env;
    82                 openVars = other.openVars;
    83                 need.clear();
    84                 cloneAll( other.need, need );
    8547                return *this;
    8648        }
    8749
    88         Alternative::Alternative( Alternative && other )
    89         : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ),
    90           env( std::move( other.env ) ), openVars( std::move( other.openVars ) ),
    91           need( std::move( other.need ) ) { other.expr = nullptr; }
     50        Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) {
     51                other.expr = nullptr;
     52        }
    9253
    9354        Alternative & Alternative::operator=( Alternative && other ) {
     
    9859                expr = other.expr;
    9960                env = std::move( other.env );
    100                 openVars = std::move( other.openVars );
    101                 need = std::move( other.need );
    10261                other.expr = nullptr;
    10362                return *this;
     
    10564
    10665        Alternative::~Alternative() {
    107                 for ( AssertionItem& n : need ) { delete n.decl; }
    10866                delete expr;
    10967        }
     
    12078                        os << "Null expression!" << std::endl;
    12179                } // if
    122                 os << indent << "Environment:";
     80                os << indent << "Environment: ";
    12381                env.print( os, indent+1 );
    12482                os << std::endl;
     83        }
     84
     85        void splice( AltList& dst, AltList& src ) {
     86                dst.reserve( dst.size() + src.size() );
     87                for ( Alternative& alt : src ) {
     88                        dst.push_back( std::move(alt) );
     89                }
     90                src.clear();
     91        }
     92
     93        void spliceBegin( AltList& dst, AltList& src ) {
     94                splice( src, dst );
     95                dst.swap( src );
    12596        }
    12697
  • src/ResolvExpr/Alternative.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:45:43 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Thu Oct 11 10:55:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:36:36 2017
     13// Update Count     : 3
    1414//
    1515
     
    2020
    2121#include "Cost.h"             // for Cost
    22 #include "TypeEnvironment.h"  // for TypeEnvironment, AssertionSetValue
    23 
    24 #include "Common/utility.h"   // for maybeClone
     22#include "TypeEnvironment.h"  // for TypeEnvironment
    2523
    2624class Expression;
    2725
    2826namespace ResolvExpr {
    29         /// One assertion to resolve
    30         struct AssertionItem {
    31                 const DeclarationWithType* decl;
    32                 AssertionSetValue info;
    33 
    34                 AssertionItem() = default;
    35                 AssertionItem( const DeclarationWithType* decl, const AssertionSetValue& info )
    36                 : decl(decl), info(info) {}
    37                 AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {}
    38                 operator AssertionSet::value_type () const { return { decl, info }; }
    39 
    40                 // to support cloneAll
    41                 AssertionItem clone() const { return { maybeClone(decl), info }; }
    42         };
    43         /// A list of unresolved assertions
    44         using AssertionList = std::vector<AssertionItem>;
    45 
    46         /// Clones an assertion list into an assertion set
    47         static inline void cloneAll( const AssertionList& src, AssertionSet& dst ) {
    48                 for ( const AssertionItem& item : src ) {
    49                         dst.emplace( maybeClone(item.decl), item.info );
    50                 }
    51         }
    52 
    53         /// Clones an assertion set into an assertion list
    54         static inline void cloneAll( const AssertionSet& src, AssertionList& dst ) {
    55                 dst.reserve( dst.size() + src.size() );
    56                 for ( const auto& entry : src ) {
    57                         dst.emplace_back( maybeClone(entry.first), entry.second );
    58                 }
    59         }
    60 
    61         /// Clones an assertion list into an assertion list
    62         static inline void cloneAll( const AssertionList& src, AssertionList& dst ) {
    63                 dst.reserve( dst.size() + src.size() );
    64                 for ( const AssertionItem& item : src ) {
    65                         dst.emplace_back( maybeClone(item.decl), item.info );
    66                 }
    67         }
    68 
    69         /// One option for resolution of an expression
    7027        struct Alternative {
    7128                Alternative();
    72                 Alternative( Expression *expr, const TypeEnvironment &env );
    73                 Alternative( const Alternative &o, Expression *expr, const Cost &cost );
    74                 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars,
    75                         const AssertionList& need, const Cost &cost );
    76                 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars,
    77                         const AssertionList& need, const Cost &cost, const Cost &cvtCost );
    78                 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars,
    79                         const AssertionSet &need, const Cost &cost);
    80                 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars,
    81                         const AssertionSet &need, const Cost &cost, const Cost& cvtCost );
    82                 Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
    83                         AssertionSet &&need, const Cost &cost );
    84                 Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
    85                         AssertionSet &&need, const Cost &cost, const Cost &cvtCost );
     29                Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost );
     30                Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost );
    8631                Alternative( const Alternative &other );
    8732                Alternative &operator=( const Alternative &other );
     
    9944                }
    10045
    101                 /// Sorts by cost
    102                 bool operator< ( const Alternative& o ) const { return cost < o.cost; }
    103 
    104                 Cost cost;            ///< Cost of the whole expression
    105                 Cost cvtCost;         ///< Cost of conversions to the satisfying expression
    106                 Expression *expr;     ///< Satisfying expression
    107                 TypeEnvironment env;  ///< Containing type environment
    108                 OpenVarSet openVars;  ///< Open variables for environment
    109                 AssertionList need;   ///< Assertions which need to be resolved
     46                Cost cost;
     47                Cost cvtCost;
     48                Expression *expr;
     49                TypeEnvironment env;
    11050        };
    11151
    11252        typedef std::vector< Alternative > AltList;
     53
     54        /// Moves all elements from src to the end of dst
     55        void splice( AltList& dst, AltList& src );
     56
     57        /// Moves all elements from src to the beginning of dst
     58        void spliceBegin( AltList& dst, AltList& src );
    11359
    11460        static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) {
  • src/ResolvExpr/AlternativeFinder.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:52:08 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:35:00 2019
    13 // Update Count     : 38
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb 17 11:19:39 2018
     13// Update Count     : 33
    1414//
    1515
     
    2525#include <vector>                  // for vector
    2626
    27 #include "CompilationState.h"      // for resolvep
    2827#include "Alternative.h"           // for AltList, Alternative
    2928#include "AlternativeFinder.h"
    30 #include "AST/Expr.hpp"
    31 #include "AST/SymbolTable.hpp"
    32 #include "AST/Type.hpp"
    3329#include "Common/SemanticError.h"  // for SemanticError
    3430#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
     
    3733#include "InitTweak/InitTweak.h"   // for getFunctionName
    3834#include "RenameVars.h"            // for RenameVars, global_renamer
    39 #include "ResolveAssertions.h"     // for resolveAssertions
    4035#include "ResolveTypeof.h"         // for resolveTypeof
    4136#include "Resolver.h"              // for resolveStmtExpr
     
    5449#include "typeops.h"               // for adjustExprType, polyCost, castCost
    5550
     51extern bool resolvep;
    5652#define PRINT( text ) if ( resolvep ) { text }
    5753//#define DEBUG_COST
     54
     55using std::move;
     56
     57/// copies any copyable type
     58template<typename T>
     59T copy(const T& x) { return x; }
    5860
    5961namespace ResolvExpr {
     
    7981                void postvisit( OffsetofExpr * offsetofExpr );
    8082                void postvisit( OffsetPackExpr * offsetPackExpr );
     83                void postvisit( AttrExpr * attrExpr );
    8184                void postvisit( LogicalExpr * logicalExpr );
    8285                void postvisit( ConditionalExpr * conditionalExpr );
     
    99102                void addAnonConversions( const Alternative & alt );
    100103                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    101                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
     104                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
    102105                /// Adds alternatives for member expressions where the left side has tuple type
    103                 void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
     106                void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
    104107                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    105108                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    109112                /// Finds matching alternatives for a function, given a set of arguments
    110113                template<typename OutputIterator>
    111                 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out );
    112                 /// Sets up parameter inference for an output alternative
     114                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
     115                /// Checks if assertion parameters match for a new alternative
    113116                template< typename OutputIterator >
    114                 void inferParameters( Alternative &newAlt, OutputIterator out );
     117                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
    115118        private:
    116119                AlternativeFinder & altFinder;
     
    130133
    131134        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) {
    132                 Indenter indent = { indentAmt };
     135                Indenter indent = { Indenter::tabsize, indentAmt };
    133136                for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    134137                        i->print( os, indent );
     
    173176                                                selected[ mangleName ] = current;
    174177                                        } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
    175                                                 // if one of the candidates contains a deleted identifier, can pick the other, since
    176                                                 // deleted expressions should not be ambiguous if there is another option that is at least as good
    177                                                 if ( findDeletedExpr( candidate->expr ) ) {
    178                                                         // do nothing
    179                                                         PRINT( std::cerr << "candidate is deleted" << std::endl; )
    180                                                 } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
    181                                                         PRINT( std::cerr << "current is deleted" << std::endl; )
    182                                                         selected[ mangleName ] = current;
    183                                                 } else {
    184                                                         PRINT(
    185                                                                 std::cerr << "marking ambiguous" << std::endl;
    186                                                         )
    187                                                         mapPlace->second.isAmbiguous = true;
    188                                                 }
     178                                                PRINT(
     179                                                        std::cerr << "marking ambiguous" << std::endl;
     180                                                )
     181                                                mapPlace->second.isAmbiguous = true;
    189182                                        } else {
    190183                                                PRINT(
     
    241234        }
    242235
    243         void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
     236        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
    244237                PassVisitor<Finder> finder( *this );
    245238                expr->accept( finder );
    246                 if ( mode.failFast && alternatives.empty() ) {
     239                if ( failFast && alternatives.empty() ) {
    247240                        PRINT(
    248241                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    250243                        SemanticError( expr, "No reasonable alternatives for expression " );
    251244                }
    252                 if ( mode.satisfyAssns || mode.prune ) {
    253                         // trim candidates just to those where the assertions resolve
    254                         // - necessary pre-requisite to pruning
    255                         AltList candidates;
    256                         std::list<std::string> errors;
    257                         for ( unsigned i = 0; i < alternatives.size(); ++i ) {
    258                                 resolveAssertions( alternatives[i], indexer, candidates, errors );
    259                         }
    260                         // fail early if none such
    261                         if ( mode.failFast && candidates.empty() ) {
    262                                 std::ostringstream stream;
    263                                 stream << "No alternatives with satisfiable assertions for " << expr << "\n";
    264                                 //        << "Alternatives with failing assertions are:\n";
    265                                 // printAlts( alternatives, stream, 1 );
    266                                 for ( const auto& err : errors ) {
    267                                         stream << err;
    268                                 }
    269                                 SemanticError( expr->location, stream.str() );
    270                         }
    271                         // reset alternatives
    272                         alternatives = std::move( candidates );
    273                 }
    274                 if ( mode.prune ) {
     245                if ( prune ) {
    275246                        auto oldsize = alternatives.size();
    276247                        PRINT(
     
    280251                        AltList pruned;
    281252                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    282                         if ( mode.failFast && pruned.empty() ) {
     253                        if ( failFast && pruned.empty() ) {
    283254                                std::ostringstream stream;
    284255                                AltList winners;
     
    299270                }
    300271                // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    301                 if ( mode.adjust ) {
    302                         for ( Alternative& i : alternatives ) {
    303                                 adjustExprType( i.expr->get_result(), i.env, indexer );
     272                for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
     273                        if ( adjust ) {
     274                                adjustExprType( i->expr->get_result(), i->env, indexer );
    304275                        }
    305276                }
     
    313284
    314285        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    315                 find( expr, ResolvMode::withAdjustment() );
     286                find( expr, true );
    316287        }
    317288
    318289        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    319                 find( expr, ResolvMode::withoutPrune() );
     290                find( expr, true, false );
    320291        }
    321292
    322293        void AlternativeFinder::maybeFind( Expression * expr ) {
    323                 find( expr, ResolvMode::withoutFailFast() );
     294                find( expr, true, true, false );
    324295        }
    325296
     
    335306                }
    336307
    337                 if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
    338                         addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
    339                 } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
    340                         addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
     308                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
     309                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     310                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
     311                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    341312                } // if
    342313        }
    343314
    344315        template< typename StructOrUnionType >
    345         void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
     316        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
    346317                std::list< Declaration* > members;
    347318                aggInst->lookup( name, members );
    348319
    349320                for ( Declaration * decl : members ) {
    350                         if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
     321                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
    351322                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    352323                                // can't construct in place and use vector::back
    353                                 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
     324                                Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
    354325                                renameTypes( newAlt.expr );
    355326                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    361332        }
    362333
    363         void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) {
     334        void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    364335                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    365336                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    366                         auto val = constantExpr->intValue();
     337                        // xxx - this should be improved by memoizing the value of constant exprs
     338                        // during parsing and reusing that information here.
     339                        std::stringstream ss( constantExpr->get_constant()->get_value() );
     340                        int val = 0;
    367341                        std::string tmp;
    368                         if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    369                                 alternatives.push_back( Alternative{
    370                                         alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
     342                        if ( ss >> val && ! (ss >> tmp) ) {
     343                                if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
     344                                        alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
     345                                } // if
    371346                        } // if
     347                } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
     348                        // xxx - temporary hack until 0/1 are int constants
     349                        if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
     350                                std::stringstream ss( nameExpr->get_name() );
     351                                int val;
     352                                ss >> val;
     353                                alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
     354                        }
    372355                } // if
    373356        }
    374357
    375         void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) {
    376                 alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
    377         }
    378 
    379         Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
    380                         const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
     358        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
     359                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
     360        }
     361
     362        Cost computeConversionCost( Type * actualType, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
    381363                PRINT(
    382364                        std::cerr << std::endl << "converting ";
     
    388370                        std::cerr << std::endl;
    389371                )
    390                 Cost convCost = conversionCost( actualType, formalType, actualIsLvalue, indexer, env );
     372                Cost convCost = conversionCost( actualType, formalType, indexer, env );
    391373                PRINT(
    392374                        std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    403385
    404386        Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
    405                 Cost convCost = computeConversionCost(
    406                         actualExpr->result, formalType, actualExpr->get_lvalue(), indexer, env );
     387                Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env );
    407388
    408389                // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion.
     
    432413        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    433414                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
    434                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
    435                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
     415                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
     416                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
    436417
    437418                Cost convCost = Cost::zero;
    438                 std::list< DeclarationWithType* >& formals = function->parameters;
     419                std::list< DeclarationWithType* >& formals = function->get_parameters();
    439420                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    440                 std::list< Expression* >& actuals = appExpr->args;
    441 
    442                 for ( Expression*& actualExpr : actuals ) {
    443                         Type * actualType = actualExpr->result;
     421                std::list< Expression* >& actuals = appExpr->get_args();
     422
     423                for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
     424                        Type * actualType = (*actualExpr)->get_result();
    444425                        PRINT(
    445426                                std::cerr << "actual expression:" << std::endl;
    446                                 actualExpr->print( std::cerr, 8 );
     427                                (*actualExpr)->print( std::cerr, 8 );
    447428                                std::cerr << "--- results are" << std::endl;
    448429                                actualType->print( std::cerr, 8 );
    449430                        )
    450431                        if ( formal == formals.end() ) {
    451                                 if ( function->isVarArgs ) {
     432                                if ( function->get_isVarArgs() ) {
    452433                                        convCost.incUnsafe();
    453434                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    454435                                        // convert reference-typed expressions to value-typed expressions
    455                                         referenceToRvalueConversion( actualExpr, convCost );
     436                                        referenceToRvalueConversion( *actualExpr, convCost );
    456437                                        continue;
    457438                                } else {
     
    459440                                }
    460441                        }
    461                         if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
    462                                 // default arguments should be free - don't include conversion cost.
    463                                 // Unwrap them here because they are not relevant to the rest of the system.
    464                                 actualExpr = def->expr;
    465                                 ++formal;
    466                                 continue;
    467                         }
    468                         // mark conversion cost to formal and also specialization cost of formal type
    469442                        Type * formalType = (*formal)->get_type();
    470                         convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
    471                         convCost.decSpec( specCost( formalType ) );
     443                        convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
    472444                        ++formal; // can't be in for-loop update because of the continue
    473445                }
     
    476448                }
    477449
    478                 // specialization cost of return types can't be accounted for directly, it disables
    479                 // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    480                 //
    481                 //   forall(otype OS) {
    482                 //     void ?|?(OS&, int);  // with newline
    483                 //     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
    484                 //   }
    485 
    486                 // mark type variable and specialization cost of forall clause
    487                 convCost.incVar( function->forall.size() );
    488                 for ( TypeDecl* td : function->forall ) {
    489                         convCost.decSpec( td->assertions.size() );
     450                for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
     451                        convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    490452                }
    491453
     
    500462                                needAssertions[ *assert ].isUsed = true;
    501463                        }
    502                 }
    503         }
    504 
    505         /// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp)
    506         extern UniqueId globalResnSlot;
     464///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
     465                }
     466        }
     467
     468        static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
     469
     470        void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
     471                for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
     472                        if ( i->second.isUsed ) {
     473                                indexer.addId( i->first );
     474                        }
     475                }
     476        }
     477
     478        template< typename ForwardIterator, typename OutputIterator >
     479        void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     480                if ( begin == end ) {
     481                        if ( newNeed.empty() ) {
     482                                PRINT(
     483                                        std::cerr << "all assertions satisfied, output alternative: ";
     484                                        newAlt.print( std::cerr );
     485                                        std::cerr << std::endl;
     486                                );
     487                                *out++ = newAlt;
     488                                return;
     489                        } else if ( level >= recursionLimit ) {
     490                                SemanticError( newAlt.expr->location, "Too many recursive assertions" );
     491                        } else {
     492                                AssertionSet newerNeed;
     493                                PRINT(
     494                                        std::cerr << "recursing with new set:" << std::endl;
     495                                        printAssertionSet( newNeed, std::cerr, 8 );
     496                                )
     497                                inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
     498                                return;
     499                        }
     500                }
     501
     502                ForwardIterator cur = begin++;
     503                if ( ! cur->second.isUsed ) {
     504                        inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
     505                        return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
     506                }
     507                DeclarationWithType *curDecl = cur->first;
     508
     509                PRINT(
     510                        std::cerr << "inferRecursive: assertion is ";
     511                        curDecl->print( std::cerr );
     512                        std::cerr << std::endl;
     513                )
     514                std::list< SymTab::Indexer::IdData > candidates;
     515                decls.lookupId( curDecl->get_name(), candidates );
     516///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
     517                for ( const auto & data : candidates ) {
     518                        DeclarationWithType * candidate = data.id;
     519                        PRINT(
     520                                std::cerr << "inferRecursive: candidate is ";
     521                                candidate->print( std::cerr );
     522                                std::cerr << std::endl;
     523                        )
     524
     525                        AssertionSet newHave, newerNeed( newNeed );
     526                        TypeEnvironment newEnv( newAlt.env );
     527                        OpenVarSet newOpenVars( openVars );
     528                        Type *adjType = candidate->get_type()->clone();
     529                        adjustExprType( adjType, newEnv, indexer );
     530                        renameTyVars( adjType );
     531                        PRINT(
     532                                std::cerr << "unifying ";
     533                                curDecl->get_type()->print( std::cerr );
     534                                std::cerr << " with ";
     535                                adjType->print( std::cerr );
     536                                std::cerr << std::endl;
     537                        )
     538                        if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
     539                                PRINT(
     540                                        std::cerr << "success!" << std::endl;
     541                                )
     542                                SymTab::Indexer newDecls( decls );
     543                                addToIndexer( newHave, newDecls );
     544                                Alternative newerAlt( newAlt );
     545                                newerAlt.env = newEnv;
     546                                assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
     547
     548                                // everything with an empty idChain was pulled in by the current assertion.
     549                                // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found.
     550                                for ( auto & a : newerNeed ) {
     551                                        if ( a.second.idChain.empty() ) {
     552                                                a.second.idChain = cur->second.idChain;
     553                                                a.second.idChain.push_back( curDecl->get_uniqueId() );
     554                                        }
     555                                }
     556
     557                                Expression *varExpr = data.combine( newerAlt.cvtCost );
     558                                delete varExpr->get_result();
     559                                varExpr->set_result( adjType->clone() );
     560                                PRINT(
     561                                        std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
     562                                        curDecl->print( std::cerr );
     563                                        std::cerr << " with declaration " << candidate->get_uniqueId() << " ";
     564                                        candidate->print( std::cerr );
     565                                        std::cerr << std::endl;
     566                                )
     567                                // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter).
     568                                InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
     569                                for ( UniqueId id : cur->second.idChain ) {
     570                                        inferParameters = (*inferParameters)[ id ].inferParams.get();
     571                                }
     572                                // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
     573                                (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
     574                                inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
     575                        } else {
     576                                delete adjType;
     577                        }
     578                }
     579        }
    507580
    508581        template< typename OutputIterator >
    509         void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) {
    510                 // Set need bindings for any unbound assertions
    511                 UniqueId crntResnSlot = 0;  // matching ID for this expression's assertions
    512                 for ( auto& assn : newAlt.need ) {
    513                         // skip already-matched assertions
    514                         if ( assn.info.resnSlot != 0 ) continue;
    515                         // assign slot for expression if needed
    516                         if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
    517                         // fix slot to assertion
    518                         assn.info.resnSlot = crntResnSlot;
    519                 }
    520                 // pair slot to expression
    521                 if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); }
    522 
    523                 // add to output list, assertion resolution is deferred
    524                 *out++ = newAlt;
     582        void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
     583//      PRINT(
     584//          std::cerr << "inferParameters: assertions needed are" << std::endl;
     585//          printAll( need, std::cerr, 8 );
     586//          )
     587                SymTab::Indexer decls( indexer );
     588                // PRINT(
     589                //      std::cerr << "============= original indexer" << std::endl;
     590                //      indexer.print( std::cerr );
     591                //      std::cerr << "============= new indexer" << std::endl;
     592                //      decls.print( std::cerr );
     593                // )
     594                addToIndexer( have, decls );
     595                AssertionSet newNeed;
     596                PRINT(
     597                        std::cerr << "env is: " << std::endl;
     598                        newAlt.env.print( std::cerr, 0 );
     599                        std::cerr << std::endl;
     600                )
     601
     602                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
     603//      PRINT(
     604//          std::cerr << "declaration 14 is ";
     605//          Declaration::declFromId
     606//          *out++ = newAlt;
     607//          )
    525608        }
    526609
     
    528611        ConstantExpr* getDefaultValue( Initializer* init ) {
    529612                if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    530                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
    531                                 return dynamic_cast<ConstantExpr*>( ce->arg );
    532                         } else {
    533                                 return dynamic_cast<ConstantExpr*>( si->value );
     613                        if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
     614                                return dynamic_cast<ConstantExpr*>( ce->get_arg() );
    534615                        }
    535616                }
     
    578659
    579660                /// Gets the list of exploded alternatives for this pack
    580                 const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const {
     661                const ExplodedActual& getExpl( const ExplodedArgs& args ) const {
    581662                        return args[nextArg-1][explAlt];
    582663                }
     
    602683        /// Instantiates an argument to match a formal, returns false if no results left
    603684        bool instantiateArgument( Type* formalType, Initializer* initializer,
    604                         const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart,
     685                        const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
    605686                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    606687                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    792873                                                                indexer ) ) {
    793874                                                        results.emplace_back(
    794                                                                 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
     875                                                                i, cnstExpr, move(env), move(need), move(have),
    795876                                                                move(openVars), nextArg, nTuples );
    796877                                                }
     
    863944                }
    864945                // build and validate new alternative
    865                 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
     946                Alternative newAlt( appExpr, result.env, cost );
    866947                PRINT(
    867948                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    869950                        printAssertionSet( result.need, std::cerr, 8 );
    870951                )
    871                 inferParameters( newAlt, out );
     952                inferParameters( result.need, result.have, newAlt, result.openVars, out );
    872953        }
    873954
    874955        template<typename OutputIterator>
    875956        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    876                         FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) {
     957                        FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
    877958                OpenVarSet funcOpenVars;
    878959                AssertionSet funcNeed, funcHave;
     
    9841065                funcFinder.findWithAdjustment( untypedExpr->function );
    9851066                // if there are no function alternatives, then proceeding is a waste of time.
    986                 // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
    9871067                if ( funcFinder.alternatives.empty() ) return;
    9881068
     
    10061086
    10071087                // pre-explode arguments
    1008                 ExplodedArgs_old argExpansions;
     1088                ExplodedArgs argExpansions;
    10091089                argExpansions.reserve( argAlternatives.size() );
    10101090
     
    10121092                        argExpansions.emplace_back();
    10131093                        auto& argE = argExpansions.back();
    1014                         // argE.reserve( arg.alternatives.size() );
     1094                        argE.reserve( arg.alternatives.size() );
    10151095
    10161096                        for ( const Alternative& actual : arg ) {
     
    10981178                                std::cerr << "bindings are:" << std::endl;
    10991179                                withFunc.env.print( std::cerr, 8 );
    1100                                 std::cerr << "cost is: " << withFunc.cost << std::endl;
    11011180                                std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    11021181                        )
     
    11141193
    11151194                // function may return struct or union value, in which case we need to add alternatives
    1116                 // for implicit conversions to each of the anonymous members, must happen after findMinCost
     1195                // for implicitconversions to each of the anonymous members, must happen after findMinCost
    11171196                // since anon conversions are never the cheapest expression
    11181197                for ( const Alternative & alt : winners ) {
     
    11371216        bool isLvalue( Expression *expr ) {
    11381217                // xxx - recurse into tuples?
    1139                 return expr->result && ( expr->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
     1218                return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
    11401219        }
    11411220
     
    11461225                        if ( isLvalue( alt.expr ) ) {
    11471226                                alternatives.push_back(
    1148                                         Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
     1227                                        Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
    11491228                        } // if
    11501229                } // for
     
    11521231
    11531232        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1154                 alternatives.push_back( Alternative{ expr->clone(), env } );
     1233                alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
    11551234        }
    11561235
     
    11881267                assert( toType );
    11891268                toType = resolveTypeof( toType, indexer );
    1190                 assert(!dynamic_cast<TypeofType *>(toType));
    11911269                SymTab::validateType( toType, &indexer );
    11921270                adjustExprType( toType, env, indexer );
     
    11981276                AltList candidates;
    11991277                for ( Alternative & alt : finder.alternatives ) {
    1200                         AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
    1201                         AssertionSet haveAssertions;
    1202                         OpenVarSet openVars{ alt.openVars };
     1278                        AssertionSet needAssertions, haveAssertions;
     1279                        OpenVarSet openVars;
    12031280
    12041281                        alt.env.extractOpenVars( openVars );
     
    12151292                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12161293                                haveAssertions, openVars, indexer );
    1217                         Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),
    1218                                 indexer, alt.env );
     1294                        Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,
     1295                                alt.env );
    12191296                        PRINT(
    12201297                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     
    12281305                                // count one safe conversion for each value that is thrown away
    12291306                                thisCost.incSafe( discardedValues );
    1230                                 Alternative newAlt{
    1231                                         restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
    1232                                         alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };
    1233                                 inferParameters( newAlt, back_inserter( candidates ) );
     1307                                Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
     1308                                        alt.cost, thisCost );
     1309                                inferParameters( needAssertions, haveAssertions, newAlt, openVars,
     1310                                        back_inserter( candidates ) );
    12341311                        } // if
    12351312                } // for
     
    12441321
    12451322        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1246                 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
     1323                assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
    12471324                AlternativeFinder finder( indexer, env );
    12481325                // don't prune here, since it's guaranteed all alternatives will have the same type
    12491326                finder.findWithoutPrune( castExpr->get_arg() );
    12501327                for ( Alternative & alt : finder.alternatives ) {
    1251                         alternatives.push_back( Alternative{
    1252                                 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
    1253                                 alt.cost } );
     1328                        alternatives.push_back( Alternative(
     1329                                new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),
     1330                                alt.env, alt.cost ) );
    12541331                }
    12551332        }
     
    12581335                /// Gets name from untyped member expression (member must be NameExpr)
    12591336                const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
    1260                         if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) {
    1261                                 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
    1262                         } // if
    12631337                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
    12641338                        assert( nameExpr );
     
    12791353                        // find member of the given type
    12801354                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1281                                 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
     1355                                addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    12821356                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1283                                 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
     1357                                addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    12841358                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1285                                 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
     1359                                addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
    12861360                        } // if
    12871361                } // for
     
    12891363
    12901364        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1291                 alternatives.push_back( Alternative{ memberExpr->clone(), env } );
     1365                alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    12921366        }
    12931367
     
    13021376                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13031377                        // can't construct in place and use vector::back
    1304                         Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
     1378                        Alternative newAlt( newExpr, env, Cost::zero, cost );
    13051379                        PRINT(
    13061380                                std::cerr << "decl is ";
     
    13201394                // not sufficient to clone here, because variable's type may have changed
    13211395                // since the VariableExpr was originally created.
    1322                 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
     1396                alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
    13231397        }
    13241398
    13251399        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1326                 alternatives.push_back( Alternative{ constantExpr->clone(), env } );
     1400                alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    13271401        }
    13281402
     
    13301404                if ( sizeofExpr->get_isType() ) {
    13311405                        Type * newType = sizeofExpr->get_type()->clone();
    1332                         alternatives.push_back( Alternative{
    1333                                 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
     1406                        alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
    13341407                } else {
    13351408                        // find all alternatives for the argument to sizeof
     
    13451418                        Alternative &choice = winners.front();
    13461419                        referenceToRvalueConversion( choice.expr, choice.cost );
    1347                         alternatives.push_back( Alternative{
    1348                                 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
     1420                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13491421                } // if
    13501422        }
     
    13531425                if ( alignofExpr->get_isType() ) {
    13541426                        Type * newType = alignofExpr->get_type()->clone();
    1355                         alternatives.push_back( Alternative{
    1356                                 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
     1427                        alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
    13571428                } else {
    13581429                        // find all alternatives for the argument to sizeof
     
    13681439                        Alternative &choice = winners.front();
    13691440                        referenceToRvalueConversion( choice.expr, choice.cost );
    1370                         alternatives.push_back( Alternative{
    1371                                 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
     1441                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13721442                } // if
    13731443        }
     
    13791449                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    13801450                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1381                                 alternatives.push_back( Alternative{
    1382                                         new OffsetofExpr{ aggInst->clone(), dwt }, env } );
     1451                                alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
    13831452                                renameTypes( alternatives.back().expr );
    13841453                        } else {
     
    13991468
    14001469        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1401                 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
     1470                alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
    14021471        }
    14031472
    14041473        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1405                 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
    1406         }
    1407 
    1408         void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) {
     1474                alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
     1475        }
     1476
     1477        namespace {
     1478                void resolveAttr( SymTab::Indexer::IdData data, FunctionType *function, Type *argType, const TypeEnvironment &env, AlternativeFinder & finder ) {
     1479                        // assume no polymorphism
     1480                        // assume no implicit conversions
     1481                        assert( function->get_parameters().size() == 1 );
     1482                        PRINT(
     1483                                std::cerr << "resolvAttr: funcDecl is ";
     1484                                data.id->print( std::cerr );
     1485                                std::cerr << " argType is ";
     1486                                argType->print( std::cerr );
     1487                                std::cerr << std::endl;
     1488                        )
     1489                        const SymTab::Indexer & indexer = finder.get_indexer();
     1490                        AltList & alternatives = finder.get_alternatives();
     1491                        if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
     1492                                Cost cost = Cost::zero;
     1493                                Expression * newExpr = data.combine( cost );
     1494                                alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
     1495                                for ( DeclarationWithType * retVal : function->returnVals ) {
     1496                                        alternatives.back().expr->result = retVal->get_type()->clone();
     1497                                } // for
     1498                        } // if
     1499                }
     1500        }
     1501
     1502        void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) {
     1503                // assume no 'pointer-to-attribute'
     1504                NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
     1505                assert( nameExpr );
     1506                std::list< SymTab::Indexer::IdData > attrList;
     1507                indexer.lookupId( nameExpr->get_name(), attrList );
     1508                if ( attrExpr->get_isType() || attrExpr->get_expr() ) {
     1509                        for ( auto & data : attrList ) {
     1510                                DeclarationWithType * id = data.id;
     1511                                // check if the type is function
     1512                                if ( FunctionType *function = dynamic_cast< FunctionType* >( id->get_type() ) ) {
     1513                                        // assume exactly one parameter
     1514                                        if ( function->get_parameters().size() == 1 ) {
     1515                                                if ( attrExpr->get_isType() ) {
     1516                                                        resolveAttr( data, function, attrExpr->get_type(), env, altFinder);
     1517                                                } else {
     1518                                                        AlternativeFinder finder( indexer, env );
     1519                                                        finder.find( attrExpr->get_expr() );
     1520                                                        for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
     1521                                                                if ( choice->expr->get_result()->size() == 1 ) {
     1522                                                                        resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder );
     1523                                                                } // fi
     1524                                                        } // for
     1525                                                } // if
     1526                                        } // if
     1527                                } // if
     1528                        } // for
     1529                } else {
     1530                        for ( auto & data : attrList ) {
     1531                                Cost cost = Cost::zero;
     1532                                Expression * newExpr = data.combine( cost );
     1533                                alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
     1534                                renameTypes( alternatives.back().expr );
     1535                        } // for
     1536                } // if
     1537        }
     1538
     1539        void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) {
    14091540                AlternativeFinder firstFinder( indexer, env );
    14101541                firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
     
    14151546                for ( const Alternative & first : firstFinder.alternatives ) {
    14161547                        for ( const Alternative & second : secondFinder.alternatives ) {
    1417                                 TypeEnvironment compositeEnv{ first.env };
     1548                                TypeEnvironment compositeEnv;
     1549                                compositeEnv.simpleCombine( first.env );
    14181550                                compositeEnv.simpleCombine( second.env );
    1419                                 OpenVarSet openVars{ first.openVars };
    1420                                 mergeOpenVars( openVars, second.openVars );
    1421                                 AssertionSet need;
    1422                                 cloneAll( first.need, need );
    1423                                 cloneAll( second.need, need );
    1424 
    1425                                 LogicalExpr *newExpr = new LogicalExpr{
    1426                                         first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
    1427                                 alternatives.push_back( Alternative{
    1428                                         newExpr, std::move(compositeEnv), std::move(openVars),
    1429                                         AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
     1551
     1552                                LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
     1553                                alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
    14301554                        }
    14311555                }
     
    14481572                        for ( const Alternative & second : secondFinder.alternatives ) {
    14491573                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1450                                         TypeEnvironment compositeEnv{ first.env };
     1574                                        TypeEnvironment compositeEnv;
     1575                                        compositeEnv.simpleCombine( first.env );
    14511576                                        compositeEnv.simpleCombine( second.env );
    14521577                                        compositeEnv.simpleCombine( third.env );
    1453                                         OpenVarSet openVars{ first.openVars };
    1454                                         mergeOpenVars( openVars, second.openVars );
    1455                                         mergeOpenVars( openVars, third.openVars );
    1456                                         AssertionSet need;
    1457                                         cloneAll( first.need, need );
    1458                                         cloneAll( second.need, need );
    1459                                         cloneAll( third.need, need );
    1460                                         AssertionSet have;
    14611578
    14621579                                        // unify true and false types, then infer parameters to produce new alternatives
     1580                                        OpenVarSet openVars;
     1581                                        AssertionSet needAssertions, haveAssertions;
     1582                                        Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    14631583                                        Type* commonType = nullptr;
    1464                                         if ( unify( second.expr->result, third.expr->result, compositeEnv,
    1465                                                         need, have, openVars, indexer, commonType ) ) {
    1466                                                 ConditionalExpr *newExpr = new ConditionalExpr{
    1467                                                         first.expr->clone(), second.expr->clone(), third.expr->clone() };
     1584                                        if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1585                                                ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
    14681586                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    14691587                                                // convert both options to the conditional result type
    1470                                                 Cost cost = first.cost + second.cost + third.cost;
    1471                                                 cost += computeExpressionConversionCost(
    1472                                                         newExpr->arg2, newExpr->result, indexer, compositeEnv );
    1473                                                 cost += computeExpressionConversionCost(
    1474                                                         newExpr->arg3, newExpr->result, indexer, compositeEnv );
    1475                                                 // output alternative
    1476                                                 Alternative newAlt{
    1477                                                         newExpr, std::move(compositeEnv), std::move(openVars),
    1478                                                         AssertionList( need.begin(), need.end() ), cost };
    1479                                                 inferParameters( newAlt, back_inserter( alternatives ) );
     1588                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
     1589                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
     1590                                                newAlt.expr = newExpr;
     1591                                                inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
    14801592                                        } // if
    14811593                                } // for
     
    14901602                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    14911603                for ( const Alternative & alt : secondFinder.alternatives ) {
    1492                         alternatives.push_back( Alternative{
    1493                                 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
     1604                        alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
    14941605                } // for
    14951606                delete newFirstArg;
     
    15061617                for ( const Alternative & first : firstFinder.alternatives ) {
    15071618                        for ( const Alternative & second : secondFinder.alternatives ) {
    1508                                 TypeEnvironment compositeEnv{ first.env };
     1619                                TypeEnvironment compositeEnv;
     1620                                compositeEnv.simpleCombine( first.env );
    15091621                                compositeEnv.simpleCombine( second.env );
    1510                                 OpenVarSet openVars{ first.openVars };
    1511                                 mergeOpenVars( openVars, second.openVars );
    1512                                 AssertionSet need;
    1513                                 cloneAll( first.need, need );
    1514                                 cloneAll( second.need, need );
    1515                                 AssertionSet have;
    1516 
     1622                                OpenVarSet openVars;
     1623                                AssertionSet needAssertions, haveAssertions;
     1624                                Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
    15171625                                Type* commonType = nullptr;
    1518                                 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
    1519                                                 openVars, indexer, commonType ) ) {
    1520                                         RangeExpr * newExpr =
    1521                                                 new RangeExpr{ first.expr->clone(), second.expr->clone() };
     1626                                if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1627                                        RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
    15221628                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1523                                         Alternative newAlt{
    1524                                                 newExpr, std::move(compositeEnv), std::move(openVars),
    1525                                                 AssertionList( need.begin(), need.end() ), first.cost + second.cost };
    1526                                         inferParameters( newAlt, back_inserter( alternatives ) );
     1629                                        newAlt.expr = newExpr;
     1630                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
    15271631                                } // if
    15281632                        } // for
     
    15421646
    15431647                        TypeEnvironment compositeEnv;
    1544                         OpenVarSet openVars;
    1545                         AssertionSet need;
    1546                         for ( const Alternative& alt : alts ) {
    1547                                 compositeEnv.simpleCombine( alt.env );
    1548                                 mergeOpenVars( openVars, alt.openVars );
    1549                                 cloneAll( alt.need, need );
    1550                         }
    1551 
    1552                         alternatives.push_back( Alternative{
    1553                                 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
    1554                                 AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
     1648                        simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
     1649                        alternatives.push_back(
     1650                                Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
    15551651                } // for
    15561652        }
    15571653
    15581654        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1559                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1655                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15601656        }
    15611657
    15621658        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1563                 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
     1659                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    15641660        }
    15651661
     
    15701666                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    15711667                for ( Alternative & alt : finder.alternatives ) {
    1572                         alternatives.push_back( Alternative{
    1573                                 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
     1668                        alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
    15741669                }
    15751670        }
    15761671
    15771672        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1578                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1673                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15791674        }
    15801675
    15811676        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1582                 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
     1677                alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    15831678        }
    15841679
     
    15891684                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    15901685                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1591                         alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
     1686                        alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
    15921687                }
    15931688        }
     
    15971692                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    15981693                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1599                 alternatives.push_back( Alternative{ newStmtExpr, env } );
     1694                alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
    16001695        }
    16011696
     
    16191714                        for ( Alternative & alt : finder.get_alternatives() ) {
    16201715                                TypeEnvironment newEnv( alt.env );
    1621                                 AssertionSet need;
    1622                                 cloneAll( alt.need, need );
    1623                                 AssertionSet have;
    1624                                 OpenVarSet openVars( alt.openVars );
    1625                                 // xxx - find things in env that don't have a "representative type" and claim
    1626                                 // those are open vars?
     1716                                AssertionSet needAssertions, haveAssertions;
     1717                                OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    16271718                                PRINT(
    16281719                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    16291720                                )
    1630                                 // It's possible that a cast can throw away some values in a multiply-valued
    1631                                 // expression. (An example is a cast-to-void, which casts from one value to
    1632                                 // zero.)  Figure out the prefix of the subexpression results that are cast
    1633                                 // directly.  The candidate is invalid if it has fewer results than there are
    1634                                 // types to cast to.
     1721                                // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
     1722                                // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
     1723                                // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
     1724                                // to.
    16351725                                int discardedValues = alt.expr->result->size() - toType->size();
    16361726                                if ( discardedValues < 0 ) continue;
    1637                                 // xxx - may need to go into tuple types and extract relevant types and use
    1638                                 // unifyList. Note that currently, this does not allow casting a tuple to an
    1639                                 // atomic type (e.g. (int)([1, 2, 3]))
    1640 
     1727                                // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
     1728                                // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    16411729                                // unification run for side-effects
    1642                                 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
    1643                                 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    1644 
    1645                                 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
    1646                                         indexer, newEnv );
     1730                                unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
     1731
     1732                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
    16471733                                if ( thisCost != Cost::infinity ) {
    16481734                                        // count one safe conversion for each value that is thrown away
    16491735                                        thisCost.incSafe( discardedValues );
    1650                                         Alternative newAlt{
    1651                                                 new InitExpr{
    1652                                                         restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
    1653                                                 std::move(newEnv), std::move(openVars),
    1654                                                 AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
    1655                                         inferParameters( newAlt, back_inserter( candidates ) );
     1736                                        Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
     1737                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
    16561738                                }
    16571739                        }
  • src/ResolvExpr/AlternativeFinder.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:56:12 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Oct -5 10:01:00 2018
    13 // Update Count     : 5
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jul 26 11:24:00 2017
     13// Update Count     : 4
    1414//
    1515
     
    2424#include "ResolvExpr/Cost.h"             // for Cost, Cost::infinity
    2525#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    26 #include "ResolvMode.h"                  // for ResolvMode
    2726#include "SynTree/Visitor.h"             // for Visitor
    2827#include "SynTree/SynTree.h"             // for Visitor Nodes
     
    3736        /// First index is which argument, second index is which alternative for that argument,
    3837        /// third index is which exploded element of that alternative
    39         using ExplodedArgs_old = std::vector< std::vector< ExplodedActual > >;
     38        using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;
    4039
    4140        class AlternativeFinder {
     
    6968                }
    7069
    71                 void find( Expression *expr, ResolvMode mode = ResolvMode{} );
     70                void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true );
    7271                /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types
    7372                void findWithAdjustment( Expression *expr );
  • src/ResolvExpr/CastCost.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 06:57:43 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:12:00 2019
    13 // Update Count     : 8
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Feb  2 15:34:36 2016
     13// Update Count     : 7
    1414//
    1515
    1616#include <cassert>                       // for assert
    1717
    18 #include "AST/Print.hpp"
    19 #include "AST/SymbolTable.hpp"
    20 #include "AST/Type.hpp"
    21 #include "AST/TypeEnvironment.hpp"
    2218#include "ConversionCost.h"              // for ConversionCost
    2319#include "Cost.h"                        // for Cost, Cost::infinity
     
    3531
    3632namespace ResolvExpr {
    37         struct CastCost_old : public ConversionCost {
     33        struct CastCost : public ConversionCost {
    3834          public:
    39                 CastCost_old( const Type * dest, bool srcIsLvalue,
    40                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
     35                CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    4136
    4237                using ConversionCost::previsit;
    4338                using ConversionCost::postvisit;
    44                 void postvisit( const BasicType * basicType );
    45                 void postvisit( const PointerType * pointerType );
     39                void postvisit( BasicType * basicType );
     40                void postvisit( PointerType * pointerType );
    4641        };
    4742
    48         Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
    49                         const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    50                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
    51                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
     43        Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     44                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
     45                        if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    5246                                if ( eqvClass->type ) {
    53                                         return castCost( src, eqvClass->type, srcIsLvalue, indexer, env );
     47                                        return castCost( src, eqvClass->type, indexer, env );
    5448                                } else {
    5549                                        return Cost::infinity;
    5650                                }
    57                         } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
     51                        } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) {
    5852                                // all typedefs should be gone by this point
    59                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType );
     53                                TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );
    6054                                if ( type->base ) {
    61                                         return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe;
     55                                        return castCost( src, type->base, indexer, env ) + Cost::safe;
    6256                                } // if
    6357                        } // if
     
    7670                        PRINT( std::cerr << "compatible!" << std::endl; )
    7771                        return Cost::zero;
    78                 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
     72                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    7973                        return Cost::safe;
    80                 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
     74                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    8175                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    82                         return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     76                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    8377                                return ptrsCastable( t1, t2, env, indexer );
    8478                        });
    8579                } else {
    86                         PassVisitor<CastCost_old> converter(
    87                                 dest, srcIsLvalue, indexer, env,
    88                                 (Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & ))
    89                                         castCost );
     80                        PassVisitor<CastCost> converter( dest, indexer, env, castCost );
    9081                        src->accept( converter );
    9182                        if ( converter.pass.get_cost() == Cost::infinity ) {
     
    9889        }
    9990
    100         CastCost_old::CastCost_old( const Type * dest, bool srcIsLvalue,
    101                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    102                 : ConversionCost( dest, srcIsLvalue, indexer, env, costFunc ) {
     91        CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     92                : ConversionCost( dest, indexer, env, costFunc ) {
    10393        }
    10494
    105         void CastCost_old::postvisit( const BasicType * basicType ) {
    106                 const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest );
     95        void CastCost::postvisit( BasicType *basicType ) {
     96                PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
    10797                if ( destAsPointer && basicType->isInteger() ) {
    108                         // necessary for, e.g. unsigned long => void *
     98                        // necessary for, e.g. unsigned long => void*
    10999                        cost = Cost::unsafe;
    110100                } else {
    111                         cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env );
     101                        cost = conversionCost( basicType, dest, indexer, env );
    112102                } // if
    113103        }
    114104
    115         void CastCost_old::postvisit( const PointerType * pointerType ) {
    116                 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
    117                         if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
     105        void CastCost::postvisit( PointerType *pointerType ) {
     106                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
     107                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    118108                                cost = Cost::safe;
    119109                        } else {
     
    128118                                } // if
    129119                        } // if
    130                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
     120                } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
    131121                        if ( destAsBasic->isInteger() ) {
    132                                 // necessary for, e.g. void * => unsigned long
     122                                // necessary for, e.g. void* => unsigned long
    133123                                cost = Cost::unsafe;
    134124                        } // if
    135125                }
    136126        }
    137 
    138 namespace {
    139         struct CastCost_new : public ConversionCost_new {
    140                 using ConversionCost_new::previsit;
    141                 using ConversionCost_new::postvisit;
    142 
    143                 CastCost_new(
    144                         const ast::Type * dst, const ast::SymbolTable & symtab,
    145                         const ast::TypeEnvironment & env, CostCalculation costFunc )
    146                 : ConversionCost_new( dst, symtab, env, costFunc ) {}
    147 
    148                 void postvisit( const ast::BasicType * basicType ) {
    149                         auto ptr = dynamic_cast< const ast::PointerType * >( dst );
    150                         if ( ptr && basicType->isInteger() ) {
    151                                 // needed for, e.g. unsigned long => void *
    152                                 cost = Cost::unsafe;
    153                         } else {
    154                                 cost = conversionCost( basicType, dst, symtab, env );
    155                         }
    156                 }
    157 
    158                 void postvisit( const ast::PointerType * pointerType ) {
    159                         if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) {
    160                                 if (
    161                                         pointerType->qualifiers <= ptr->qualifiers
    162                                         && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
    163                                 ) {
    164                                         cost = Cost::safe;
    165                                 } else {
    166                                         ast::TypeEnvironment newEnv{ env };
    167                                         if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) {
    168                                                 newEnv.add( wParams->forall );
    169                                         }
    170                                         int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv );
    171                                         if ( castResult > 0 ) {
    172                                                 cost = Cost::safe;
    173                                         } else if ( castResult < 0 ) {
    174                                                 cost = Cost::infinity;
    175                                         }
    176                                 }
    177                         } else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) {
    178                                 if ( basic->isInteger() ) {
    179                                         // necessary for, e.g. void * => unsigned long
    180                                         cost = Cost::unsafe;
    181                                 }
    182                         }
    183                 }
    184         };
    185 } // anonymous namespace
    186 
    187 Cost castCost(
    188         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    189         const ast::TypeEnvironment & env
    190 ) {
    191         if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    192                 if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) {
    193                         // check cast cost against bound type, if present
    194                         if ( eqvClass->bound ) {
    195                                 return castCost( src, eqvClass->bound, symtab, env );
    196                         } else {
    197                                 return Cost::infinity;
    198                         }
    199                 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) {
    200                         // all typedefs should be gone by now
    201                         auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
    202                         if ( type->base ) {
    203                                 return castCost( src, type->base, symtab, env ) + Cost::safe;
    204                         }
    205                 }
    206         }
    207 
    208         PRINT(
    209                 std::cerr << "castCost ::: src is ";
    210                 ast::print( std::cerr, src );
    211                 std::cerr << std::endl << "dest is ";
    212                 ast::print( std::cerr, dst );
    213                 std::cerr << std::endl << "env is" << std::endl;
    214                 ast::print( std::cerr, env, 2 );
    215         )
    216 
    217         if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
    218                 PRINT( std::cerr << "compatible!" << std::endl; )
    219                 return Cost::zero;
    220         } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
    221                 return Cost::safe;
    222         } else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
    223                 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    224                 #warning cast on ptrsCastable artifact of having two functions, remove when port done
    225                 return convertToReferenceCost(
    226                         src, refType, symtab, env,
    227                         ( int (*)(
    228                                 const ast::Type *, const ast::Type *, const ast::SymbolTable &,
    229                                 const ast::TypeEnvironment & )
    230                         ) ptrsCastable );
    231         } else {
    232                 #warning cast on castCost artifact of having two functions, remove when port done
    233                 ast::Pass< CastCost_new > converter{
    234                         dst, symtab, env,
    235                         ( Cost (*)(
    236                                 const ast::Type *, const ast::Type *, const ast::SymbolTable &,
    237                                 const ast::TypeEnvironment & )
    238                         ) castCost };
    239                 src->accept( converter );
    240                 return converter.pass.cost;
    241         }
    242 }
    243 
    244127} // namespace ResolvExpr
    245128
  • src/ResolvExpr/CommonType.cc

    rb067d9b r7951100  
    1010// Created On       : Sun May 17 06:59:27 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 14 17:10:10 2019
    13 // Update Count     : 24
     12// Last Modified On : Mon Sep 25 15:18:17 2017
     13// Update Count     : 9
    1414//
    1515
     
    1818#include <utility>                       // for pair
    1919
    20 #include "AST/Decl.hpp"
    21 #include "AST/Type.hpp"
    2220#include "Common/PassVisitor.h"
    2321#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
     
    2624#include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    2725#include "SynTree/Visitor.h"             // for Visitor
    28 #include "Unify.h"                       // for unifyExact, WidenMode
     26#include "Unify.h"                       // for unifyExact, bindVar, WidenMode
    2927#include "typeops.h"                     // for isFtype
    3028
     
    3735
    3836namespace ResolvExpr {
    39         struct CommonType_old : public WithShortCircuiting {
    40                 CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    41                 Type * get_result() const { return result; }
     37        struct CommonType : public WithShortCircuiting {
     38                CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
     39                Type *get_result() const { return result; }
    4240
    4341                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     
    6058
    6159          private:
    62                 template< typename Pointer > void getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer );
    63                 template< typename RefType > void handleRefType( RefType * inst, Type * other );
    64 
    65                 Type * result;
    66                 Type * type2;                           // inherited
     60                template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
     61                template< typename RefType > void handleRefType( RefType *inst, Type *other );
     62
     63                Type *result;
     64                Type *type2;                            // inherited
    6765                bool widenFirst, widenSecond;
    6866                const SymTab::Indexer &indexer;
     
    8078                                std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
    8179                        )
    82                         if ( (widenFirst || t2->tq <= t1->tq) && (widenSecond || t1->tq <= t2->tq) ) {
     80                        if ( (widenFirst || t2->get_qualifiers() <= t1->get_qualifiers()) && (widenSecond || t1->get_qualifiers() <= t2->get_qualifiers()) ) {
    8381                                PRINT(
    8482                                        std::cerr << "widen okay" << std::endl;
    8583                                )
    86                                 common->tq |= t1->tq;
    87                                 common->tq |= t2->tq;
     84                                common->get_qualifiers() |= t1->get_qualifiers();
     85                                common->get_qualifiers() |= t2->get_qualifiers();
    8886                                return common;
    8987                        }
     
    9593        }
    9694
    97         Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    98                 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     95        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
     96                PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    9997
    10098                int depth1 = type1->referenceDepth();
     
    127125                                                std::cerr << "formal is reference; result should be reference" << std::endl;
    128126                                        )
    129                                         result = new ReferenceType( ref1->tq, result );
     127                                        result = new ReferenceType( ref1->get_qualifiers(), result );
    130128                                }
    131129                                PRINT(
     
    138136
    139137                type1->accept( visitor );
    140                 Type * result = visitor.pass.get_result();
     138                Type *result = visitor.pass.get_result();
    141139                if ( ! result ) {
    142140                        // this appears to be handling for opaque type declarations
    143141                        if ( widenSecond ) {
    144                                 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type2 ) ) {
    145                                         if ( const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() ) ) {
    146                                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
     142                                if ( TypeInstType *inst = dynamic_cast< TypeInstType* >( type2 ) ) {
     143                                        if ( NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ) ) {
     144                                                TypeDecl *type = strict_dynamic_cast< TypeDecl* >( nt );
    147145                                                if ( type->get_base() ) {
    148                                                         Type::Qualifiers tq1 = type1->tq, tq2 = type2->tq;
     146                                                        Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
    149147                                                        AssertionSet have, need;
    150148                                                        OpenVarSet newOpen( openVars );
    151                                                         type1->tq = Type::Qualifiers();
    152                                                         type->get_base()->tq = tq1;
     149                                                        type1->get_qualifiers() = Type::Qualifiers();
     150                                                        type->get_base()->get_qualifiers() = tq1;
    153151                                                        if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) {
    154152                                                                result = type1->clone();
    155                                                                 result->tq = tq1 | tq2;
     153                                                                result->get_qualifiers() = tq1 | tq2;
    156154                                                        } // if
    157                                                         type1->tq = tq1;
    158                                                         type->get_base()->tq = Type::Qualifiers();
     155                                                        type1->get_qualifiers() = tq1;
     156                                                        type->get_base()->get_qualifiers() = Type::Qualifiers();
    159157                                                } // if
    160158                                        } // if
     
    178176        }
    179177
    180         // GENERATED START, DO NOT EDIT
    181         // GENERATED BY BasicTypes-gen.cc
    182         #define BT BasicType::
    183         static const BasicType::Kind commonTypes[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // nearest common ancestor
    184                 /*                                      B                       C                      SC                      UC                      SI                     SUI
    185                                                         I                      UI                      LI                     LUI                     LLI                    LLUI
    186                                                        IB                     UIB                     _FH                     _FH                      _F                     _FC
    187                                                         F                      FC                     _FX                    _FXC                      FD                    _FDC
    188                                                         D                      DC                    F80X                   _FDXC                     F80                     _FB
    189                                                     _FLDC                      FB                      LD                     LDC                    _FBX                  _FLDXC
    190                                  */
    191                                   {
    192                 /*      B */                BT Bool,                BT Char,          BT SignedChar,        BT UnsignedChar,      BT ShortSignedInt,    BT ShortUnsignedInt,
    193                                              BT SignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    194                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    195                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    196                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    197                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    198                                   },
    199                                   {
    200                 /*      C */                BT Char,                BT Char,          BT SignedChar,        BT UnsignedChar,      BT ShortSignedInt,    BT ShortUnsignedInt,
    201                                              BT SignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    202                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    203                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    204                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    205                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    206                                   },
    207                                   {
    208                 /*     SC */          BT SignedChar,          BT SignedChar,          BT SignedChar,        BT UnsignedChar,      BT ShortSignedInt,    BT ShortUnsignedInt,
    209                                              BT SignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    210                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    211                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    212                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    213                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    214                                   },
    215                                   {
    216                 /*     UC */        BT UnsignedChar,        BT UnsignedChar,        BT UnsignedChar,        BT UnsignedChar,      BT ShortSignedInt,    BT ShortUnsignedInt,
    217                                              BT SignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    218                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    219                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    220                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    221                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    222                                   },
    223                                   {
    224                 /*     SI */      BT ShortSignedInt,      BT ShortSignedInt,      BT ShortSignedInt,      BT ShortSignedInt,      BT ShortSignedInt,    BT ShortUnsignedInt,
    225                                              BT SignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    226                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    227                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    228                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    229                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    230                                   },
    231                                   {
    232                 /*    SUI */    BT ShortUnsignedInt,    BT ShortUnsignedInt,    BT ShortUnsignedInt,    BT ShortUnsignedInt,    BT ShortUnsignedInt,    BT ShortUnsignedInt,
    233                                              BT SignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    234                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    235                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    236                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    237                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    238                                   },
    239                                   {
    240                 /*      I */           BT SignedInt,           BT SignedInt,           BT SignedInt,           BT SignedInt,           BT SignedInt,           BT SignedInt,
    241                                              BT SignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    242                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    243                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    244                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    245                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    246                                   },
    247                                   {
    248                 /*     UI */         BT UnsignedInt,         BT UnsignedInt,         BT UnsignedInt,         BT UnsignedInt,         BT UnsignedInt,         BT UnsignedInt,
    249                                            BT UnsignedInt,         BT UnsignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    250                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    251                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    252                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    253                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    254                                   },
    255                                   {
    256                 /*     LI */       BT LongSignedInt,       BT LongSignedInt,       BT LongSignedInt,       BT LongSignedInt,       BT LongSignedInt,       BT LongSignedInt,
    257                                          BT LongSignedInt,       BT LongSignedInt,       BT LongSignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    258                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    259                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    260                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    261                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    262                                   },
    263                                   {
    264                 /*    LUI */     BT LongUnsignedInt,     BT LongUnsignedInt,     BT LongUnsignedInt,     BT LongUnsignedInt,     BT LongUnsignedInt,     BT LongUnsignedInt,
    265                                        BT LongUnsignedInt,     BT LongUnsignedInt,     BT LongUnsignedInt,     BT LongUnsignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    266                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    267                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    268                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    269                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    270                                   },
    271                                   {
    272                 /*    LLI */   BT LongLongSignedInt,   BT LongLongSignedInt,   BT LongLongSignedInt,   BT LongLongSignedInt,   BT LongLongSignedInt,   BT LongLongSignedInt,
    273                                      BT LongLongSignedInt,   BT LongLongSignedInt,   BT LongLongSignedInt,   BT LongLongSignedInt,   BT LongLongSignedInt, BT LongLongUnsignedInt,
    274                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    275                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    276                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    277                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    278                                   },
    279                                   {
    280                 /*   LLUI */ BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt,
    281                                    BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt, BT LongLongUnsignedInt,
    282                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    283                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    284                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    285                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    286                                   },
    287                                   {
    288                 /*     IB */        BT SignedInt128,        BT SignedInt128,        BT SignedInt128,        BT SignedInt128,        BT SignedInt128,        BT SignedInt128,
    289                                           BT SignedInt128,        BT SignedInt128,        BT SignedInt128,        BT SignedInt128,        BT SignedInt128,        BT SignedInt128,
    290                                           BT SignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    291                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    292                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    293                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    294                                   },
    295                                   {
    296                 /*    UIB */      BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,
    297                                         BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,      BT UnsignedInt128,
    298                                         BT UnsignedInt128,      BT UnsignedInt128,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    299                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    300                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    301                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    302                                   },
    303                                   {
    304                 /*    _FH */            BT uFloat16,            BT uFloat16,            BT uFloat16,            BT uFloat16,            BT uFloat16,            BT uFloat16,
    305                                               BT uFloat16,            BT uFloat16,            BT uFloat16,            BT uFloat16,            BT uFloat16,            BT uFloat16,
    306                                               BT uFloat16,            BT uFloat16,            BT uFloat16,     BT uFloat16Complex,            BT uFloat32,     BT uFloat32Complex,
    307                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    308                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    309                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    310                                   },
    311                                   {
    312                 /*    _FH */     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,
    313                                        BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,
    314                                        BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat16Complex,     BT uFloat32Complex,     BT uFloat32Complex,
    315                                           BT FloatComplex,        BT FloatComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,     BT uFloat64Complex,     BT uFloat64Complex,
    316                                          BT DoubleComplex,       BT DoubleComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat128Complex,
    317                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    318                                   },
    319                                   {
    320                 /*     _F */            BT uFloat32,            BT uFloat32,            BT uFloat32,            BT uFloat32,            BT uFloat32,            BT uFloat32,
    321                                               BT uFloat32,            BT uFloat32,            BT uFloat32,            BT uFloat32,            BT uFloat32,            BT uFloat32,
    322                                               BT uFloat32,            BT uFloat32,            BT uFloat32,     BT uFloat32Complex,            BT uFloat32,     BT uFloat32Complex,
    323                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    324                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    325                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    326                                   },
    327                                   {
    328                 /*    _FC */     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,
    329                                        BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,
    330                                        BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,     BT uFloat32Complex,
    331                                           BT FloatComplex,        BT FloatComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,     BT uFloat64Complex,     BT uFloat64Complex,
    332                                          BT DoubleComplex,       BT DoubleComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat128Complex,
    333                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    334                                   },
    335                                   {
    336                 /*      F */               BT Float,               BT Float,               BT Float,               BT Float,               BT Float,               BT Float,
    337                                                  BT Float,               BT Float,               BT Float,               BT Float,               BT Float,               BT Float,
    338                                                  BT Float,               BT Float,               BT Float,        BT FloatComplex,               BT Float,        BT FloatComplex,
    339                                                  BT Float,        BT FloatComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    340                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    341                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    342                                   },
    343                                   {
    344                 /*     FC */        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,
    345                                           BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,
    346                                           BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,        BT FloatComplex,
    347                                           BT FloatComplex,        BT FloatComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,     BT uFloat64Complex,     BT uFloat64Complex,
    348                                          BT DoubleComplex,       BT DoubleComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat128Complex,
    349                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    350                                   },
    351                                   {
    352                 /*    _FX */           BT uFloat32x,           BT uFloat32x,           BT uFloat32x,           BT uFloat32x,           BT uFloat32x,           BT uFloat32x,
    353                                              BT uFloat32x,           BT uFloat32x,           BT uFloat32x,           BT uFloat32x,           BT uFloat32x,           BT uFloat32x,
    354                                              BT uFloat32x,           BT uFloat32x,           BT uFloat32x,    BT uFloat32xComplex,           BT uFloat32x,    BT uFloat32xComplex,
    355                                              BT uFloat32x,    BT uFloat32xComplex,           BT uFloat32x,    BT uFloat32xComplex,            BT uFloat64,     BT uFloat64Complex,
    356                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    357                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    358                                   },
    359                                   {
    360                 /*   _FXC */    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,
    361                                       BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,
    362                                       BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,
    363                                       BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,    BT uFloat32xComplex,     BT uFloat64Complex,     BT uFloat64Complex,
    364                                          BT DoubleComplex,       BT DoubleComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat128Complex,
    365                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    366                                   },
    367                                   {
    368                 /*     FD */            BT uFloat64,            BT uFloat64,            BT uFloat64,            BT uFloat64,            BT uFloat64,            BT uFloat64,
    369                                               BT uFloat64,            BT uFloat64,            BT uFloat64,            BT uFloat64,            BT uFloat64,            BT uFloat64,
    370                                               BT uFloat64,            BT uFloat64,            BT uFloat64,     BT uFloat64Complex,            BT uFloat64,     BT uFloat64Complex,
    371                                               BT uFloat64,     BT uFloat64Complex,            BT uFloat64,     BT uFloat64Complex,            BT uFloat64,     BT uFloat64Complex,
    372                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    373                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    374                                   },
    375                                   {
    376                 /*   _FDC */     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,
    377                                        BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,
    378                                        BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,
    379                                        BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,     BT uFloat64Complex,
    380                                          BT DoubleComplex,       BT DoubleComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat128Complex,
    381                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    382                                   },
    383                                   {
    384                 /*      D */              BT Double,              BT Double,              BT Double,              BT Double,              BT Double,              BT Double,
    385                                                 BT Double,              BT Double,              BT Double,              BT Double,              BT Double,              BT Double,
    386                                                 BT Double,              BT Double,              BT Double,       BT DoubleComplex,              BT Double,       BT DoubleComplex,
    387                                                 BT Double,       BT DoubleComplex,              BT Double,       BT DoubleComplex,              BT Double,       BT DoubleComplex,
    388                                                 BT Double,       BT DoubleComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    389                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    390                                   },
    391                                   {
    392                 /*     DC */       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,
    393                                          BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,
    394                                          BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,
    395                                          BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,       BT DoubleComplex,
    396                                          BT DoubleComplex,       BT DoubleComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat128Complex,
    397                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    398                                   },
    399                                   {
    400                 /*   F80X */           BT uFloat64x,           BT uFloat64x,           BT uFloat64x,           BT uFloat64x,           BT uFloat64x,           BT uFloat64x,
    401                                              BT uFloat64x,           BT uFloat64x,           BT uFloat64x,           BT uFloat64x,           BT uFloat64x,           BT uFloat64x,
    402                                              BT uFloat64x,           BT uFloat64x,           BT uFloat64x,    BT uFloat64xComplex,           BT uFloat64x,    BT uFloat64xComplex,
    403                                              BT uFloat64x,    BT uFloat64xComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uFloat64x,    BT uFloat64xComplex,
    404                                              BT uFloat64x,    BT uFloat64xComplex,           BT uFloat64x,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    405                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    406                                   },
    407                                   {
    408                 /*  _FDXC */    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,
    409                                       BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,
    410                                       BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,
    411                                       BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,
    412                                       BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat64xComplex,    BT uFloat128Complex,
    413                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    414                                   },
    415                                   {
    416                 /*    F80 */           BT uuFloat80,           BT uuFloat80,           BT uuFloat80,           BT uuFloat80,           BT uuFloat80,           BT uuFloat80,
    417                                              BT uuFloat80,           BT uuFloat80,           BT uuFloat80,           BT uuFloat80,           BT uuFloat80,           BT uuFloat80,
    418                                              BT uuFloat80,           BT uuFloat80,           BT uuFloat80,    BT uFloat64xComplex,           BT uuFloat80,    BT uFloat64xComplex,
    419                                              BT uuFloat80,    BT uFloat64xComplex,           BT uuFloat80,    BT uFloat64xComplex,           BT uuFloat80,    BT uFloat64xComplex,
    420                                              BT uuFloat80,    BT uFloat64xComplex,           BT uuFloat80,    BT uFloat64xComplex,           BT uuFloat80,           BT uFloat128,
    421                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    422                                   },
    423                                   {
    424                 /*    _FB */           BT uFloat128,           BT uFloat128,           BT uFloat128,           BT uFloat128,           BT uFloat128,           BT uFloat128,
    425                                              BT uFloat128,           BT uFloat128,           BT uFloat128,           BT uFloat128,           BT uFloat128,           BT uFloat128,
    426                                              BT uFloat128,           BT uFloat128,           BT uFloat128,    BT uFloat128Complex,           BT uFloat128,    BT uFloat128Complex,
    427                                              BT uFloat128,    BT uFloat128Complex,           BT uFloat128,    BT uFloat128Complex,           BT uFloat128,    BT uFloat128Complex,
    428                                              BT uFloat128,    BT uFloat128Complex,           BT uFloat128,    BT uFloat128Complex,           BT uFloat128,           BT uFloat128,
    429                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    430                                   },
    431                                   {
    432                 /*  _FLDC */    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,
    433                                       BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,
    434                                       BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,
    435                                       BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,
    436                                       BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,    BT uFloat128Complex,
    437                                       BT uFloat128Complex,    BT uFloat128Complex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    438                                   },
    439                                   {
    440                 /*     FB */          BT uuFloat128,          BT uuFloat128,          BT uuFloat128,          BT uuFloat128,          BT uuFloat128,          BT uuFloat128,
    441                                             BT uuFloat128,          BT uuFloat128,          BT uuFloat128,          BT uuFloat128,          BT uuFloat128,          BT uuFloat128,
    442                                             BT uuFloat128,          BT uuFloat128,          BT uuFloat128,    BT uFloat128Complex,          BT uuFloat128,    BT uFloat128Complex,
    443                                             BT uuFloat128,    BT uFloat128Complex,          BT uuFloat128,    BT uFloat128Complex,          BT uuFloat128,    BT uFloat128Complex,
    444                                             BT uuFloat128,    BT uFloat128Complex,          BT uuFloat128,    BT uFloat128Complex,          BT uuFloat128,          BT uuFloat128,
    445                                       BT uFloat128Complex,          BT uuFloat128,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    446                                   },
    447                                   {
    448                 /*     LD */          BT LongDouble,          BT LongDouble,          BT LongDouble,          BT LongDouble,          BT LongDouble,          BT LongDouble,
    449                                             BT LongDouble,          BT LongDouble,          BT LongDouble,          BT LongDouble,          BT LongDouble,          BT LongDouble,
    450                                             BT LongDouble,          BT LongDouble,          BT LongDouble,   BT LongDoubleComplex,          BT LongDouble,   BT LongDoubleComplex,
    451                                             BT LongDouble,   BT LongDoubleComplex,          BT LongDouble,   BT LongDoubleComplex,          BT LongDouble,   BT LongDoubleComplex,
    452                                             BT LongDouble,   BT LongDoubleComplex,          BT LongDouble,   BT LongDoubleComplex,          BT LongDouble,          BT LongDouble,
    453                                      BT LongDoubleComplex,          BT LongDouble,          BT LongDouble,   BT LongDoubleComplex,          BT uFloat128x,   BT uFloat128xComplex,
    454                                   },
    455                                   {
    456                 /*    LDC */   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,
    457                                      BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,
    458                                      BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,
    459                                      BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,
    460                                      BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,
    461                                      BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT LongDoubleComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    462                                   },
    463                                   {
    464                 /*   _FBX */          BT uFloat128x,          BT uFloat128x,          BT uFloat128x,          BT uFloat128x,          BT uFloat128x,          BT uFloat128x,
    465                                             BT uFloat128x,          BT uFloat128x,          BT uFloat128x,          BT uFloat128x,          BT uFloat128x,          BT uFloat128x,
    466                                             BT uFloat128x,          BT uFloat128x,          BT uFloat128x,   BT uFloat128xComplex,          BT uFloat128x,   BT uFloat128xComplex,
    467                                             BT uFloat128x,   BT uFloat128xComplex,          BT uFloat128x,   BT uFloat128xComplex,          BT uFloat128x,   BT uFloat128xComplex,
    468                                             BT uFloat128x,   BT uFloat128xComplex,          BT uFloat128x,   BT uFloat128xComplex,          BT uFloat128x,          BT uFloat128x,
    469                                      BT uFloat128xComplex,          BT uFloat128x,          BT uFloat128x,   BT uFloat128xComplex,          BT uFloat128x,   BT uFloat128xComplex,
    470                                   },
    471                                   {
    472                 /* _FLDXC */   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    473                                      BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    474                                      BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    475                                      BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    476                                      BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    477                                      BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,   BT uFloat128xComplex,
    478                                   },
    479         }; // commonTypes
    480         #undef BT
    481         // GENERATED END
     178        static const BasicType::Kind combinedType[][ BasicType::NUMBER_OF_BASIC_TYPES ] =
     179        {
     180/*              Bool            Char    SignedChar      UnsignedChar    ShortSignedInt  ShortUnsignedInt        SignedInt       UnsignedInt     LongSignedInt   LongUnsignedInt LongLongSignedInt       LongLongUnsignedInt     Float   Double  LongDouble      FloatComplex    DoubleComplex   LongDoubleComplex       FloatImaginary  DoubleImaginary LongDoubleImaginary   SignedInt128   UnsignedInt128   Float80   Float128 */
     181                /* Bool */      { BasicType::Bool,              BasicType::Char,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     182                /* Char */      { BasicType::Char,              BasicType::Char,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     183                /* SignedChar */        { BasicType::SignedChar,        BasicType::UnsignedChar,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     184                /* UnsignedChar */      { BasicType::UnsignedChar,      BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     185                /* ShortSignedInt */    { BasicType::ShortSignedInt,    BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     186                /* ShortUnsignedInt */  { BasicType::ShortUnsignedInt,  BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     187                /* SignedInt */         { BasicType::SignedInt,         BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     188                /* UnsignedInt */       { BasicType::UnsignedInt,               BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     189                /* LongSignedInt */     { BasicType::LongSignedInt,             BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     190                /* LongUnsignedInt */   { BasicType::LongUnsignedInt,   BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     191                /* LongLongSignedInt */         { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     192                /* LongLongUnsignedInt */       { BasicType::LongLongUnsignedInt,       BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     193                /* Float */     { BasicType::Float,     BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Float,       BasicType::Float, BasicType::Float80, BasicType::Float128 },
     194                /* Double */    { BasicType::Double,    BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::LongDouble,  BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Double,      BasicType::Double, BasicType::Float80, BasicType::Float128 },
     195                /* LongDouble */        { BasicType::LongDouble,                BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDouble,  BasicType::LongDouble, BasicType::BasicType::LongDouble, BasicType::Float128 },
     196                /* FloatComplex */      { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::FloatComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, },
     197                /* DoubleComplex */     { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex },
     198                /* LongDoubleComplex */         { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, },
     199                /* FloatImaginary */    { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatImaginary,      BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::FloatImaginary,      BasicType::FloatImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
     200                /* DoubleImaginary */   { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleImaginary,     BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::DoubleImaginary,     BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
     201                /* LongDoubleImaginary */       { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
     202                /* SignedInt128 */      { BasicType::SignedInt128,      BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, },
     203                /* UnsignedInt128 */    { BasicType::UnsignedInt128,    BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::UnsignedInt128,      BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, },
     204                /* Float80 */   { BasicType::Float80,   BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::Float80,     BasicType::Float80, BasicType::Float80, BasicType::Float128 },
     205                /* Float128 */  { BasicType::Float128,  BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::Float128,    BasicType::Float128, BasicType::Float128, BasicType::Float128 },
     206        };
    482207        static_assert(
    483                 sizeof(commonTypes)/sizeof(commonTypes[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
     208                sizeof(combinedType)/sizeof(combinedType[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
    484209                "Each basic type kind should have a corresponding row in the combined type matrix"
    485210        );
    486211
    487         CommonType_old::CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     212        CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    488213                : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    489214        }
    490215
    491         void CommonType_old::postvisit( VoidType * ) {}
    492 
    493         void CommonType_old::postvisit( BasicType * basicType ) {
    494                 if ( BasicType * otherBasic = dynamic_cast< BasicType * >( type2 ) ) {
    495                         BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ otherBasic->get_kind() ];
    496                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= otherBasic->tq ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->tq <= otherBasic->tq ) || widenSecond ) ) {
    497                                 result = new BasicType( basicType->tq | otherBasic->tq, newType );
    498                         } // if
    499                 } else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
     216        void CommonType::postvisit( VoidType * ) {}
     217
     218        void CommonType::postvisit( BasicType *basicType ) {
     219                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
     220                        BasicType::Kind newType = combinedType[ basicType->get_kind() ][ otherBasic->get_kind() ];
     221                        if ( ( ( newType == basicType->get_kind() && basicType->get_qualifiers() >= otherBasic->get_qualifiers() ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->get_qualifiers() <= otherBasic->get_qualifiers() ) || widenSecond ) ) {
     222                                result = new BasicType( basicType->get_qualifiers() | otherBasic->get_qualifiers(), newType );
     223                        } // if
     224                } else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    500225                        // use signed int in lieu of the enum/zero/one type
    501                         BasicType::Kind newType = commonTypes[ basicType->get_kind() ][ BasicType::SignedInt ];
    502                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
    503                                 result = new BasicType( basicType->tq | type2->tq, newType );
     226                        BasicType::Kind newType = combinedType[ basicType->get_kind() ][ BasicType::SignedInt ];
     227                        if ( ( ( newType == basicType->get_kind() && basicType->get_qualifiers() >= type2->get_qualifiers() ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->get_qualifiers() <= type2->get_qualifiers() ) || widenSecond ) ) {
     228                                result = new BasicType( basicType->get_qualifiers() | type2->get_qualifiers(), newType );
    504229                        } // if
    505230                } // if
     
    507232
    508233        template< typename Pointer >
    509         void CommonType_old::getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ) {
    510                 if ( TypeInstType * var = dynamic_cast< TypeInstType * >( otherPointer->get_base() ) ) {
     234        void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
     235                if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
    511236                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
    512237                        if ( entry != openVars.end() ) {
    513238                                AssertionSet need, have;
    514239                                WidenMode widen( widenFirst, widenSecond );
    515                                 if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
     240                                if ( entry != openVars.end() && ! bindVar(var, voidPointer->get_base(), entry->second, env, need, have, openVars, widen, indexer ) ) return;
    516241                        }
    517242                }
    518243                result = voidPointer->clone();
    519                 result->tq |= otherPointer->tq;
    520         }
    521 
    522         void CommonType_old::postvisit( PointerType * pointerType ) {
    523                 if ( PointerType * otherPointer = dynamic_cast< PointerType * >( type2 ) ) {
     244                result->get_qualifiers() |= otherPointer->get_qualifiers();
     245        }
     246
     247        void CommonType::postvisit( PointerType *pointerType ) {
     248                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    524249                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
    525                         if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
     250                        if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
    526251                                getCommonWithVoidPointer( otherPointer, pointerType );
    527                         } else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
     252                        } else if ( widenSecond && dynamic_cast< VoidType* >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
    528253                                getCommonWithVoidPointer( pointerType, otherPointer );
    529                         } else if ( ( pointerType->get_base()->tq >= otherPointer->get_base()->tq || widenFirst )
    530                                            && ( pointerType->get_base()->tq <= otherPointer->get_base()->tq || widenSecond ) ) {
     254                        } else if ( ( pointerType->get_base()->get_qualifiers() >= otherPointer->get_base()->get_qualifiers() || widenFirst )
     255                                           && ( pointerType->get_base()->get_qualifiers() <= otherPointer->get_base()->get_qualifiers() || widenSecond ) ) {
    531256                                // std::cerr << "middle case" << std::endl;
    532                                 Type::Qualifiers tq1 = pointerType->get_base()->tq, tq2 = otherPointer->get_base()->tq;
    533                                 pointerType->get_base()->tq = Type::Qualifiers();
    534                                 otherPointer->get_base()->tq = Type::Qualifiers();
     257                                Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(), tq2 = otherPointer->get_base()->get_qualifiers();
     258                                pointerType->get_base()->get_qualifiers() = Type::Qualifiers();
     259                                otherPointer->get_base()->get_qualifiers() = Type::Qualifiers();
    535260                                AssertionSet have, need;
    536261                                OpenVarSet newOpen( openVars );
     
    542267                                                result = otherPointer->clone();
    543268                                        } // if
    544                                         strict_dynamic_cast<PointerType *>(result)->base->tq = tq1 | tq2;
     269                                        result->get_qualifiers() = tq1 | tq2;
    545270                                } else {
    546271                                        /// std::cerr << "place for ptr-to-type" << std::endl;
    547272                                } // if
    548                                 pointerType->get_base()->tq = tq1;
    549                                 otherPointer->get_base()->tq = tq2;
    550                         } // if
    551                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
     273                                pointerType->get_base()->get_qualifiers() = tq1;
     274                                otherPointer->get_base()->get_qualifiers() = tq2;
     275                        } // if
     276                } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
    552277                        result = pointerType->clone();
    553                         result->tq |= type2->tq;
    554                 } // if
    555         }
    556 
    557         void CommonType_old::postvisit( ArrayType * ) {}
    558 
    559         void CommonType_old::postvisit( ReferenceType * refType ) {
    560                 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( type2 ) ) {
     278                        result->get_qualifiers() |= type2->get_qualifiers();
     279                } // if
     280        }
     281
     282        void CommonType::postvisit( ArrayType * ) {}
     283
     284        void CommonType::postvisit( ReferenceType *refType ) {
     285                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    561286                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
    562                         // std::cerr << ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst ) << (refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond) << std::endl;
    563                         if ( widenFirst && dynamic_cast< VoidType * >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
     287                        // std::cerr << ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst ) << (refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond) << std::endl;
     288                        if ( widenFirst && dynamic_cast< VoidType* >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
    564289                                getCommonWithVoidPointer( otherRef, refType );
    565                         } else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
     290                        } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
    566291                                getCommonWithVoidPointer( refType, otherRef );
    567                         } else if ( ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst )
    568                                            && ( refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond ) ) {
     292                        } else if ( ( refType->get_base()->get_qualifiers() >= otherRef->get_base()->get_qualifiers() || widenFirst )
     293                                           && ( refType->get_base()->get_qualifiers() <= otherRef->get_base()->get_qualifiers() || widenSecond ) ) {
    569294                                // std::cerr << "middle case" << std::endl;
    570                                 Type::Qualifiers tq1 = refType->get_base()->tq, tq2 = otherRef->get_base()->tq;
    571                                 refType->get_base()->tq = Type::Qualifiers();
    572                                 otherRef->get_base()->tq = Type::Qualifiers();
     295                                Type::Qualifiers tq1 = refType->get_base()->get_qualifiers(), tq2 = otherRef->get_base()->get_qualifiers();
     296                                refType->get_base()->get_qualifiers() = Type::Qualifiers();
     297                                otherRef->get_base()->get_qualifiers() = Type::Qualifiers();
    573298                                AssertionSet have, need;
    574299                                OpenVarSet newOpen( openVars );
     
    579304                                                result = otherRef->clone();
    580305                                        } // if
    581                                         strict_dynamic_cast<ReferenceType *>(result)->base->tq = tq1 | tq2;
     306                                        result->get_qualifiers() = tq1 | tq2;
    582307                                } else {
    583308                                        /// std::cerr << "place for ptr-to-type" << std::endl;
    584309                                } // if
    585                                 refType->get_base()->tq = tq1;
    586                                 otherRef->get_base()->tq = tq2;
    587                         } // if
    588                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
     310                                refType->get_base()->get_qualifiers() = tq1;
     311                                otherRef->get_base()->get_qualifiers() = tq2;
     312                        } // if
     313                } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
    589314                        result = refType->clone();
    590                         result->tq |= type2->tq;
    591                 } // if
    592         }
    593 
    594         void CommonType_old::postvisit( FunctionType * ) {}
    595         void CommonType_old::postvisit( StructInstType * ) {}
    596         void CommonType_old::postvisit( UnionInstType * ) {}
    597 
    598         void CommonType_old::postvisit( EnumInstType * enumInstType ) {
    599                 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
     315                        result->get_qualifiers() |= type2->get_qualifiers();
     316                } // if
     317        }
     318
     319        void CommonType::postvisit( FunctionType * ) {}
     320        void CommonType::postvisit( StructInstType * ) {}
     321        void CommonType::postvisit( UnionInstType * ) {}
     322
     323        void CommonType::postvisit( EnumInstType *enumInstType ) {
     324                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    600325                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    601326                        result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
     
    603328        }
    604329
    605         void CommonType_old::postvisit( TraitInstType * ) {
    606         }
    607 
    608         void CommonType_old::postvisit( TypeInstType * inst ) {
     330        void CommonType::postvisit( TraitInstType * ) {
     331        }
     332
     333        void CommonType::postvisit( TypeInstType *inst ) {
    609334                if ( widenFirst ) {
    610                         const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() );
     335                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
    611336                        if ( nt ) {
    612                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
     337                                TypeDecl *type = strict_dynamic_cast< TypeDecl* >( nt );
    613338                                if ( type->get_base() ) {
    614                                         Type::Qualifiers tq1 = inst->tq, tq2 = type2->tq;
     339                                        Type::Qualifiers tq1 = inst->get_qualifiers(), tq2 = type2->get_qualifiers();
    615340                                        AssertionSet have, need;
    616341                                        OpenVarSet newOpen( openVars );
    617                                         type2->tq = Type::Qualifiers();
    618                                         type->get_base()->tq = tq1;
     342                                        type2->get_qualifiers() = Type::Qualifiers();
     343                                        type->get_base()->get_qualifiers() = tq1;
    619344                                        if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) {
    620345                                                result = type2->clone();
    621                                                 result->tq = tq1 | tq2;
     346                                                result->get_qualifiers() = tq1 | tq2;
    622347                                        } // if
    623                                         type2->tq = tq2;
    624                                         type->get_base()->tq = Type::Qualifiers();
     348                                        type2->get_qualifiers() = tq2;
     349                                        type->get_base()->get_qualifiers() = Type::Qualifiers();
    625350                                } // if
    626351                        } // if
     
    628353        }
    629354
    630         void CommonType_old::postvisit( TupleType * ) {}
    631         void CommonType_old::postvisit( VarArgsType * ) {}
    632 
    633         void CommonType_old::postvisit( ZeroType * zeroType ) {
     355        void CommonType::postvisit( TupleType * ) {}
     356        void CommonType::postvisit( VarArgsType * ) {}
     357
     358        void CommonType::postvisit( ZeroType *zeroType ) {
    634359                if ( widenFirst ) {
    635                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    636                                 if ( widenSecond || zeroType->tq <= type2->tq ) {
     360                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     361                                if ( widenSecond || zeroType->get_qualifiers() <= type2->get_qualifiers() ) {
    637362                                        result = type2->clone();
    638                                         result->tq |= zeroType->tq;
     363                                        result->get_qualifiers() |= zeroType->get_qualifiers();
    639364                                }
    640                         } else if ( widenSecond && dynamic_cast< OneType * >( type2 ) ) {
    641                                 result = new BasicType( zeroType->tq, BasicType::SignedInt );
    642                                 result->tq |= type2->tq;
    643                         }
    644                 }
    645         }
    646 
    647         void CommonType_old::postvisit( OneType * oneType ) {
     365                        } else if ( widenSecond && dynamic_cast< OneType* >( type2 ) ) {
     366                                result = new BasicType( zeroType->get_qualifiers(), BasicType::SignedInt );
     367                                result->get_qualifiers() |= type2->get_qualifiers();
     368                        }
     369                }
     370        }
     371
     372        void CommonType::postvisit( OneType *oneType ) {
    648373                if ( widenFirst ) {
    649                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    650                                 if ( widenSecond || oneType->tq <= type2->tq ) {
     374                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     375                                if ( widenSecond || oneType->get_qualifiers() <= type2->get_qualifiers() ) {
    651376                                        result = type2->clone();
    652                                         result->tq |= oneType->tq;
     377                                        result->get_qualifiers() |= oneType->get_qualifiers();
    653378                                }
    654                         } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    655                                 result = new BasicType( oneType->tq, BasicType::SignedInt );
    656                                 result->tq |= type2->tq;
    657                         }
    658                 }
    659         }
    660 
    661         class CommonType_new final : public ast::WithShortCircuiting {
    662                 const ast::Type * type2;
    663                 WidenMode widen;
    664                 const ast::SymbolTable & symtab;
    665                 ast::TypeEnvironment & tenv;
    666                 const ast::OpenVarSet & open;
    667         public:
    668                 ast::ptr< ast::Type > result;
    669 
    670                 CommonType_new(
    671                         const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
    672                         ast::TypeEnvironment & env, const ast::OpenVarSet & o )
    673                 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {}
    674 
    675                 void previsit( const ast::Node * ) { visit_children = false; }
    676 
    677                 void postvisit( const ast::VoidType * ) {}
    678 
    679                 void postvisit( const ast::BasicType * basic ) {
    680                         if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
    681                                 #warning remove casts when `commonTypes` moved to new AST
    682                                 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ];
    683                                 if (
    684                                         ( ( kind == basic->kind && basic->qualifiers >= basic2->qualifiers )
    685                                                 || widen.first )
    686                                         && ( ( kind == basic2->kind && basic->qualifiers <= basic2->qualifiers )
    687                                                 || widen.second )
    688                                 ) {
    689                                         result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers };
    690                                 }
    691                         } else if (
    692                                 dynamic_cast< const ast::EnumInstType * >( type2 )
    693                                 || dynamic_cast< const ast::ZeroType * >( type2 )
    694                                 || dynamic_cast< const ast::OneType * >( type2 )
    695                         ) {
    696                                 #warning remove casts when `commonTypes` moved to new AST
    697                                 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ];
    698                                 if (
    699                                         ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
    700                                                 || widen.first )
    701                                         && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
    702                                                 || widen.second )
    703                                 ) {
    704                                         result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
    705                                 }
    706                         }
    707                 }
    708 
    709         private:
    710                 template< typename Pointer >
    711                 void getCommonWithVoidPointer( const Pointer * voidPtr, const Pointer * oPtr ) {
    712                         const ast::Type * base = oPtr->base;
    713                         if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) {
    714                                 auto entry = open.find( var->name );
    715                                 if ( entry != open.end() ) {
    716                                         ast::AssertionSet need, have;
    717                                         if ( ! tenv.bindVar(
    718                                                 var, voidPtr->base, entry->second, need, have, open, widen, symtab )
    719                                         ) return;
    720                                 }
    721                         }
    722                         result = voidPtr;
    723                         add_qualifiers( result, oPtr->qualifiers );
    724                 }
    725 
    726         public:
    727                 void postvisit( const ast::PointerType * pointer ) {
    728                         if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
    729                                 if (
    730                                         widen.first
    731                                         && pointer2->base.as< ast::VoidType >()
    732                                         && ! ast::isFtype( pointer->base )
    733                                 ) {
    734                                         getCommonWithVoidPointer( pointer2, pointer );
    735                                 } else if (
    736                                         widen.second
    737                                         && pointer->base.as< ast::VoidType >()
    738                                         && ! ast::isFtype( pointer2->base )
    739                                 ) {
    740                                         getCommonWithVoidPointer( pointer, pointer2 );
    741                                 } else if (
    742                                         ( pointer->base->qualifiers >= pointer2->base->qualifiers || widen.first )
    743                                         && ( pointer->base->qualifiers <= pointer2->base->qualifiers || widen.second )
    744                                 ) {
    745                                         ast::CV::Qualifiers q1 = pointer->base->qualifiers;
    746                                         ast::CV::Qualifiers q2 = pointer2->base->qualifiers;
    747 
    748                                         // force t{1,2} to be cloned if their qualifiers must be stripped, so that
    749                                         // pointer{,2}->base are unchanged
    750                                         ast::ptr< ast::Type > t1{ pointer->base }, t2{ pointer2->base };
    751                                         reset_qualifiers( t1 );
    752                                         reset_qualifiers( t2 );
    753 
    754                                         ast::AssertionSet have, need;
    755                                         ast::OpenVarSet newOpen{ open };
    756                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    757                                                 result = pointer;
    758                                                 if ( q1.val != q2.val ) {
    759                                                         // reset result->base->qualifiers to be union of two base qualifiers
    760                                                         strict_dynamic_cast< ast::PointerType * >(
    761                                                                 result.get_and_mutate()
    762                                                         )->base.get_and_mutate()->qualifiers = q1 | q2;
    763                                                 }
    764                                         }
    765                                 }
    766                         } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
    767                                 result = pointer;
    768                                 add_qualifiers( result, type2->qualifiers );
    769                         }
    770                 }
    771 
    772                 void postvisit( const ast::ArrayType * ) {}
    773 
    774                 void postvisit( const ast::ReferenceType * ref ) {
    775                         if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    776                                 if (
    777                                         widen.first && ref2->base.as< ast::VoidType >() && ! ast::isFtype( ref->base )
    778                                 ) {
    779                                         getCommonWithVoidPointer( ref2, ref );
    780                                 } else if (
    781                                         widen.second && ref->base.as< ast::VoidType>() && ! ast::isFtype( ref2->base )
    782                                 ) {
    783                                         getCommonWithVoidPointer( ref, ref2 );
    784                                 } else if (
    785                                         ( ref->base->qualifiers >= ref2->base->qualifiers || widen.first )
    786                                         && ( ref->base->qualifiers <= ref2->base->qualifiers || widen.second )
    787                                 ) {
    788                                         ast::CV::Qualifiers q1 = ref->base->qualifiers, q2 = ref2->base->qualifiers;
    789 
    790                                         // force t{1,2} to be cloned if their qualifiers must be stripped, so that
    791                                         // ref{,2}->base are unchanged
    792                                         ast::ptr< ast::Type > t1{ ref->base }, t2{ ref2->base };
    793                                         reset_qualifiers( t1 );
    794                                         reset_qualifiers( t2 );
    795 
    796                                         ast::AssertionSet have, need;
    797                                         ast::OpenVarSet newOpen{ open };
    798                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    799                                                 result = ref;
    800                                                 if ( q1.val != q2.val ) {
    801                                                         // reset result->base->qualifiers to be union of two base qualifiers
    802                                                         strict_dynamic_cast< ast::ReferenceType * >(
    803                                                                 result.get_and_mutate()
    804                                                         )->base.get_and_mutate()->qualifiers = q1 | q2;
    805                                                 }
    806                                         }
    807                                 }
    808                         } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
    809                                 result = ref;
    810                                 add_qualifiers( result, type2->qualifiers );
    811                         }
    812                 }
    813 
    814                 void postvisit( const ast::FunctionType * ) {}
    815 
    816                 void postvisit( const ast::StructInstType * ) {}
    817 
    818                 void postvisit( const ast::UnionInstType * ) {}
    819 
    820                 void postvisit( const ast::EnumInstType * enumInst ) {
    821                         if (
    822                                 dynamic_cast< const ast::BasicType * >( type2 )
    823                                 || dynamic_cast< const ast::ZeroType * >( type2 )
    824                                 || dynamic_cast< const ast::OneType * >( type2 )
    825                         ) {
    826                                 // reuse BasicType/EnumInstType common type by swapping
    827                                 result = commonType( type2, enumInst, widen, symtab, tenv, open );
    828                         }
    829                 }
    830 
    831                 void postvisit( const ast::TraitInstType * ) {}
    832 
    833                 void postvisit( const ast::TypeInstType * inst ) {
    834                         if ( ! widen.first ) return;
    835                         if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    836                                 if ( const ast::Type * base =
    837                                                 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base
    838                                 ) {
    839                                         ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers;
    840 
    841                                         // force t{1,2} to be cloned if their qualifiers must be mutated
    842                                         ast::ptr< ast::Type > t1{ base }, t2{ type2 };
    843                                         reset_qualifiers( t1, q1 );
    844                                         reset_qualifiers( t2 );
    845 
    846                                         ast::AssertionSet have, need;
    847                                         ast::OpenVarSet newOpen{ open };
    848                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    849                                                 result = type2;
    850                                                 reset_qualifiers( result, q1 | q2 );
    851                                         }
    852                                 }
    853                         }
    854                 }
    855 
    856                 void postvisit( const ast::TupleType * ) {}
    857 
    858                 void postvisit( const ast::VarArgsType * ) {}
    859 
    860                 void postvisit( const ast::ZeroType * zero ) {
    861                         if ( ! widen.first ) return;
    862                         if (
    863                                 dynamic_cast< const ast::BasicType * >( type2 )
    864                                 || dynamic_cast< const ast::PointerType * >( type2 )
    865                                 || dynamic_cast< const ast::EnumInstType * >( type2 )
    866                         ) {
    867                                 if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
    868                                         result = type2;
    869                                         add_qualifiers( result, zero->qualifiers );
    870                                 }
    871                         } else if ( widen.second && dynamic_cast< const ast::OneType * >( type2 ) ) {
    872                                 result = new ast::BasicType{
    873                                         ast::BasicType::SignedInt, zero->qualifiers | type2->qualifiers };
    874                         }
    875                 }
    876 
    877                 void postvisit( const ast::OneType * one ) {
    878                         if ( ! widen.first ) return;
    879                         if (
    880                                 dynamic_cast< const ast::BasicType * >( type2 )
    881                                 || dynamic_cast< const ast::EnumInstType * >( type2 )
    882                         ) {
    883                                 if ( widen.second || one->qualifiers <= type2->qualifiers ) {
    884                                         result = type2;
    885                                         add_qualifiers( result, one->qualifiers );
    886                                 }
    887                         } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
    888                                 result = new ast::BasicType{
    889                                         ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers };
    890                         }
    891                 }
    892 
    893         };
    894 
    895         namespace {
    896                 ast::ptr< ast::Type > handleReference(
    897                         const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen,
    898                         const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    899                         const ast::OpenVarSet & open
    900                 ) {
    901                         ast::ptr<ast::Type> common;
    902                         ast::AssertionSet have, need;
    903                         ast::OpenVarSet newOpen{ open };
    904 
    905                         // need unify to bind type variables
    906                         if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) {
    907                                 ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers;
    908                                 PRINT(
    909                                         std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
    910                                 )
    911                                 if ( ( widen.first || q2 <= q1 ) && ( widen.second || q1 <= q2 ) ) {
    912                                         PRINT(
    913                                                 std::cerr << "widen okay" << std::endl;
    914                                         )
    915                                         add_qualifiers( common, q1 | q2 );
    916                                         return common;
    917                                 }
    918                         }
    919 
    920                         PRINT(
    921                                 std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
    922                         )
    923                         return { nullptr };
    924                 }
    925         }
    926 
    927         ast::ptr< ast::Type > commonType(
    928                         const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    929                         WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    930                         const ast::OpenVarSet & open
    931         ) {
    932                 unsigned depth1 = type1->referenceDepth();
    933                 unsigned depth2 = type2->referenceDepth();
    934 
    935                 if ( depth1 != depth2 ) {  // implies depth1 > 0 || depth2 > 0
    936                         PRINT(
    937                                 std::cerr << "reference depth diff: " << (depth1-depth2) << std::endl;
    938                         )
    939                         ast::ptr< ast::Type > result;
    940                         const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
    941                         const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
    942 
    943                         if ( depth1 > depth2 ) {
    944                                 assert( ref1 );
    945                                 result = handleReference( ref1->base, type2, widen, symtab, env, open );
    946                         } else {  // implies depth1 < depth2
    947                                 assert( ref2 );
    948                                 result = handleReference( type1, ref2->base, widen, symtab, env, open );
    949                         }
    950 
    951                         if ( result && ref1 ) {
    952                                 // formal is reference, so result should be reference
    953                                 PRINT(
    954                                         std::cerr << "formal is reference; result should be reference" << std::endl;
    955                                 )
    956                                 result = new ast::ReferenceType{ result, ref1->qualifiers };
    957                         }
    958 
    959                         PRINT(
    960                                 std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is "
    961                                 "[" << result << "]" << std::endl;
    962                         )
    963                         return result;
    964                 }
    965                 // otherwise both are reference types of the same depth and this is handled by the visitor
    966                 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
    967                 type1->accept( visitor );
    968                 ast::ptr< ast::Type > result = visitor.pass.result;
    969 
    970                 // handling for opaque type declarations (?)
    971                 if ( ! result && widen.second ) {
    972                         if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) {
    973                                 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    974                                         auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt );
    975                                         if ( type->base ) {
    976                                                 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
    977                                                 ast::AssertionSet have, need;
    978                                                 ast::OpenVarSet newOpen{ open };
    979 
    980                                                 // force t{1,2} to be cloned if its qualifiers must be stripped, so that
    981                                                 // type1 and type->base are left unchanged; calling convention forces
    982                                                 // {type1,type->base}->strong_ref >= 1
    983                                                 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base };
    984                                                 reset_qualifiers( t1 );
    985                                                 reset_qualifiers( t2, q1 );
    986 
    987                                                 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) {
    988                                                         result = t1;
    989                                                         reset_qualifiers( result, q1 | q2 );
    990                                                 }
    991                                         }
    992                                 }
    993                         }
    994                 }
    995 
    996                 return result;
    997         }
    998 
     379                        } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
     380                                result = new BasicType( oneType->get_qualifiers(), BasicType::SignedInt );
     381                                result->get_qualifiers() |= type2->get_qualifiers();
     382                        }
     383                }
     384        }
    999385} // namespace ResolvExpr
    1000386
  • src/ResolvExpr/ConversionCost.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 07:06:19 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Aug 12 10:21:00 2019
    13 // Update Count     : 27
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Sep 25 15:43:34 2017
     13// Update Count     : 10
    1414//
    1515
     
    2828
    2929namespace ResolvExpr {
    30 #if 0
    31         const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0,  0 };
    32         const Cost Cost::infinity =  Cost{ -1, -1, -1, -1, -1,  1, -1 };
    33         const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0,  0 };
    34         const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0,  0 };
    35         const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0,  0 };
    36         const Cost Cost::sign =      Cost{  0,  0,  0,  1,  0,  0,  0 };
    37         const Cost Cost::var =       Cost{  0,  0,  0,  0,  1,  0,  0 };
    38         const Cost Cost::spec =      Cost{  0,  0,  0,  0,  0, -1,  0 };
    39         const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  0,  1 };
    40 #endif
     30        const Cost Cost::zero =      Cost(  0,  0,  0,  0 );
     31        const Cost Cost::infinity =  Cost( -1, -1, -1, -1 );
     32        const Cost Cost::unsafe =    Cost(  1,  0,  0,  0 );
     33        const Cost Cost::poly =      Cost(  0,  1,  0,  0 );
     34        const Cost Cost::safe =      Cost(  0,  0,  1,  0 );
     35        const Cost Cost::reference = Cost(  0,  0,  0,  1 );
    4136
    4237#if 0
     
    4540#define PRINT(x)
    4641#endif
    47 
    48         Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
    49                         const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    50                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
     42        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     43                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    5144                        PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
    52                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
     45                        if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->name ) ) {
    5346                                if ( eqvClass->type ) {
    54                                         return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
     47                                        return conversionCost( src, eqvClass->type, indexer, env );
    5548                                } else {
    5649                                        return Cost::infinity;
    5750                                }
    58                         } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
     51                        } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    5952                                PRINT( std::cerr << " found" << std::endl; )
    60                                 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
     53                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    6154                                // all typedefs should be gone by this point
    6255                                assert( type );
    6356                                if ( type->base ) {
    64                                         return conversionCost( src, type->base, srcIsLvalue, indexer, env )
    65                                                 + Cost::safe;
     57                                        return conversionCost( src, type->base, indexer, env ) + Cost::safe;
    6658                                } // if
    6759                        } // if
     
    7971                        PRINT( std::cerr << "compatible!" << std::endl; )
    8072                        return Cost::zero;
    81                 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
     73                } else if ( dynamic_cast< VoidType* >( dest ) ) {
    8274                        return Cost::safe;
    83                 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
     75                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    8476                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    85                         return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
     77                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
    8678                                return ptrsAssignable( t1, t2, env );
    8779                        });
    8880                } else {
    89                         PassVisitor<ConversionCost> converter(
    90                                 dest, srcIsLvalue, indexer, env,
    91                                 (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
    92                                         conversionCost );
     81                        PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
    9382                        src->accept( converter );
    9483                        if ( converter.pass.get_cost() == Cost::infinity ) {
     
    10089        }
    10190
    102         static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
    103                         int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
     91        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    10492                PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
    10593                if ( diff > 0 ) {
    10694                        // TODO: document this
    107                         Cost cost = convertToReferenceCost(
    108                                 strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
    109                                 diff-1, indexer, env, func );
     95                        Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
    11096                        cost.incReference();
    11197                        return cost;
    11298                } else if ( diff < -1 ) {
    11399                        // TODO: document this
    114                         Cost cost = convertToReferenceCost(
    115                                 src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
    116                                 diff+1, indexer, env, func );
     100                        Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func );
    117101                        cost.incReference();
    118102                        return cost;
    119103                } else if ( diff == 0 ) {
    120                         const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
    121                         const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
     104                        ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
     105                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
    122106                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
    123107                                PRINT( std::cerr << "converting between references" << std::endl; )
    124                                 Type::Qualifiers tq1 = srcAsRef->base->tq;
    125                                 Type::Qualifiers tq2 = destAsRef->base->tq;
     108                                Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers();
     109                                Type::Qualifiers tq2 = destAsRef->base->get_qualifiers();
    126110                                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
    127111                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     
    144128                        } else {
    145129                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    146                                 PassVisitor<ConversionCost> converter(
    147                                         dest, srcIsLvalue, indexer, env,
    148                                         (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
    149                                                 conversionCost );
     130                                PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
    150131                                src->accept( converter );
    151132                                return converter.pass.get_cost();
    152133                        } // if
    153134                } else {
    154                         const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
     135                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
    155136                        assert( diff == -1 && destAsRef );
    156137                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    157138                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
    158139                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
    159                                 if ( srcIsLvalue ) {
     140                                if ( src->get_lvalue() ) {
    160141                                        PRINT(
    161142                                                std::cerr << "lvalue to reference conversion" << std::endl;
     
    163144                                        )
    164145                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
    165                                         if ( src->tq == destAsRef->base->tq ) {
     146                                        if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
    166147                                                return Cost::reference; // cost needs to be non-zero to add cast
    167                                         } if ( src->tq < destAsRef->base->tq ) {
     148                                        } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
    168149                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    169150                                        } else {
     
    185166        }
    186167
    187         Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
    188                         const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
     168        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    189169                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
    190                 Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
     170                Cost cost = convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
    191171                PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
    192172                return cost;
    193173        }
    194174
    195         ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    196                 : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
    197         }
    198 
    199         // GENERATED START, DO NOT EDIT
    200         // GENERATED BY BasicTypes-gen.cc
    201         /* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves)
    202                                  _Bool
    203         char                signed char         unsigned char
    204                   signed short int         unsigned short int
    205                   signed int               unsigned int
    206                   signed long int          unsigned long int
    207                   signed long long int     unsigned long long int
    208                   __int128                 unsigned __int128
    209                   _Float16                 _Float16 _Complex
    210                   _Float32                 _Float32 _Complex
    211                   float                    float _Complex
    212                   _Float32x                _Float32x _Complex
    213                   _Float64                 _Float64 _Complex
    214                   double                   double _Complex
    215                   _Float64x                _Float64x _Complex
    216                              __float80
    217                   _Float128                _Float128 _Complex
    218                             __float128
    219                   long double              long double _Complex
    220                   _Float128x               _Float128x _Complex
    221         */
    222         // GENERATED END
    223 
    224         // GENERATED START, DO NOT EDIT
    225         // GENERATED BY BasicTypes-gen.cc
    226         static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
    227                 /*               B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
    228                 /*      B */ {   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,  17,  16,  18,  17, },
    229                 /*      C */ {  -1,   0,   1,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
    230                 /*     SC */ {  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
    231                 /*     UC */ {  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
    232                 /*     SI */ {  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  15,  14,  16,  15, },
    233                 /*    SUI */ {  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  15,  14,  16,  15, },
    234                 /*      I */ {  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  14,  13,  15,  14, },
    235                 /*     UI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  14,  13,  15,  14, },
    236                 /*     LI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  13,  12,  14,  13, },
    237                 /*    LUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  13,  12,  14,  13, },
    238                 /*    LLI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  12,  11,  13,  12, },
    239                 /*   LLUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  12,  11,  13,  12, },
    240                 /*     IB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  11,  10,  12,  11, },
    241                 /*    UIB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  11,  10,  12,  11, },
    242                 /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,  10,   9,  11,  10, },
    243                 /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,   5,  -1,   6,  -1,  -1,   7,  -1,  -1,   8,  -1,   9, },
    244                 /*     _F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   9,   8,  10,   9, },
    245                 /*    _FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,   5,  -1,  -1,   6,  -1,  -1,   7,  -1,   8, },
    246                 /*      F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   8,   7,   9,   8, },
    247                 /*     FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,  -1,   5,  -1,  -1,   6,  -1,   7, },
    248                 /*    _FX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   7,   6,   8,   7, },
    249                 /*   _FXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,  -1,   4,  -1,  -1,   5,  -1,   6, },
    250                 /*     FD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   6,   5,   7,   6, },
    251                 /*   _FDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,  -1,   3,  -1,  -1,   4,  -1,   5, },
    252                 /*      D */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   5,   4,   6,   5, },
    253                 /*     DC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,  -1,   2,  -1,  -1,   3,  -1,   4, },
    254                 /*   F80X */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   4,   3,   5,   4, },
    255                 /*  _FDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   1,  -1,  -1,   2,  -1,   3, },
    256                 /*    F80 */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   1,   0,   1,   2,   2,   3,   3,   4,   4, },
    257                 /*    _FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3, },
    258                 /*  _FLDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   1,  -1,   2, },
    259                 /*     FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   1,   0,   1,   2,   2,   3, },
    260                 /*     LD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2, },
    261                 /*    LDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1, },
    262                 /*   _FBX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1, },
    263                 /* _FLDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0, },
    264         }; // costMatrix
    265         static const int maxIntCost = 15;
    266         // GENERATED END
     175        ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     176                : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
     177        }
     178
     179/*
     180            Old
     181            ===
     182           Double
     183             |
     184           Float
     185             |
     186           ULong
     187           /   \
     188        UInt    Long
     189           \   /
     190            Int
     191             |
     192           Ushort
     193             |
     194           Short
     195             |
     196           Uchar
     197           /   \
     198        Schar   Char
     199
     200                                New
     201                                ===
     202                       +-----LongDoubleComplex--+
     203           LongDouble--+          |             +-LongDoubleImag
     204             |         +---DoubleComplex---+         |
     205           Double------+        |          +----DoubleImag
     206             |           +-FloatComplex-+            |
     207           Float---------+              +-------FloatImag
     208             |
     209          ULongLong
     210             |
     211          LongLong
     212             |
     213           ULong
     214           /   \
     215        UInt    Long
     216           \   /
     217            Int
     218             |
     219           Ushort
     220             |
     221           Short
     222             |
     223           Uchar
     224           /   \
     225        Schar   Char
     226           \   /
     227            Bool
     228*/
     229
     230        static const int costMatrix[][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
     231        /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag  I128,   U128, F80, F128 */
     232                /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              12,             13,             14,             12,             13,             14,             -1,             -1,             -1,             10,             11,       14,   15},
     233                /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,       13,   14},
     234                /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,       13,   14},
     235                /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              10,             11,             12,             10,             11,             12,             -1,             -1,             -1,             8,              9,        12,   13},
     236                /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              9,              10,             11,             9,              10,             11,             -1,             -1,             -1,             7,              8,        11,   12},
     237                /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              8,              9,              10,             8,              9,              10,             -1,             -1,             -1,             6,              7,        10,   11},
     238                /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              7,              8,              9,              7,              8,              9,              -1,             -1,             -1,             5,              6,        9,    10},
     239                /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,        8,    9},
     240                /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,        8,    9},
     241                /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              5,              6,              7,              5,              6,              7,              -1,             -1,             -1,             3,              4,        7,    8},
     242                /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              4,              5,              6,              4,              5,              6,              -1,             -1,             -1,             2,              3,        6,    7},
     243                /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              3,              4,              5,              3,              4,              5,              -1,             -1,             -1,             1,              2,        5,    6},
     244
     245                /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1,             -1,             -1,       2,    3},
     246                /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1,             -1,             -1,       1,    2},
     247                /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       -1,   1},
     248                /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
     249                /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
     250                /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
     251                /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2,              -1,             -1,       -1,   -1},
     252                /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1,              -1,             -1,       -1,   -1},
     253                /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0,              -1,             -1,       -1,   -1},
     254
     255                /* I128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             2,              3,              4,              3,              4,              5,              -1,             -1,             -1,             0,              1,        4,    4},
     256                /* U128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              2,              3,              4,              -1,             -1,             -1,             -1,             0,        3,    3},
     257
     258                /* F80 */       { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       0,    1},
     259                /* F128 */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       -1,   0},
     260        };
    267261        static_assert(
    268                 sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
    269                 "Missing row in the cost matrix"
     262                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
     263                "Each basic type kind should have a corresponding row in the cost matrix"
    270264        );
    271265
    272         // GENERATED START, DO NOT EDIT
    273         // GENERATED BY BasicTypes-gen.cc
    274         static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
    275                 /*               B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
    276                 /*      B */ {   0,   0,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    277                 /*      C */ {  -1,   0,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    278                 /*     SC */ {  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    279                 /*     UC */ {  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    280                 /*     SI */ {  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    281                 /*    SUI */ {  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    282                 /*      I */ {  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    283                 /*     UI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    284                 /*     LI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    285                 /*    LUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    286                 /*    LLI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    287                 /*   LLUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    288                 /*     IB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    289                 /*    UIB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    290                 /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    291                 /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    292                 /*     _F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    293                 /*    _FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    294                 /*      F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    295                 /*     FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    296                 /*    _FX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    297                 /*   _FXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    298                 /*     FD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    299                 /*   _FDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    300                 /*      D */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    301                 /*     DC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    302                 /*   F80X */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    303                 /*  _FDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    304                 /*    F80 */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
    305                 /*    _FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0, },
    306                 /*  _FLDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
    307                 /*     FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0, },
    308                 /*     LD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0, },
    309                 /*    LDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0, },
    310                 /*   _FBX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0, },
    311                 /* _FLDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0, },
    312         }; // signMatrix
    313         // GENERATED END
    314         static_assert(
    315                 sizeof(signMatrix)/sizeof(signMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
    316                 "Missing row in the sign matrix"
    317         );
    318 
    319         void ConversionCost::postvisit( const VoidType * ) {
     266
     267        void ConversionCost::postvisit( VoidType * ) {
    320268                cost = Cost::infinity;
    321269        }
    322270
    323         void ConversionCost::postvisit(const BasicType * basicType) {
    324                 if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    325                         int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ];
     271        void ConversionCost::postvisit(BasicType *basicType) {
     272                if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
     273                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
    326274                        if ( tableResult == -1 ) {
    327275                                cost = Cost::unsafe;
     
    329277                                cost = Cost::zero;
    330278                                cost.incSafe( tableResult );
    331                                 cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
    332                         } // if
    333                 } else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
     279                        } // if
     280                } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
    334281                        // xxx - not positive this is correct, but appears to allow casting int => enum
    335282                        cost = Cost::unsafe;
     
    338285        }
    339286
    340         void ConversionCost::postvisit( const PointerType * pointerType ) {
    341                 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
     287        void ConversionCost::postvisit( PointerType * pointerType ) {
     288                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    342289                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
    343                         Type::Qualifiers tq1 = pointerType->base->tq;
    344                         Type::Qualifiers tq2 = destAsPtr->base->tq;
     290                        Type::Qualifiers tq1 = pointerType->base->get_qualifiers();
     291                        Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers();
    345292                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    346293                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     
    351298                                        // types are the same, except otherPointer has more qualifiers
    352299                                        cost = Cost::safe;
    353                                 } // if
     300                                }
    354301                        } else {
    355302                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
     
    371318        }
    372319
    373         void ConversionCost::postvisit( const ArrayType * ) {}
    374 
    375         void ConversionCost::postvisit( const ReferenceType * refType ) {
     320        void ConversionCost::postvisit( ArrayType * ) {}
     321
     322        void ConversionCost::postvisit( ReferenceType * refType ) {
    376323                // Note: dest can never be a reference, since it would have been caught in an earlier check
    377                 assert( ! dynamic_cast< const ReferenceType * >( dest ) );
     324                assert( ! dynamic_cast< ReferenceType * >( dest ) );
    378325                // convert reference to rvalue: cv T1 & => T2
    379326                // recursively compute conversion cost from T1 to T2.
    380327                // cv can be safely dropped because of 'implicit dereference' behavior.
    381                 cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
    382                 if ( refType->base->tq == dest->tq ) {
     328                cost = costFunc( refType->base, dest, indexer, env );
     329                if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
    383330                        cost.incReference();  // prefer exact qualifiers
    384                 } else if ( refType->base->tq < dest->tq ) {
     331                } else if ( refType->base->get_qualifiers() < dest->get_qualifiers() ) {
    385332                        cost.incSafe(); // then gaining qualifiers
    386333                } else {
     
    390337        }
    391338
    392         void ConversionCost::postvisit( const FunctionType * ) {}
    393 
    394         void ConversionCost::postvisit( const StructInstType * inst ) {
    395                 if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
     339        void ConversionCost::postvisit( FunctionType * ) {}
     340
     341        void ConversionCost::postvisit( StructInstType * inst ) {
     342                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
    396343                        if ( inst->name == destAsInst->name ) {
    397344                                cost = Cost::zero;
     
    400347        }
    401348
    402         void ConversionCost::postvisit( const UnionInstType * inst ) {
    403                 if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
     349        void ConversionCost::postvisit( UnionInstType * inst ) {
     350                if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
    404351                        if ( inst->name == destAsInst->name ) {
    405352                                cost = Cost::zero;
     
    408355        }
    409356
    410         void ConversionCost::postvisit( const EnumInstType * ) {
     357        void ConversionCost::postvisit( EnumInstType * ) {
    411358                static Type::Qualifiers q;
    412359                static BasicType integer( q, BasicType::SignedInt );
    413                 cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
     360                cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
    414361                if ( cost < Cost::unsafe ) {
    415362                        cost.incSafe();
     
    417364        }
    418365
    419         void ConversionCost::postvisit( const TraitInstType * ) {}
    420 
    421         void ConversionCost::postvisit( const TypeInstType * inst ) {
    422                 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
    423                         cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
    424                 } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
     366        void ConversionCost::postvisit( TraitInstType * ) {}
     367
     368        void ConversionCost::postvisit( TypeInstType *inst ) {
     369                if ( const EqvClass *eqvClass = env.lookup( inst->name ) ) {
     370                        cost = costFunc( eqvClass->type, dest, indexer, env );
     371                } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
    425372                        if ( inst->name == destAsInst->name ) {
    426373                                cost = Cost::zero;
    427374                        }
    428                 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
    429                         const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
     375                } else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) {
     376                        TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    430377                        // all typedefs should be gone by this point
    431378                        assert( type );
    432379                        if ( type->base ) {
    433                                 cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
    434                         } // if
    435                 } // if
    436         }
    437 
    438         void ConversionCost::postvisit( const TupleType * tupleType ) {
     380                                cost = costFunc( type->base, dest, indexer, env ) + Cost::safe;
     381                        } // if
     382                } // if
     383        }
     384
     385        void ConversionCost::postvisit( TupleType * tupleType ) {
    439386                Cost c = Cost::zero;
    440                 if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
     387                if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
    441388                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
    442389                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
    443390                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
    444                                 Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
     391                                Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env );
    445392                                if ( newCost == Cost::infinity ) {
    446393                                        return;
     
    456403        }
    457404
    458         void ConversionCost::postvisit( const VarArgsType * ) {
    459                 if ( dynamic_cast< const VarArgsType * >( dest ) ) {
     405        void ConversionCost::postvisit( VarArgsType * ) {
     406                if ( dynamic_cast< VarArgsType* >( dest ) ) {
    460407                        cost = Cost::zero;
    461408                }
    462409        }
    463410
    464         void ConversionCost::postvisit( const ZeroType * ) {
    465                 if ( dynamic_cast< const ZeroType * >( dest ) ) {
     411        void ConversionCost::postvisit( ZeroType * ) {
     412                if ( dynamic_cast< ZeroType * >( dest ) ) {
    466413                        cost = Cost::zero;
    467                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    468                         // copied from visit(BasicType *) for signed int, but +1 for safe conversions
    469                         int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
     414                } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
     415                        // copied from visit(BasicType*) for signed int, but +1 for safe conversions
     416                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    470417                        if ( tableResult == -1 ) {
    471418                                cost = Cost::unsafe;
     
    473420                                cost = Cost::zero;
    474421                                cost.incSafe( tableResult + 1 );
    475                                 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
    476                         } // if
    477                 } else if ( dynamic_cast< const PointerType * >( dest ) ) {
     422                        }
     423                } else if ( dynamic_cast< PointerType* >( dest ) ) {
     424                        cost = Cost::safe;
     425                }
     426        }
     427
     428        void ConversionCost::postvisit( OneType * ) {
     429                if ( dynamic_cast< OneType * >( dest ) ) {
    478430                        cost = Cost::zero;
    479                         cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
    480                 } // if
    481         }
    482 
    483         void ConversionCost::postvisit( const OneType * ) {
    484                 if ( dynamic_cast< const OneType * >( dest ) ) {
    485                         cost = Cost::zero;
    486                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    487                         // copied from visit(BasicType *) for signed int, but +1 for safe conversions
    488                         int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
     431                } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
     432                        // copied from visit(BasicType*) for signed int, but +1 for safe conversions
     433                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
    489434                        if ( tableResult == -1 ) {
    490435                                cost = Cost::unsafe;
     
    492437                                cost = Cost::zero;
    493438                                cost.incSafe( tableResult + 1 );
    494                                 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
    495                         } // if
    496                 } // if
    497         }
    498 
    499 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
    500                 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
    501         return ptrsAssignable( t1, t2, env );
    502 }
    503 
    504 // TODO: This is used for overload resolution. It might be able to be dropped once the old system
    505 // is removed.
    506 static Cost localConversionCost(
    507         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    508         const ast::TypeEnvironment & env
    509 ) { return conversionCost( src, dst, symtab, env ); }
    510 
    511 Cost conversionCost(
    512         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    513         const ast::TypeEnvironment & env
    514 ) {
    515         if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    516                 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
    517                         if ( eqv->bound ) {
    518                                 return conversionCost(src, eqv->bound, symtab, env );
    519                         } else {
    520                                 return Cost::infinity;
    521                         }
    522                 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
    523                         const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
    524                         assertf( type, "Unexpected typedef." );
    525                         if ( type->base ) {
    526                                 return conversionCost( src, type->base, symtab, env ) + Cost::safe;
    527439                        }
    528440                }
    529441        }
    530         if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
    531                 return Cost::zero;
    532         } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
    533                 return Cost::safe;
    534         } else if ( const ast::ReferenceType * refType =
    535                          dynamic_cast< const ast::ReferenceType * >( dst ) ) {
    536                 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
    537         } else {
    538                 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
    539                 src->accept( converter );
    540                 return converter.pass.cost;
    541         }
    542 }
    543 
    544 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
    545                 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    546                 NumCostCalculation func ) {
    547         if ( 0 < diff ) {
    548                 Cost cost = convertToReferenceCost(
    549                         strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
    550                         dst, (diff - 1), symtab, env, func );
    551                 cost.incReference();
    552                 return cost;
    553         } else if ( diff < -1 ) {
    554                 Cost cost = convertToReferenceCost(
    555                         src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
    556                         (diff + 1), symtab, env, func );
    557                 cost.incReference();
    558                 return cost;
    559         } else if ( 0 == diff ) {
    560                 const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
    561                 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
    562                 if ( srcAsRef && dstAsRef ) {
    563                         ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
    564                         ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
    565                         if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    566                                         srcAsRef->base, dstAsRef->base, symtab, env ) ) {
    567                                 if ( tq1 == tq2 ) {
    568                                         return Cost::zero;
    569                                 } else {
    570                                         return Cost::safe;
    571                                 }
    572                         } else {
    573                                 int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
    574                                 if ( 0 < assignResult ) {
    575                                         return Cost::safe;
    576                                 } else if ( assignResult < 0 ) {
    577                                         return Cost::unsafe;
    578                                 }
    579                         }
    580                 } else {
    581                         ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
    582                         src->accept( converter );
    583                         return converter.pass.cost;
    584                 }
    585         } else {
    586                 assert( -1 == diff );
    587                 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
    588                 assert( dstAsRef );
    589                 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
    590                         if ( src->is_lvalue() ) {
    591                                 if ( src->qualifiers == dstAsRef->base->qualifiers ) {
    592                                         return Cost::reference;
    593                                 } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
    594                                         return Cost::safe;
    595                                 } else {
    596                                         return Cost::unsafe;
    597                                 }
    598                         } else if ( dstAsRef->base->is_const() ) {
    599                                 return Cost::safe;
    600                         } else {
    601                                 return Cost::unsafe;
    602                         }
    603                 }
    604         }
    605         return Cost::infinity;
    606 }
    607 
    608 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
    609             const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    610                 NumCostCalculation func ) {
    611         int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
    612         return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
    613 }
    614 
    615 void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
    616         (void)voidType;
    617         cost = Cost::infinity;
    618 }
    619 
    620 void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
    621         if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
    622                 int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
    623                 if ( tableResult == -1 ) {
    624                         cost = Cost::unsafe;
    625                 } else {
    626                         cost = Cost::zero;
    627                         cost.incSafe( tableResult );
    628                         cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
    629                 }
    630         } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    631                 // xxx - not positive this is correct, but appears to allow casting int => enum
    632                 cost = Cost::unsafe;
    633         }
    634 }
    635 
    636 void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
    637         if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
    638                 ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
    639                 ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
    640                 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    641                                 pointerType->base, dstAsPtr->base, symtab, env ) ) {
    642                         if ( tq1 == tq2 ) {
    643                                 cost = Cost::zero;
    644                         } else {
    645                                 cost = Cost::safe;
    646                         }
    647                 } else {
    648                         int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
    649                         if ( 0 < assignResult && tq1 <= tq2 ) {
    650                                 if ( tq1 == tq2 ) {
    651                                         cost = Cost::safe;
    652                                 } else {
    653                                         cost = Cost::safe + Cost::safe;
    654                                 }
    655                         } else if ( assignResult < 0 ) {
    656                                 cost = Cost::unsafe;
    657                         } // else Cost::infinity
    658                 }
    659         }
    660 }
    661 
    662 void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
    663         (void)arrayType;
    664 }
    665 
    666 void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
    667         assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
    668 
    669         cost = costCalc( refType->base, dst, symtab, env );
    670         if ( refType->base->qualifiers == dst->qualifiers ) {
    671                 cost.incReference();
    672         } else if ( refType->base->qualifiers < dst->qualifiers ) {
    673                 cost.incSafe();
    674         } else {
    675                 cost.incUnsafe();
    676         }
    677 }
    678 
    679 void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
    680         (void)functionType;
    681 }
    682 
    683 void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
    684         if ( const ast::StructInstType * dstAsInst =
    685                         dynamic_cast< const ast::StructInstType * >( dst ) ) {
    686                 if ( structInstType->name == dstAsInst->name ) {
    687                         cost = Cost::zero;
    688                 }
    689         }
    690 }
    691 
    692 void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
    693         if ( const ast::UnionInstType * dstAsInst =
    694                         dynamic_cast< const ast::UnionInstType * >( dst ) ) {
    695                 if ( unionInstType->name == dstAsInst->name ) {
    696                         cost = Cost::zero;
    697                 }
    698         }
    699 }
    700 
    701 void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    702         (void)enumInstType;
    703         static const ast::BasicType integer( ast::BasicType::SignedInt );
    704         cost = costCalc( &integer, dst, symtab, env );
    705         if ( cost < Cost::unsafe ) {
    706                 cost.incSafe();
    707         }
    708 }
    709 
    710 void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
    711         (void)traitInstType;
    712 }
    713 
    714 void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
    715         if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
    716                 cost = costCalc( eqv->bound, dst, symtab, env );
    717         } else if ( const ast::TypeInstType * dstAsInst =
    718                         dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    719                 if ( typeInstType->name == dstAsInst->name ) {
    720                         cost = Cost::zero;
    721                 }
    722         } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
    723                 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
    724                 assertf( type, "Unexpected typedef.");
    725                 if ( type->base ) {
    726                         cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
    727                 }
    728         }
    729 }
    730 
    731 void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
    732         Cost c = Cost::zero;
    733         if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
    734                 auto srcIt = tupleType->types.begin();
    735                 auto dstIt = dstAsTuple->types.begin();
    736                 auto srcEnd = tupleType->types.end();
    737                 auto dstEnd = dstAsTuple->types.end();
    738                 while ( srcIt != srcEnd && dstIt != dstEnd ) {
    739                         Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
    740                         if ( newCost == Cost::infinity ) {
    741                                 return;
    742                         }
    743                         c += newCost;
    744                 }
    745                 if ( dstIt != dstEnd ) {
    746                         cost = Cost::infinity;
    747                 } else {
    748                         cost = c;
    749                 }
    750         }
    751 }
    752 
    753 void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
    754         (void)varArgsType;
    755         if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
    756                 cost = Cost::zero;
    757         }
    758 }
    759 
    760 void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
    761         (void)zeroType;
    762         if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
    763                 cost = Cost::zero;
    764         } else if ( const ast::BasicType * dstAsBasic =
    765                         dynamic_cast< const ast::BasicType * >( dst ) ) {
    766                 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
    767                 if ( -1 == tableResult ) {
    768                         cost = Cost::unsafe;
    769                 } else {
    770                         cost = Cost::zero;
    771                         cost.incSafe( tableResult + 1 );
    772                         cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    773                 }
    774         }
    775 }
    776 
    777 void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
    778         (void)oneType;
    779         if ( dynamic_cast< const ast::OneType * >( dst ) ) {
    780                 cost = Cost::zero;
    781         } else if ( const ast::BasicType * dstAsBasic =
    782                         dynamic_cast< const ast::BasicType * >( dst ) ) {
    783                 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
    784                 if ( -1 == tableResult ) {
    785                         cost = Cost::unsafe;
    786                 } else {
    787                         cost = Cost::zero;
    788                         cost.incSafe( tableResult + 1 );
    789                         cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    790                 }
    791         } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    792                 cost = Cost::zero;
    793                 cost.incSafe( maxIntCost + 2 );
    794         }
    795 }
    796 
    797 
    798442} // namespace ResolvExpr
    799443
  • src/ResolvExpr/ConversionCost.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:37:28 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:13:00 2019
    13 // Update Count     : 6
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:38:24 2017
     13// Update Count     : 4
    1414//
    1515
     
    2020#include "Cost.h"             // for Cost
    2121
    22 #include "AST/Fwd.hpp"
    23 #include "AST/Pass.hpp"       // for WithShortCircuiting
    2422#include "Common/PassVisitor.h"
    2523#include "SynTree/Visitor.h"  // for Visitor
     
    3331        class TypeEnvironment;
    3432
    35         typedef std::function<Cost(const Type *, const Type *, bool,
    36                 const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
    37 
     33        typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
    3834        struct ConversionCost : public WithShortCircuiting {
    3935          public:
    40                 ConversionCost( const Type * dest, bool srcIsLvalue,
    41                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
     36                ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
    4237
    4338                Cost get_cost() const { return cost; }
    4439
    45                 void previsit( const BaseSyntaxNode * ) { visit_children = false; }
     40                void previsit( BaseSyntaxNode * ) { visit_children = false; }
    4641
    47                 void postvisit( const VoidType * voidType );
    48                 void postvisit( const BasicType * basicType );
    49                 void postvisit( const PointerType * pointerType );
    50                 void postvisit( const ArrayType * arrayType );
    51                 void postvisit( const ReferenceType * refType );
    52                 void postvisit( const FunctionType * functionType );
    53                 void postvisit( const StructInstType * aggregateUseType );
    54                 void postvisit( const UnionInstType * aggregateUseType );
    55                 void postvisit( const EnumInstType * aggregateUseType );
    56                 void postvisit( const TraitInstType * aggregateUseType );
    57                 void postvisit( const TypeInstType * aggregateUseType );
    58                 void postvisit( const TupleType * tupleType );
    59                 void postvisit( const VarArgsType * varArgsType );
    60                 void postvisit( const ZeroType * zeroType );
    61                 void postvisit( const OneType * oneType );
     42                void postvisit( VoidType * voidType );
     43                void postvisit( BasicType * basicType );
     44                void postvisit( PointerType * pointerType );
     45                void postvisit( ArrayType * arrayType );
     46                void postvisit( ReferenceType * refType );
     47                void postvisit( FunctionType * functionType );
     48                void postvisit( StructInstType * aggregateUseType );
     49                void postvisit( UnionInstType * aggregateUseType );
     50                void postvisit( EnumInstType * aggregateUseType );
     51                void postvisit( TraitInstType * aggregateUseType );
     52                void postvisit( TypeInstType * aggregateUseType );
     53                void postvisit( TupleType * tupleType );
     54                void postvisit( VarArgsType * varArgsType );
     55                void postvisit( ZeroType * zeroType );
     56                void postvisit( OneType * oneType );
    6257          protected:
    63                 const Type * dest;
    64                 bool srcIsLvalue;
     58                Type *dest;
    6559                const SymTab::Indexer &indexer;
    6660                Cost cost;
     
    6963        };
    7064
    71         typedef std::function<int(const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
    72         Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
    73                 const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
    74 
    75 // Some function pointer types, differ in return type.
    76 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
    77         const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    78 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,
    79         const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    80 
    81 #warning when the old ConversionCost is removed, get ride of the _new suffix.
    82 class ConversionCost_new : public ast::WithShortCircuiting {
    83 protected:
    84         const ast::Type * dst;
    85         const ast::SymbolTable & symtab;
    86         const ast::TypeEnvironment & env;
    87         CostCalculation costCalc;
    88 public:
    89         Cost cost;
    90 
    91         ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
    92                         const ast::TypeEnvironment & env, CostCalculation costCalc ) :
    93                 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
    94         {}
    95 
    96         void previsit( const ast::Node * ) { visit_children = false; }
    97 
    98         void postvisit( const ast::VoidType * voidType );
    99         void postvisit( const ast::BasicType * basicType );
    100         void postvisit( const ast::PointerType * pointerType );
    101         void postvisit( const ast::ArrayType * arrayType );
    102         void postvisit( const ast::ReferenceType * refType );
    103         void postvisit( const ast::FunctionType * functionType );
    104         void postvisit( const ast::StructInstType * structInstType );
    105         void postvisit( const ast::UnionInstType * unionInstType );
    106         void postvisit( const ast::EnumInstType * enumInstType );
    107         void postvisit( const ast::TraitInstType * traitInstType );
    108         void postvisit( const ast::TypeInstType * typeInstType );
    109         void postvisit( const ast::TupleType * tupleType );
    110         void postvisit( const ast::VarArgsType * varArgsType );
    111         void postvisit( const ast::ZeroType * zeroType );
    112         void postvisit( const ast::OneType * oneType );
    113 };
    114 
    115 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    116         const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
    117 
     65        typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
     66        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
    11867} // namespace ResolvExpr
    11968
  • src/ResolvExpr/Cost.h

    rb067d9b r7951100  
    77// Cost.h --
    88//
    9 // Author           : Peter Buhr and Aaron Moss
     9// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:39:50 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 21 11:39:13 2019
    13 // Update Count     : 63
     12// Last Modified On : Sat Jul 22 09:35:55 2017
     13// Update Count     : 5
    1414//
    1515
     
    1717
    1818#include <iostream>
    19 #include <cassert>
    20 #include <climits>
    2119
    2220namespace ResolvExpr {
    23         // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the
    24         // specialization cost is a negative value so a correction is needed is a few places.
     21        class Cost {
     22          private:
     23                Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
    2524
    26         class Cost {
    27                 union {
    28                         struct {
    29                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    30                                 // Little-endian => first value is low priority and last is high priority.
    31                                 unsigned char padding;                                  ///< unused
    32                                 unsigned char referenceCost;                    ///< reference conversions
    33                                 unsigned char specCost;                                 ///< Polymorphic type specializations (type assertions), negative cost
    34                                 unsigned char varCost;                                  ///< Count of polymorphic type variables
    35                                 unsigned char signCost;                                 ///< Count of safe sign conversions
    36                                 unsigned char safeCost;                                 ///< Safe (widening) conversions
    37                                 unsigned char polyCost;                                 ///< Count of parameters and return values bound to some poly type
    38                                 unsigned char unsafeCost;                               ///< Unsafe (narrowing) conversions
    39                         #else
    40                                 #error Cost BIG_ENDIAN unsupported
    41                         #endif
    42                         } v;
    43                         uint64_t all;
    44                 };
    45                 static const unsigned char correctb = 0xff;             // byte correction for negative spec cost
    46                 static const uint64_t correctw = 0x00'00'00'00'00'ff'00'00; //' word correction for negative spec cost
    4725          public:
    48                 // Compiler adjusts constants for correct endian.
    49                 enum : uint64_t {
    50                         zero      = 0x00'00'00'00'00'ff'00'00,
    51                         infinity  = 0xff'ff'ff'ff'ff'00'ff'ff,
    52                         unsafe    = 0x01'00'00'00'00'ff'00'00,
    53                         poly      = 0x00'01'00'00'00'ff'00'00,
    54                         safe      = 0x00'00'01'00'00'ff'00'00,
    55                         sign      = 0x00'00'00'01'00'ff'00'00,
    56                         var       = 0x00'00'00'00'01'ff'00'00,
    57                         spec      = 0x00'00'00'00'00'fe'00'00,
    58                         reference = 0x00'00'00'00'00'ff'01'00,
    59                 }; //'
     26                Cost & incUnsafe( int inc = 1 );
     27                Cost & incPoly( int inc = 1 );
     28                Cost & incSafe( int inc = 1 );
     29                Cost & incReference( int inc = 1 );
    6030
    61                 Cost( uint64_t all ) { Cost::all = all; }
    62                 Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) {
    63                         // Assume little-endian => first value is low priority and last is high priority.
    64                         v = {
    65                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    66                                 (unsigned char)0,                                               // padding
    67                                 (unsigned char)referenceCost,                   // low priority
    68                                 (unsigned char)(specCost + correctb),   // correct for signedness
    69                                 (unsigned char)varCost,
    70                                 (unsigned char)signCost,
    71                                 (unsigned char)safeCost,
    72                                 (unsigned char)polyCost,
    73                                 (unsigned char)unsafeCost,                              // high priority
    74                         #else
    75                                 #error Cost BIG_ENDIAN unsupported
    76                         #endif
    77                         };
    78                 }
     31                int get_unsafeCost() const { return unsafeCost; }
     32                int get_polyCost() const { return polyCost; }
     33                int get_safeCost() const { return safeCost; }
     34                int get_referenceCost() const { return referenceCost; }
    7935
    80                 int get_unsafeCost() const { return v.unsafeCost; }
    81                 int get_polyCost() const { return v.polyCost; }
    82                 int get_safeCost() const { return v.safeCost; }
    83                 int get_signCost() const { return v.signCost; }
    84                 int get_varCost() const { return v.varCost; }
    85                 int get_specCost() const { return -(correctb - v.specCost); }
    86                 int get_referenceCost() const { return v.referenceCost; }
     36                Cost operator+( const Cost &other ) const;
     37                Cost operator-( const Cost &other ) const;
     38                Cost &operator+=( const Cost &other );
     39                bool operator<( const Cost &other ) const;
     40                bool operator==( const Cost &other ) const;
     41                bool operator!=( const Cost &other ) const;
     42                friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
    8743
    88                 friend bool operator==( const Cost, const Cost );
    89                 friend bool operator!=( const Cost lhs, const Cost rhs );
    90                 // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs
    91                 int compare( const Cost rhs ) const {
    92                         if ( all == infinity ) return 1;
    93                         if ( rhs.all == infinity ) return -1;
    94                         return all > rhs.all ? 1 : all == rhs.all ? 0 : -1;
    95                 }
    96                 friend bool operator<( const Cost lhs, const Cost rhs );
     44                static const Cost zero;
     45                static const Cost infinity;
    9746
    98                 friend Cost operator+( const Cost lhs, const Cost rhs );
    99  
    100                 Cost operator+=( const Cost rhs ) {
    101                         if ( all == infinity ) return *this;
    102                         if ( rhs.all == infinity ) {
    103                                 all = infinity;
    104                                 return *this;
    105                         }
    106                         all += rhs.all - correctw;                                      // correct for negative spec cost
     47                static const Cost unsafe;
     48                static const Cost poly;
     49                static const Cost safe;
     50                static const Cost reference;
     51          private:
     52                int compare( const Cost &other ) const;
     53
     54                int unsafeCost;
     55                int polyCost;
     56                int safeCost;
     57                int referenceCost;
     58        };
     59
     60        inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {}
     61
     62        inline Cost & Cost::incUnsafe( int inc ) {
     63                if ( *this == infinity ) return *this;
     64                unsafeCost += inc;
     65                return *this;
     66        }
     67
     68        inline Cost & Cost::incPoly( int inc ) {
     69                if ( *this == infinity ) return *this;
     70                polyCost += inc;
     71                return *this;
     72        }
     73
     74        inline Cost & Cost::incSafe( int inc ) {
     75                if ( *this == infinity ) return *this;
     76                safeCost += inc;
     77                return *this;
     78        }
     79
     80        inline Cost & Cost::incReference( int inc ) {
     81                if ( *this == infinity ) return *this;
     82                referenceCost += inc;
     83                return *this;
     84        }
     85
     86        inline Cost Cost::operator+( const Cost &other ) const {
     87                if ( *this == infinity || other == infinity ) return infinity;
     88                return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost );
     89        }
     90
     91        inline Cost Cost::operator-( const Cost &other ) const {
     92                if ( *this == infinity || other == infinity ) return infinity;
     93                return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost );
     94        }
     95
     96        inline Cost &Cost::operator+=( const Cost &other ) {
     97                if ( *this == infinity ) return *this;
     98                if ( other == infinity ) {
     99                        *this = infinity;
    107100                        return *this;
    108101                }
    109 
    110                 Cost incUnsafe( int inc = 1 ) {
    111                         if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; }
    112                         return *this;
    113                 }
    114 
    115                 Cost incPoly( int inc = 1 ) {
    116                         if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; }
    117                         return *this;
    118                 }
    119 
    120                 Cost incSafe( int inc = 1 ) {
    121                         if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; }
    122                         return *this;
    123                 }
    124 
    125                 Cost incSign( int inc = 1 ) {
    126                         if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; }
    127                         return *this;
    128                 }
    129 
    130                 Cost incVar( int inc = 1 ) {
    131                         if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; }
    132                         return *this;
    133                 }
    134 
    135                 Cost decSpec( int dec = 1 ) {
    136                         if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; }
    137                         return *this;
    138                 }
    139 
    140                 Cost incReference( int inc = 1 ) {
    141                         if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; }
    142                         return *this;
    143                 }
    144 
    145                 friend std::ostream & operator<<( std::ostream & os, const Cost cost );
    146         };
    147 
    148         inline bool operator==( const Cost lhs, const Cost rhs ) {
    149                 return lhs.all == rhs.all;
     102                unsafeCost += other.unsafeCost;
     103                polyCost += other.polyCost;
     104                safeCost += other.safeCost;
     105                referenceCost += other.referenceCost;
     106                return *this;
    150107        }
    151108
    152         inline bool operator!=( const Cost lhs, const Cost rhs ) {
    153                 return !( lhs.all == rhs.all );
     109        inline bool Cost::operator<( const Cost &other ) const {
     110                if ( *this == infinity ) return false;
     111                if ( other == infinity ) return true;
     112
     113                if ( unsafeCost > other.unsafeCost ) {
     114                        return false;
     115                } else if ( unsafeCost < other.unsafeCost ) {
     116                        return true;
     117                } else if ( polyCost > other.polyCost ) {
     118                        return false;
     119                } else if ( polyCost < other.polyCost ) {
     120                        return true;
     121                } else if ( safeCost > other.safeCost ) {
     122                        return false;
     123                } else if ( safeCost < other.safeCost ) {
     124                        return true;
     125                } else if ( referenceCost > other.referenceCost ) {
     126                        return false;
     127                } else if ( referenceCost < other.referenceCost ) {
     128                        return true;
     129                } else {
     130                        return false;
     131                } // if
    154132        }
    155133
    156         inline bool operator<( const Cost lhs, const Cost rhs ) {
    157                 if ( lhs.all == Cost::infinity ) return false;
    158                 if ( rhs.all == Cost::infinity ) return true;
    159                 return lhs.all < rhs.all;
     134        inline bool Cost::operator==( const Cost &other ) const {
     135                return unsafeCost == other.unsafeCost
     136                        && polyCost == other.polyCost
     137                        && safeCost == other.safeCost
     138                        && referenceCost == other.referenceCost;
    160139        }
    161140
    162         inline Cost operator+( const Cost lhs, const Cost rhs ) {
    163                 if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity };
    164                 return Cost{ lhs.all + rhs.all - Cost::correctw }; // correct for negative spec cost
     141        inline bool Cost::operator!=( const Cost &other ) const {
     142                return !( *this == other );
    165143        }
    166144
    167         inline std::ostream & operator<<( std::ostream & os, const Cost cost ) {
    168                 return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost()
    169                                   << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost()
    170                                   << ", " << cost.get_referenceCost() << " )";
     145        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
     146                os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
     147                return os;
    171148        }
    172149} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    rb067d9b r7951100  
    1616#include <stddef.h>                    // for size_t
    1717#include <cassert>                     // for assertf, assert, safe_dynamic_...
    18 #include <deque>
    1918#include <iostream>                    // for ostream, operator<<, basic_ost...
    2019#include <stack>                       // for stack
    2120#include <string>                      // for string, operator<<, allocator
    2221
    23 #include "AST/Expr.hpp"                // for InitAlternative
    24 #include "AST/GenericSubstitution.hpp" // for genericSubstitution
    25 #include "AST/Init.hpp"                // for Designation
    26 #include "AST/Node.hpp"                // for readonly
    27 #include "AST/Type.hpp"
    2822#include "Common/Indenter.h"           // for Indenter, operator<<
    2923#include "Common/SemanticError.h"      // for SemanticError
     
    145139                ArrayIterator( ArrayType * at ) : array( at ) {
    146140                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    147                         base = at->base;
     141                        base = at->get_base();
    148142                        memberIter = createMemberIterator( base );
    149                         if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
    150                         setSize( at->dimension );
     143                        if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=" );
     144                        setSize( at->get_dimension() );
    151145                }
    152146
     
    156150
    157151        private:
    158                 void setSize( Expression * expr ) { // replace this logic with an eval call
    159                         auto res = eval(expr);
    160                         if (res.second) {
    161                                 size = res.first;
     152                void setSize( Expression * expr ) {
     153                        if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
     154                                try {
     155                                        size = constExpr->intValue();
     156                                        PRINT( std::cerr << "array type with size: " << size << std::endl; )
     157                                } catch ( SemanticErrorException & ) {
     158                                        SemanticError( expr, "Constant expression of non-integral type in array dimension: " );
     159                                }
     160                        }       else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     161                                setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast
     162                        } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
     163                                if ( EnumInstType * inst = dynamic_cast< EnumInstType * > ( varExpr->result ) ) {
     164                                        long long int value;
     165                                        if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
     166                                                size = value;
     167                                        }
     168                                }
    162169                        } else {
    163                                 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
     170                                assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this
    164171                        }
    165172                }
     
    585592} // namespace ResolvExpr
    586593
    587 namespace ast {
    588         /// create a new MemberIterator that traverses a type correctly
    589         MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
    590 
    591         /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
    592         class SimpleIterator final : public MemberIterator {
    593                 CodeLocation location;
    594                 readonly< Type > type = nullptr;
    595         public:
    596                 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
    597 
    598                 void setPosition(
    599                         std::deque< ptr< Expr > >::const_iterator begin,
    600                         std::deque< ptr< Expr > >::const_iterator end
    601                 ) override {
    602                         if ( begin != end ) {
    603                                 SemanticError( location, "Un-designated initializer given non-empty designator" );
    604                         }
    605                 }
    606 
    607                 std::deque< InitAlternative > operator* () const override { return first(); }
    608 
    609                 operator bool() const override { return type; }
    610 
    611                 SimpleIterator & bigStep() override { return smallStep(); }
    612                 SimpleIterator & smallStep() override {
    613                         type = nullptr;  // empty on increment because no members
    614                         return *this;
    615                 }
    616 
    617                 const Type * getType() override { return type; }
    618 
    619                 const Type * getNext() override { return type; }
    620 
    621                 std::deque< InitAlternative > first() const override {
    622                         if ( type ) return { InitAlternative{ type, new Designation{ location } } };
    623                         return {};
    624                 }
    625         };
    626 
    627         /// Iterates array types
    628         class ArrayIterator final : public MemberIterator {
    629                 CodeLocation location;
    630                 readonly< ArrayType > array = nullptr;
    631                 readonly< Type > base = nullptr;
    632                 size_t index = 0;
    633                 size_t size = 0;
    634                 std::unique_ptr< MemberIterator > memberIter;
    635 
    636                 void setSize( const Expr * expr ) {
    637                         auto res = eval(expr);
    638                         if ( ! res.second ) {
    639                                 SemanticError( location,
    640                                         toString("Array designator must be a constant expression: ", expr ) );
    641                         }
    642                         size = res.first;
    643                 }
    644 
    645         public:
    646                 ArrayIterator( const CodeLocation & loc, const ArrayType * at )
    647                 : location( loc ), array( at ), base( at->base ) {
    648                         PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    649                         memberIter.reset( createMemberIterator( loc, base ) );
    650                         if ( at->isVarLen ) {
    651                                 SemanticError( location, at, "VLA initialization does not support @=: " );
    652                         }
    653                         setSize( at->dimension );
    654                 }
    655 
    656                 void setPosition( const Expr * expr ) {
    657                         // need to permit integer-constant-expressions, including: integer constants,
    658                         // enumeration constants, character constants, sizeof expressions, alignof expressions,
    659                         // cast expressions
    660                         if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
    661                                 try {
    662                                         index = constExpr->intValue();
    663                                 } catch ( SemanticErrorException & ) {
    664                                         SemanticError( expr,
    665                                                 "Constant expression of non-integral type in array designator: " );
    666                                 }
    667                         } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    668                                 setPosition( castExpr->arg );
    669                         } else if (
    670                                 dynamic_cast< const SizeofExpr * >( expr )
    671                                 || dynamic_cast< const AlignofExpr * >( expr )
    672                         ) {
    673                                 index = 0;
    674                         } else {
    675                                 assertf( false,
    676                                         "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    677                         }
    678                 }
    679 
    680                 void setPosition(
    681                         std::deque< ptr< Expr > >::const_iterator begin,
    682                         std::deque< ptr< Expr > >::const_iterator end
    683                 ) override {
    684                         if ( begin == end ) return;
    685 
    686                         setPosition( *begin );
    687                         memberIter->setPosition( ++begin, end );
    688                 }
    689 
    690                 std::deque< InitAlternative > operator* () const override { return first(); }
    691 
    692                 operator bool() const override { return index < size; }
    693 
    694                 ArrayIterator & bigStep() override {
    695                         PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    696                         ++index;
    697                         memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
    698                         return *this;
    699                 }
    700 
    701                 ArrayIterator & smallStep() override {
    702                         PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    703                         if ( memberIter ) {
    704                                 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
    705                                 memberIter->smallStep();
    706                                 if ( *memberIter ) {
    707                                         PRINT( std::cerr << "has valid member iter" << std::endl; )
    708                                         return *this;
    709                                 }
    710                         }
    711                         return bigStep();
    712                 }
    713 
    714                 const Type * getType() override { return array; }
    715 
    716                 const Type * getNext() override { return base; }
    717 
    718                 std::deque< InitAlternative > first() const override {
    719                         PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    720                         if ( memberIter && *memberIter ) {
    721                                 std::deque< InitAlternative > ret = memberIter->first();
    722                                 for ( InitAlternative & alt : ret ) {
    723                                         alt.designation.get_and_mutate()->designators.emplace_front(
    724                                                 ConstantExpr::from_ulong( location, index ) );
    725                                 }
    726                                 return ret;
    727                         }
    728                         return {};
    729                 }
    730         };
    731 
    732         class AggregateIterator : public MemberIterator {
    733         protected:
    734                 using MemberList = std::vector< ptr< Decl > >;
    735 
    736                 CodeLocation location;
    737                 std::string kind;  // for debug
    738                 std::string name;
    739                 const Type * inst;
    740                 const MemberList & members;
    741                 MemberList::const_iterator curMember;
    742                 bool atbegin = true;  // false at first {small,big}Step
    743                 const Type * curType = nullptr;
    744                 std::unique_ptr< MemberIterator > memberIter = nullptr;
    745                 TypeSubstitution sub;
    746 
    747                 bool init() {
    748                         PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
    749                         if ( curMember != members.end() ) {
    750                                 if ( auto field = curMember->as< ObjectDecl >() ) {
    751                                         PRINT( std::cerr << "incremented to field: " << field << std::endl; )
    752                                         curType = field->get_type();
    753                                         memberIter.reset( createMemberIterator( location, curType ) );
    754                                         return true;
    755                                 }
    756                         }
    757                         return false;
    758                 }
    759 
    760                 AggregateIterator(
    761                         const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
    762                         const MemberList & ms )
    763                 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
    764                   sub( genericSubstitution( i ) ) {
    765                         PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
    766                         init();
    767                 }
    768 
    769         public:
    770                 void setPosition(
    771                         std::deque< ptr< Expr > >::const_iterator begin,
    772                         std::deque< ptr< Expr > >::const_iterator end
    773                 ) final {
    774                         if ( begin == end ) return;
    775 
    776                         if ( auto varExpr = begin->as< VariableExpr >() ) {
    777                                 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
    778                                         if ( *curMember != varExpr->var ) continue;
    779 
    780                                         ++begin;
    781 
    782                                         memberIter.reset( createMemberIterator( location, varExpr->result ) );
    783                                         curType = varExpr->result;
    784                                         atbegin = curMember == members.begin() && begin == end;
    785                                         memberIter->setPosition( begin, end );
    786                                         return;
    787                                 }
    788                                 assertf( false,
    789                                         "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    790                         } else {
    791                                 assertf( false,
    792                                         "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
    793                         }
    794                 }
    795 
    796                 std::deque< InitAlternative > operator* () const final {
    797                         if ( memberIter && *memberIter ) {
    798                                 std::deque< InitAlternative > ret = memberIter->first();
    799                                 PRINT( std::cerr << "sub: " << sub << std::endl; )
    800                                 for ( InitAlternative & alt : ret ) {
    801                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    802                                         alt.designation.get_and_mutate()->designators.emplace_front(
    803                                                 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    804                                         // need to substitute for generic types so that casts are to concrete types
    805                                         PRINT( std::cerr << "  type is: " << alt.type; )
    806                                         sub.apply( alt.type ); // also apply to designation??
    807                                         PRINT( std::cerr << " ==> " << alt.type << std::endl; )
    808                                 }
    809                                 return ret;
    810                         }
    811                         return {};
    812                 }
    813 
    814                 AggregateIterator & smallStep() final {
    815                         PRINT( std::cerr << "smallStep in " << kind << std::endl; )
    816                         atbegin = false;
    817                         if ( memberIter ) {
    818                                 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
    819                                 memberIter->smallStep();
    820                                 if ( *memberIter ) {
    821                                         PRINT( std::cerr << "success!" << std::endl; )
    822                                         return *this;
    823                                 }
    824                         }
    825                         return bigStep();
    826                 }
    827 
    828                 AggregateIterator & bigStep() override = 0;
    829 
    830                 const Type * getType() final { return inst; }
    831 
    832                 const Type * getNext() final {
    833                         return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr;
    834                 }
    835 
    836                 std::deque< InitAlternative > first() const final {
    837                         std::deque< InitAlternative > ret;
    838                         PRINT( std::cerr << "first " << kind << std::endl; )
    839                         if ( memberIter && *memberIter ) {
    840                                 PRINT( std::cerr << "adding children" << std::endl; )
    841                                 ret = memberIter->first();
    842                                 for ( InitAlternative & alt : ret ) {
    843                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    844                                         alt.designation.get_and_mutate()->designators.emplace_front(
    845                                                 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    846                                 }
    847                         }
    848                         if ( atbegin ) {
    849                                 // only add self if at the very beginning of the structure
    850                                 PRINT( std::cerr << "adding self" << std::endl; )
    851                                 ret.emplace_front( inst, new Designation{ location } );
    852                         }
    853                         return ret;
    854                 }
    855         };
    856 
    857         class StructIterator final : public AggregateIterator {
    858         public:
    859                 StructIterator( const CodeLocation & loc, const StructInstType * inst )
    860                 : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
    861 
    862                 operator bool() const override {
    863                         return curMember != members.end() || (memberIter && *memberIter);
    864                 }
    865 
    866                 StructIterator & bigStep() override {
    867                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    868                         atbegin = false;
    869                         memberIter = nullptr;
    870                         curType = nullptr;
    871                         while ( curMember != members.end() ) {
    872                                 ++curMember;
    873                                 if ( init() ) return *this;
    874                         }
    875                         return *this;
    876                 }
    877         };
    878 
    879         class UnionIterator final : public AggregateIterator {
    880         public:
    881                 UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
    882                 : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
    883 
    884                 operator bool() const override { return memberIter && *memberIter; }
    885 
    886                 UnionIterator & bigStep() override {
    887                         // unions only initialize one member
    888                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    889                         atbegin = false;
    890                         memberIter = nullptr;
    891                         curType = nullptr;
    892                         curMember = members.end();
    893                         return *this;
    894                 }
    895         };
    896 
    897         class TupleIterator final : public AggregateIterator {
    898         public:
    899                 TupleIterator( const CodeLocation & loc, const TupleType * inst )
    900                 : AggregateIterator(
    901                         loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
    902                 ) {}
    903 
    904                 operator bool() const override {
    905                         return curMember != members.end() || (memberIter && *memberIter);
    906                 }
    907 
    908                 TupleIterator & bigStep() override {
    909                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    910                         atbegin = false;
    911                         memberIter = nullptr;
    912                         curType = nullptr;
    913                         while ( curMember != members.end() ) {
    914                                 ++curMember;
    915                                 if ( init() ) return *this;
    916                         }
    917                         return *this;
    918                 }
    919         };
    920 
    921         MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
    922                 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
    923                         if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
    924                                 return new StructIterator{ loc, sit };
    925                         } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
    926                                 return new UnionIterator{ loc, uit };
    927                         } else {
    928                                 assertf(
    929                                         dynamic_cast< const EnumInstType * >( aggr )
    930                                                 || dynamic_cast< const TypeInstType * >( aggr ),
    931                                         "Encountered unhandled ReferenceToType in createMemberIterator: %s",
    932                                                 toString( type ).c_str() );
    933                                 return new SimpleIterator{ loc, type };
    934                         }
    935                 } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
    936                         return new ArrayIterator{ loc, at };
    937                 } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
    938                         return new TupleIterator{ loc, tt };
    939                 } else {
    940                         return new SimpleIterator{ loc, type };
    941                 }
    942         }
    943 
    944         CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
    945                 objStack.emplace_back( new SimpleIterator{ loc, type } );
    946         }
    947 
    948         const Designation * CurrentObject::findNext( const Designation * designation ) {
    949                 using DesignatorChain = std::deque< ptr< Expr > >;
    950                 PRINT( std::cerr << "___findNext" << std::endl; )
    951                
    952                 // find all the d's
    953                 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
    954                 std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;
    955                 for ( const Expr * expr : designation->designators ) {
    956                         PRINT( std::cerr << "____untyped: " << expr << std::endl; )
    957                         auto dit = desigAlts.begin();
    958                         if ( auto nexpr = dynamic_cast< const NameExpr * >( expr ) ) {
    959                                 for ( const Type * t : curTypes ) {
    960                                         assert( dit != desigAlts.end() );
    961 
    962                                         DesignatorChain & d = *dit;
    963                                         PRINT( std::cerr << "____actual: " << t << std::endl; )
    964                                         if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {
    965                                                 // concatenate identical field names
    966                                                 for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
    967                                                         if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
    968                                                                 PRINT( std::cerr << "____alt: " << field->type << std::endl; )
    969                                                                 DesignatorChain d2 = d;
    970                                                                 d2.emplace_back( new VariableExpr{ expr->location, field } );
    971                                                                 newDesigAlts.emplace_back( std::move( d2 ) );
    972                                                                 newTypes.emplace_back( field->type );
    973                                                         }
    974                                                 }
    975                                         }
    976 
    977                                         ++dit;
    978                                 }
    979                         } else {
    980                                 for ( const Type * t : curTypes ) {
    981                                         assert( dit != desigAlts.end() );
    982 
    983                                         DesignatorChain & d = *dit;
    984                                         if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
    985                                                 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
    986                                                 d.emplace_back( expr );
    987                                                 newDesigAlts.emplace_back( d );
    988                                                 newTypes.emplace_back( at->base );
    989                                         }
    990                                 }
    991                         }
    992 
    993                         // reset queue
    994                         desigAlts = std::move( newDesigAlts );
    995                         newDesigAlts.clear();
    996                         curTypes = std::move( newTypes );
    997                         newTypes.clear();
    998                         assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
    999                 }
    1000 
    1001                 if ( desigAlts.size() > 1 ) {
    1002                         SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
    1003                 } else if ( desigAlts.empty() ) {
    1004                         SemanticError( designation, "No reasonable alternatives for designation: " );
    1005                 }
    1006 
    1007                 DesignatorChain & d = desigAlts.back();
    1008                 PRINT( for ( Expression * expr : d ) {
    1009                         std::cerr << "____desig: " << expr << std::endl;
    1010                 } ) // for
    1011                 assertf( ! curTypes.empty(), "empty designator chosen");
    1012 
    1013                 // set new designators
    1014                 assertf( ! objStack.empty(), "empty object stack when setting designation" );
    1015                 Designation * actualDesignation =
    1016                         new Designation{ designation->location, DesignatorChain{d} };
    1017                 objStack.back()->setPosition( d ); // destroys d
    1018                 return actualDesignation;
    1019         }
    1020 
    1021         void CurrentObject::setNext( const Designation * designation ) {
    1022                 PRINT( std::cerr << "____setNext" << designation << std::endl; )
    1023                 assertf( ! objStack.empty(), "obj stack empty in setNext" );
    1024                 objStack.back()->setPosition( designation->designators );
    1025         }
    1026 
    1027         void CurrentObject::increment() {
    1028                 PRINT( std::cerr << "____increment" << std::endl; )
    1029                 if ( objStack.empty() ) return;
    1030                 PRINT( std::cerr << *objStack.back() << std::endl; )
    1031                 objStack.back()->smallStep();
    1032         }
    1033 
    1034         void CurrentObject::enterListInit( const CodeLocation & loc ) {
    1035                 PRINT( std::cerr << "____entering list init" << std::endl; )
    1036                 assertf( ! objStack.empty(), "empty obj stack entering list init" );
    1037                 const ast::Type * type = objStack.back()->getNext();
    1038                 assert( type );
    1039                 objStack.emplace_back( createMemberIterator( loc, type ) );
    1040         }
    1041 
    1042         void CurrentObject::exitListInit() {
    1043                 PRINT( std::cerr << "____exiting list init" << std::endl; )
    1044                 assertf( ! objStack.empty(), "objstack empty" );
    1045                 objStack.pop_back();
    1046                 if ( ! objStack.empty() ) {
    1047                         PRINT( std::cerr << *objStack.back() << std::endl; )
    1048                         objStack.back()->bigStep();
    1049                 }
    1050         }
    1051 
    1052         std::deque< InitAlternative > CurrentObject::getOptions() {
    1053                 PRINT( std::cerr << "____getting current options" << std::endl; )
    1054                 assertf( ! objStack.empty(), "objstack empty in getOptions" );
    1055                 return **objStack.back();
    1056         }
    1057 
    1058         const Type * CurrentObject::getCurrentType() {
    1059                 PRINT( std::cerr << "____getting current type" << std::endl; )
    1060                 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
    1061                 return objStack.back()->getNext();
    1062         }
    1063 }
    1064 
    1065594// Local Variables: //
    1066595// tab-width: 4 //
  • src/ResolvExpr/CurrentObject.h

    rb067d9b r7951100  
    1616#pragma once
    1717
    18 #include <deque>
    1918#include <list>   // for list
    20 #include <memory> // for unique_ptr
    2119#include <stack>  // for stack
    22 #include <vector>
    23 
    24 #include "AST/Node.hpp"  // for ptr
    25 #include "Common/CodeLocation.h"
    2620
    2721class Designation;
     
    5852} // namespace ResolvExpr
    5953
    60 namespace ast {
    61         // AST class types
    62         class Designation;
    63         struct InitAlternative;
    64         class Type;
    65 
    66         /// Iterates members of a type by initializer
    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         };
    104 
    105         /// Builds initializer lists in resolution
    106         class CurrentObject final {
    107                 std::vector< std::shared_ptr<MemberIterator> > objStack;
    108        
    109         public:
    110                 CurrentObject() = default;
    111                 CurrentObject( const CodeLocation & loc, const Type * type );
    112 
    113                 /// resolves unresolved designation
    114                 const Designation * findNext( const Designation * designation );
    115                 /// sets current position using the resolved designation
    116                 void setNext( const ast::Designation * designation );
    117                 /// steps to next sub-object of current object
    118                 void increment();
    119                 /// sets new current object for the duration of this brace-enclosed intializer-list
    120                 void enterListInit( const CodeLocation & loc );
    121                 /// restores previous current object
    122                 void exitListInit();
    123                 /// produces a list of alternatives (Type *, Designation *) for the current sub-object's
    124                 /// initializer.
    125                 std::deque< InitAlternative > getOptions();
    126                 /// produces the type of the current object but no subobjects
    127                 const Type * getCurrentType();
    128         };
    129 } // namespace ast
    130 
    13154// Local Variables: //
    13255// tab-width: 4 //
  • src/ResolvExpr/ExplodedActual.cc

    rb067d9b r7951100  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ExplodedActual.cc --
     7// Alternative.h --
    88//
    99// Author           : Aaron B. Moss
     
    2424        }
    2525}
    26 
    27 // Local Variables: //
    28 // tab-width: 4 //
    29 // mode: c++ //
    30 // compile-command: "make install" //
    31 // End: //
  • src/ResolvExpr/ExplodedActual.h

    rb067d9b r7951100  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ExplodedActual.h --
     7// Alternative.h --
    88//
    99// Author           : Aaron B. Moss
     
    3232
    3333                ExplodedActual() : env(), cost(Cost::zero), exprs() {}
     34
    3435                ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );
    35                 ExplodedActual(ExplodedActual&&) = default;
    36                 ExplodedActual& operator= (ExplodedActual&&) = default;
    3736        };
    3837}
    39 
    40 // Local Variables: //
    41 // tab-width: 4 //
    42 // mode: c++ //
    43 // compile-command: "make install" //
    44 // End: //
  • src/ResolvExpr/FindOpenVars.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:42:48 2015
    11 // Last Modified By : Andrew
    12 // Last Modified On : Fri Jul 12 14:18:00 2019
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun May 17 09:45:25 2015
     13// Update Count     : 3
    1414//
    1515
     
    1919#include <map>                    // for map<>::mapped_type
    2020
    21 #include "AST/Pass.hpp"
    22 #include "AST/Type.hpp"
    2321#include "Common/PassVisitor.h"
    2422#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
     
    2624
    2725namespace ResolvExpr {
    28         struct FindOpenVars_old : public WithGuards {
    29                 FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
     26        struct FindOpenVars : public WithGuards {
     27                FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    3028
    31                 void previsit( const PointerType * pointerType );
    32                 void previsit( const ArrayType * arrayType );
    33                 void previsit( const FunctionType * functionType );
    34                 void previsit( const TupleType * tupleType );
     29                void previsit( PointerType * pointerType );
     30                void previsit( ArrayType * arrayType );
     31                void previsit( FunctionType * functionType );
     32                void previsit( TupleType * tupleType );
    3533
    36                 void common_action( const Type *type );
     34                void common_action( Type *type );
    3735
    3836                OpenVarSet &openVars, &closedVars;
     
    4139        };
    4240
    43         void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    44                 PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
     41        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
     42                PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
    4543                type->accept( finder );
    4644        }
    4745
    48         FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
     46        FindOpenVars::FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
    4947                : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) {
    5048        }
    5149
    52         void FindOpenVars_old::common_action( const Type * type ) {
     50        void FindOpenVars::common_action( Type *type ) {
    5351                if ( nextIsOpen ) {
    54                         for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
     52                        for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
    5553                                openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    5654                                for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
     
    6159                        }
    6260                } else {
    63                         for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
     61                        for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
    6462                                closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    6563                                for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
     
    7876        }
    7977
    80         void FindOpenVars_old::previsit(const PointerType * pointerType) {
     78        void FindOpenVars::previsit(PointerType *pointerType) {
    8179                common_action( pointerType );
    8280        }
    8381
    84         void FindOpenVars_old::previsit(const ArrayType * arrayType) {
     82        void FindOpenVars::previsit(ArrayType *arrayType) {
    8583                common_action( arrayType );
    8684        }
    8785
    88         void FindOpenVars_old::previsit(const FunctionType * functionType) {
     86        void FindOpenVars::previsit(FunctionType *functionType) {
    8987                common_action( functionType );
    9088                nextIsOpen = ! nextIsOpen;
     
    9290        }
    9391
    94         void FindOpenVars_old::previsit(const TupleType * tupleType) {
     92        void FindOpenVars::previsit(TupleType *tupleType) {
    9593                common_action( tupleType );
    96         }
    97 
    98         namespace {
    99                 struct FindOpenVars_new final : public ast::WithGuards {
    100                         ast::OpenVarSet & open;
    101                         ast::OpenVarSet & closed;
    102                         ast::AssertionSet & need;
    103                         ast::AssertionSet & have;
    104                         bool nextIsOpen;
    105 
    106                         FindOpenVars_new(
    107                                 ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n,
    108                                 ast::AssertionSet & h, FirstMode firstIsOpen )
    109                         : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {}
    110 
    111                         void previsit( const ast::FunctionType * type ) {
    112                                 // mark open/closed variables
    113                                 if ( nextIsOpen ) {
    114                                         for ( const ast::TypeDecl * decl : type->forall ) {
    115                                                 open[ decl->name ] = ast::TypeDecl::Data{ decl };
    116                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    117                                                         need[ assert ].isUsed = false;
    118                                                 }
    119                                         }
    120                                 } else {
    121                                         for ( const ast::TypeDecl * decl : type->forall ) {
    122                                                 closed[ decl->name ] = ast::TypeDecl::Data{ decl };
    123                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    124                                                         have[ assert ].isUsed = false;
    125                                                 }
    126                                         }
    127                                 }
    128 
    129                                 // flip open variables for contained function types
    130                                 nextIsOpen = ! nextIsOpen;
    131                                 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
    132                         }
    133 
    134                 };
    135         }
    136 
    137         void findOpenVars(
    138                         const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
    139                         ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {
    140                 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };
    141                 type->accept( finder );
    14294        }
    14395} // namespace ResolvExpr
  • src/ResolvExpr/FindOpenVars.h

    rb067d9b r7951100  
    1616#pragma once
    1717
    18 #include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    1918#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2019
    2120class Type;
    22 namespace ast {
    23         class Type;
    24 }
    2521
    2622namespace ResolvExpr {
    2723        // Updates open and closed variables and their associated assertions
    28         void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    29 
    30         enum FirstMode { FirstClosed, FirstOpen };
    31 
    32         // Updates open and closed variables and their associated assertions
    33         void findOpenVars(
    34                 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,
    35                 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen );
     24        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    3625} // namespace ResolvExpr
    3726
  • src/ResolvExpr/Occurs.cc

    rb067d9b r7951100  
    2424        struct Occurs : public WithVisitorRef<Occurs> {
    2525                Occurs( std::string varName, const TypeEnvironment &env );
    26                 void previsit( const TypeInstType * typeInst );
     26                void previsit( TypeInstType * typeInst );
    2727
    2828                bool result;
     
    3131        };
    3232
    33         bool occurs( const Type *type, const std::string & varName, const TypeEnvironment &env ) {
     33        bool occurs( Type *type, std::string varName, const TypeEnvironment &env ) {
    3434                PassVisitor<Occurs> occur( varName, env );
    3535                type->accept( occur );
     
    4545        }
    4646
    47         void Occurs::previsit( const TypeInstType * typeInst ) {
     47        void Occurs::previsit( TypeInstType * typeInst ) {
    4848                ///   std::cerr << "searching for vars: ";
    4949///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) );
  • src/ResolvExpr/PolyCost.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:50:12 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 19 10:45:00 2019
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun May 17 09:52:02 2015
     13// Update Count     : 3
    1414//
    1515
    16 #include "AST/SymbolTable.hpp"
    17 #include "AST/Type.hpp"
    18 #include "AST/TypeEnvironment.hpp"
    1916#include "Common/PassVisitor.h"
    2017#include "SymTab/Indexer.h"   // for Indexer
     
    5754        }
    5855
    59 // TODO: When the old PolyCost is torn out get rid of the _new suffix.
    60 struct PolyCost_new {
    61         int result;
    62         const ast::SymbolTable &symtab;
    63         const ast::TypeEnvironment &env_;
    64 
    65         PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :
    66                 result( 0 ), symtab( symtab ), env_( env ) {}
    67 
    68         void previsit( const ast::TypeInstType * type ) {
    69                 if ( const ast::EqvClass * eqv = env_.lookup( type->name ) ) /* && */ if ( eqv->bound ) {
    70                         if ( const ast::TypeInstType * otherType = eqv->bound.as< ast::TypeInstType >() ) {
    71                                 if ( symtab.lookupType( otherType->name ) ) {
    72                                         // Bound to opaque type.
    73                                         result += 1;
    74                                 }
    75                         } else {
    76                                 // Bound to concrete type.
    77                                 result += 1;
    78                         }
    79                 }
    80         }
    81 };
    82 
    83 int polyCost(
    84         const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    85 ) {
    86         ast::Pass<PolyCost_new> costing( symtab, env );
    87         type->accept( costing );
    88         return costing.pass.result;
    89 }
    90 
    9156} // namespace ResolvExpr
    9257
  • src/ResolvExpr/PtrsAssignable.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 11:44:11 2015
    11 // Last Modified By : Andrew
    12 // Last Modified On : Mon Jun 24 15:29:00 2019
    13 // Update Count     : 9
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Mar  2 17:36:05 2016
     13// Update Count     : 8
    1414//
    1515
    16 #include "typeops.h"
    17 
    18 #include "AST/Pass.hpp"
    19 #include "AST/Type.hpp"
    20 #include "AST/TypeEnvironment.hpp"
    2116#include "Common/PassVisitor.h"
    2217#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    2722namespace ResolvExpr {
    2823        struct PtrsAssignable : public WithShortCircuiting {
    29                 PtrsAssignable( const Type * dest, const TypeEnvironment &env );
     24                PtrsAssignable( Type *dest, const TypeEnvironment &env );
    3025
    3126                int get_result() const { return result; }
    3227
    33                 void previsit( const Type * ) { visit_children = false; }
     28                void previsit( Type * ) { visit_children = false; }
    3429
    35                 void postvisit( const VoidType * voidType );
    36                 void postvisit( const BasicType * basicType );
    37                 void postvisit( const PointerType * pointerType );
    38                 void postvisit( const ArrayType * arrayType );
    39                 void postvisit( const FunctionType * functionType );
    40                 void postvisit( const StructInstType * inst );
    41                 void postvisit( const UnionInstType * inst );
    42                 void postvisit( const EnumInstType * inst );
    43                 void postvisit( const TraitInstType * inst );
    44                 void postvisit( const TypeInstType * inst );
    45                 void postvisit( const TupleType * tupleType );
    46                 void postvisit( const VarArgsType * varArgsType );
    47                 void postvisit( const ZeroType * zeroType );
    48                 void postvisit( const OneType * oneType );
     30                void postvisit( VoidType * voidType );
     31                void postvisit( BasicType * basicType );
     32                void postvisit( PointerType * pointerType );
     33                void postvisit( ArrayType * arrayType );
     34                void postvisit( FunctionType * functionType );
     35                void postvisit( StructInstType * inst );
     36                void postvisit( UnionInstType * inst );
     37                void postvisit( EnumInstType * inst );
     38                void postvisit( TraitInstType * inst );
     39                void postvisit( TypeInstType * inst );
     40                void postvisit( TupleType * tupleType );
     41                void postvisit( VarArgsType * varArgsType );
     42                void postvisit( ZeroType * zeroType );
     43                void postvisit( OneType * oneType );
    4944          private:
    50                 const Type * dest;
     45                Type *dest;
    5146                int result;
    5247                const TypeEnvironment &env;
    5348        };
    5449
    55         int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) {
     50        int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) {
    5651                // std::cerr << "assignable: " << src << " | " << dest << std::endl;
    57                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
    58                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     52                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
     53                        if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    5954                                return ptrsAssignable( src, eqvClass->type, env );
    6055                        } // if
    6156                } // if
    62                 if ( dynamic_cast< const VoidType* >( dest ) ) {
     57                if ( dynamic_cast< VoidType* >( dest ) ) {
    6358                        // void * = T * for any T is unsafe
    6459                        // xxx - this should be safe, but that currently breaks the build
     
    7166        }
    7267
    73         PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
     68        PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
    7469
    75         void PtrsAssignable::postvisit( const VoidType * ) {
     70        void PtrsAssignable::postvisit( VoidType * ) {
    7671                // T * = void * is disallowed - this is a change from C, where any
    7772                // void * can be assigned or passed to a non-void pointer without a cast.
    7873        }
    7974
    80         void PtrsAssignable::postvisit( const BasicType * ) {}
    81         void PtrsAssignable::postvisit( const PointerType * ) {}
    82         void PtrsAssignable::postvisit( const ArrayType * ) {}
    83         void PtrsAssignable::postvisit( const FunctionType * ) {}
     75        void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType ) {}
     76        void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType ) {}
     77        void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType ) {}
     78        void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType ) {}
    8479
    85         void PtrsAssignable::postvisit( const StructInstType * ) {}
    86         void PtrsAssignable::postvisit( const UnionInstType * ) {}
     80        void PtrsAssignable::postvisit(  __attribute__((unused)) StructInstType *inst ) {}
     81        void PtrsAssignable::postvisit(  __attribute__((unused)) UnionInstType *inst ) {}
    8782
    88         void PtrsAssignable::postvisit( const EnumInstType * ) {
    89                 if ( dynamic_cast< const BasicType* >( dest ) ) {
     83        void PtrsAssignable::postvisit( EnumInstType * ) {
     84                if ( dynamic_cast< BasicType* >( dest ) ) {
    9085                        // int * = E *, etc. is safe. This isn't technically correct, as each
    9186                        // enum has one basic type that it is compatible with, an that type can
     
    9792        }
    9893
    99         void PtrsAssignable::postvisit(  const TraitInstType * ) {}
    100         void PtrsAssignable::postvisit( const TypeInstType * inst ) {
    101                 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
     94        void PtrsAssignable::postvisit(  __attribute__((unused)) TraitInstType *inst ) {}
     95        void PtrsAssignable::postvisit( TypeInstType *inst ) {
     96                if ( const EqvClass *eqvClass = env.lookup( inst->get_name() ) ) {
    10297                        if ( eqvClass->type ) {
    10398                                // T * = S * for any S depends on the type bound to T
     
    107102        }
    108103
    109         void PtrsAssignable::postvisit( const TupleType * ) {}
    110         void PtrsAssignable::postvisit( const VarArgsType * ) {}
    111         void PtrsAssignable::postvisit( const ZeroType * ) {}
    112         void PtrsAssignable::postvisit( const OneType * ) {}
    113 
    114 // TODO: Get rid of the `_new` suffix when the old version is removed.
    115 struct PtrsAssignable_new : public ast::WithShortCircuiting {
    116         const ast::Type * dst;
    117         const ast::TypeEnvironment & typeEnv;
    118         int result;
    119 
    120         PtrsAssignable_new( const ast::Type * dst, const ast::TypeEnvironment & env ) :
    121                 dst( dst ), typeEnv( env ), result( 0 ) {}
    122 
    123         void previsit( Type * ) { visit_children = false; }
    124 
    125         void postvisit( const ast::EnumInstType * ) {
    126                 if ( dynamic_cast< const ast::BasicType * >( dst ) ) {
    127                         // int * = E *, etc. is safe. This isn't technically correct, as each
    128                         // enum has one basic type that it is compatible with, an that type can
    129                         // differ from enum to enum. Without replicating GCC's internal logic,
    130                         // there is no way to know which type this particular enum is compatible
    131                         // with, so punt on this for now.
    132                         result = 1;
    133                 }
    134         }
    135         void postvisit( const ast::TypeInstType * inst ) {
    136                 if ( const ast::EqvClass * eqv = typeEnv.lookup( inst->name ) ) {
    137                         if ( eqv->bound ) {
    138                                 // T * = S * for any S depends on the type bound to T
    139                                 result = ptrsAssignable( eqv->bound, dst, typeEnv );
    140                         }
    141                 }
    142         }
    143 };
    144 
    145 int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
    146                 const ast::TypeEnvironment & env ) {
    147         if ( const ast::TypeInstType * dstAsInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    148                 if ( const ast::EqvClass * eqv = env.lookup( dstAsInst->name ) ) {
    149                         return ptrsAssignable( src, eqv->bound, env );
    150                 }
    151         }
    152         if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
    153                 return -1;
    154         } else {
    155                 ast::Pass<PtrsAssignable_new> visitor( dst, env );
    156                 src->accept( visitor );
    157                 return visitor.pass.result;
    158         }
    159 
    160 // see ticket #136 (this should be able to replace the visitor).
    161 #if 0
    162         if ( const ast::TypeInstType * dstAsTypeInst =
    163                         dynamic_cast< const ast::TypeInstType* >( dst ) ) {
    164                 if ( const ast::EqvClass * eqv = env.lookup( dstAsTypeInst->get_name() ) ) {
    165                         return ptrsAssignable( src, eqv->type, env );
    166                 } // if
    167         } // if
    168         if ( dynamic_cast< VoidType* >( dst ) ) {
    169                 // void * = T * for any T is unsafe
    170                 // xxx - this should be safe, but that currently breaks the build
    171                 return -1;
    172         } else if ( dynamic_cast< EnumInstType * >( src ) ) {
    173                 if ( dynamic_cast< BasicType * >( dst ) ) {
    174                         // int * = E *, etc. is safe. This isn't technically correct, as each
    175                         // enum has one basic type that it is compatible with, an that type can
    176                         // differ from enum to enum. Without replicating GCC's internal logic,
    177                         // there is no way to know which type this particular enum is compatible
    178                         // with, so punt on this for now.
    179                         return 1;
    180                 }
    181         } else if ( const ast::TypeInstType * typeInstType =
    182                         dynamic_cast< const ast::TypeInstType * >( src ) ) {
    183                 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
    184                         if ( eqv->bound ) {
    185                                 // T * = S * for any S depends on the type bound to T
    186                                 return ptrsAssignable( eqv->bound, dst, env );
    187                         }
    188                 }
    189         }
    190         return 0;
    191 #endif
    192 }
     104        void PtrsAssignable::postvisit(  __attribute__((unused)) TupleType *tupleType ) {}
     105        void PtrsAssignable::postvisit(  __attribute__((unused)) VarArgsType *varArgsType ) {}
     106        void PtrsAssignable::postvisit(  __attribute__((unused)) ZeroType *zeroType ) {}
     107        void PtrsAssignable::postvisit(  __attribute__((unused)) OneType *oneType ) {}
    193108
    194109} // namespace ResolvExpr
  • src/ResolvExpr/PtrsCastable.cc

    rb067d9b r7951100  
    1414//
    1515
    16 #include "AST/Decl.hpp"
    17 #include "AST/Pass.hpp"
    18 #include "AST/Type.hpp"
    19 #include "AST/TypeEnvironment.hpp"
    2016#include "Common/PassVisitor.h"
    2117#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    2723
    2824namespace ResolvExpr {
    29         struct PtrsCastable_old : public WithShortCircuiting  {
     25        struct PtrsCastable : public WithShortCircuiting  {
    3026          public:
    31                 PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     27                PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    3228
    3329                int get_result() const { return result; }
    3430
    35                 void previsit( const Type * ) { visit_children = false; }
     31                void previsit( Type * ) { visit_children = false; }
    3632
    37                 void postvisit( const VoidType * voidType );
    38                 void postvisit( const BasicType * basicType );
    39                 void postvisit( const PointerType * pointerType );
    40                 void postvisit( const ArrayType * arrayType );
    41                 void postvisit( const FunctionType * functionType );
    42                 void postvisit( const StructInstType * inst );
    43                 void postvisit( const UnionInstType * inst );
    44                 void postvisit( const EnumInstType * inst );
    45                 void postvisit( const TraitInstType * inst );
    46                 void postvisit( const TypeInstType * inst );
    47                 void postvisit( const TupleType * tupleType );
    48                 void postvisit( const VarArgsType * varArgsType );
    49                 void postvisit( const ZeroType * zeroType );
    50                 void postvisit( const OneType * oneType );
     33                void postvisit( VoidType * voidType );
     34                void postvisit( BasicType * basicType );
     35                void postvisit( PointerType * pointerType );
     36                void postvisit( ArrayType * arrayType );
     37                void postvisit( FunctionType * functionType );
     38                void postvisit( StructInstType * inst );
     39                void postvisit( UnionInstType * inst );
     40                void postvisit( EnumInstType * inst );
     41                void postvisit( TraitInstType * inst );
     42                void postvisit( TypeInstType * inst );
     43                void postvisit( TupleType * tupleType );
     44                void postvisit( VarArgsType * varArgsType );
     45                void postvisit( ZeroType * zeroType );
     46                void postvisit( OneType * oneType );
    5147          private:
    52                 const Type * dest;
     48                Type *dest;
    5349                int result;
    5450                const TypeEnvironment &env;
     
    5753
    5854        namespace {
    59                 int objectCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    60                         if ( dynamic_cast< const FunctionType* >( src ) ) {
     55                int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     56                        if ( dynamic_cast< FunctionType* >( src ) ) {
    6157                                return -1;
    62                         } else if ( const TypeInstType * typeInst = dynamic_cast< const TypeInstType* >( src ) ) {
    63                                 if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->name ) ) {
    64                                         if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl* >( ntDecl ) ) {
    65                                                 if ( tyDecl->kind == TypeDecl::Ftype ) {
     58                        } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) {
     59                                if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
     60                                        if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
     61                                                if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
    6662                                                        return -1;
    6763                                                } // if
    6864                                        } //if
    69                                 } else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
     65                                } else if ( const EqvClass *eqvClass = env.lookup( typeInst->get_name() ) ) {
    7066                                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    7167                                                return -1;
     
    7571                        return 1;
    7672                }
    77                 int functionCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     73                int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    7874                        return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
    7975                }
    8076        }
    8177
    82         int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    83                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
    84                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     78        int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     79                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
     80                        if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    8581                                // xxx - should this be ptrsCastable?
    8682                                return ptrsAssignable( src, eqvClass->type, env );
    8783                        } // if
    8884                } // if
    89                 if ( dynamic_cast< const VoidType* >( dest ) ) {
     85                if ( dynamic_cast< VoidType* >( dest ) ) {
    9086                        return objectCast( src, env, indexer );
    9187                } else {
    92                         PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer );
     88                        PassVisitor<PtrsCastable> ptrs( dest, env, indexer );
    9389                        src->accept( ptrs );
    9490                        return ptrs.pass.get_result();
     
    9692        }
    9793
    98         PtrsCastable_old::PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
     94        PtrsCastable::PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
    9995                : dest( dest ), result( 0 ), env( env ), indexer( indexer )     {
    10096        }
    10197
    102         void PtrsCastable_old::postvisit( const VoidType * ) {
     98        void PtrsCastable::postvisit( VoidType * ) {
    10399                result = objectCast( dest, env, indexer );
    104100        }
    105101
    106         void PtrsCastable_old::postvisit( const BasicType * ) {
     102        void PtrsCastable::postvisit( BasicType * ) {
    107103                result = objectCast( dest, env, indexer );
    108104        }
    109105
    110         void PtrsCastable_old::postvisit( const PointerType * ) {
     106        void PtrsCastable::postvisit( PointerType * ) {
    111107                result = objectCast( dest, env, indexer );
    112108        }
    113109
    114         void PtrsCastable_old::postvisit( const ArrayType * ) {
     110        void PtrsCastable::postvisit( ArrayType * ) {
    115111                result = objectCast( dest, env, indexer );
    116112        }
    117113
    118         void PtrsCastable_old::postvisit( const FunctionType * ) {
     114        void PtrsCastable::postvisit( FunctionType * ) {
    119115                // result = -1;
    120116                result = functionCast( dest, env, indexer );
    121117        }
    122118
    123         void PtrsCastable_old::postvisit( const StructInstType * ) {
     119        void PtrsCastable::postvisit( StructInstType * ) {
    124120                result = objectCast( dest, env, indexer );
    125121        }
    126122
    127         void PtrsCastable_old::postvisit( const UnionInstType * ) {
     123        void PtrsCastable::postvisit( UnionInstType * ) {
    128124                result = objectCast( dest, env, indexer );
    129125        }
    130126
    131         void PtrsCastable_old::postvisit( const EnumInstType * ) {
    132                 if ( dynamic_cast< const EnumInstType * >( dest ) ) {
     127        void PtrsCastable::postvisit( EnumInstType * ) {
     128                if ( dynamic_cast< EnumInstType* >( dest ) ) {
    133129                        result = 1;
    134                 } else if ( const BasicType * bt = dynamic_cast< const BasicType * >( dest ) ) {
    135                         if ( bt->kind == BasicType::SignedInt ) {
     130                } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {
     131                        if ( bt->get_kind() == BasicType::SignedInt ) {
    136132                                result = 0;
    137133                        } else {
     
    143139        }
    144140
    145         void PtrsCastable_old::postvisit( const TraitInstType * ) {}
     141        void PtrsCastable::postvisit( TraitInstType * ) {}
    146142
    147         void PtrsCastable_old::postvisit( const TypeInstType *inst ) {
     143        void PtrsCastable::postvisit(TypeInstType *inst) {
    148144                //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
    149145                result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
    150146        }
    151147
    152         void PtrsCastable_old::postvisit( const TupleType * ) {
     148        void PtrsCastable::postvisit( TupleType * ) {
    153149                result = objectCast( dest, env, indexer );
    154150        }
    155151
    156         void PtrsCastable_old::postvisit( const VarArgsType * ) {
     152        void PtrsCastable::postvisit( VarArgsType * ) {
    157153                result = objectCast( dest, env, indexer );
    158154        }
    159155
    160         void PtrsCastable_old::postvisit( const ZeroType * ) {
     156        void PtrsCastable::postvisit( ZeroType * ) {
    161157                result = objectCast( dest, env, indexer );
    162158        }
    163159
    164         void PtrsCastable_old::postvisit( const OneType * ) {
     160        void PtrsCastable::postvisit( OneType * ) {
    165161                result = objectCast( dest, env, indexer );
    166162        }
    167 
    168 namespace {
    169         // can this type be cast to an object (1 for yes, -1 for no)
    170         int objectCast(
    171                 const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
    172         ) {
    173                 if ( dynamic_cast< const ast::FunctionType * >( src ) ) {
    174                         return -1;
    175                 } else if ( auto inst = dynamic_cast< const ast::TypeInstType * >( src ) ) {
    176                         if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
    177                                 if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( named ) ) {
    178                                         if ( tyDecl->kind == ast::TypeVar::Ftype ) {
    179                                                 return -1;
    180                                         }
    181                                 }
    182                         } else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
    183                                 if ( eqvClass->data.kind == ast::TypeVar::Ftype ) {
    184                                         return -1;
    185                                 }
    186                         }
    187                 }
    188 
    189                 return 1;
    190         }
    191 
    192         // can this type be cast to a function (inverse of objectCast)
    193         int functionCast(
    194                 const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
    195         ) {
    196                 return -1 * objectCast( src, env, symtab );
    197         }
    198 
    199         class PtrsCastable_new : public ast::WithShortCircuiting {
    200                 const ast::Type * dst;
    201                 const ast::TypeEnvironment & env;
    202                 const ast::SymbolTable & symtab;
    203         public:
    204                 int result;
    205 
    206                 PtrsCastable_new(
    207                         const ast::Type * d, const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
    208                 : dst( d ), env( e ), symtab( syms ), result( 0 ) {}
    209 
    210                 void previsit( const ast::Type * ) { visit_children = false; }
    211 
    212                 void postvisit( const ast::VoidType * ) {
    213                         result = objectCast( dst, env, symtab );
    214                 }
    215 
    216                 void postvisit( const ast::BasicType * ) {
    217                         result = objectCast( dst, env, symtab );
    218                 }
    219 
    220                 void postvisit( const ast::PointerType * ) {
    221                         result = objectCast( dst, env, symtab );
    222                 }
    223 
    224                 void postvisit( const ast::ArrayType * ) {
    225                         result = objectCast( dst, env, symtab );
    226                 }
    227 
    228                 void postvisit( const ast::FunctionType * ) {
    229                         result = functionCast( dst, env, symtab );
    230                 }
    231 
    232                 void postvisit( const ast::StructInstType * ) {
    233                         result = objectCast( dst, env, symtab );
    234                 }
    235 
    236                 void postvisit( const ast::UnionInstType * ) {
    237                         result = objectCast( dst, env, symtab );
    238                 }
    239 
    240                 void postvisit( const ast::EnumInstType * ) {
    241                         if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    242                                 result = 1;
    243                         } else if ( auto bt = dynamic_cast< const ast::BasicType * >( dst ) ) {
    244                                 if ( bt->kind == ast::BasicType::SignedInt ) {
    245                                         result = 0;
    246                                 } else {
    247                                         result = 1;
    248                                 }
    249                         } else {
    250                                 result = objectCast( dst, env, symtab );
    251                         }
    252                 }
    253 
    254                 void postvisit( const ast::TraitInstType * ) {}
    255 
    256                 void postvisit( const ast::TypeInstType * inst ) {
    257                         // check trait and destination type are both object or both function
    258                         result = objectCast( inst, env, symtab ) == objectCast( dst, env, symtab ) ? 1 : -1;
    259                 }
    260 
    261                 void postvisit( const ast::TupleType * ) {
    262                         result = objectCast( dst, env, symtab );
    263                 }
    264 
    265                 void postvisit( const ast::VarArgsType * ) {
    266                         result = objectCast( dst, env, symtab );
    267                 }
    268 
    269                 void postvisit( const ast::ZeroType * ) {
    270                         result = objectCast( dst, env, symtab );
    271                 }
    272 
    273                 void postvisit( const ast::OneType * ) {
    274                         result = objectCast( dst, env, symtab );
    275                 }
    276 
    277         };
    278 } // anonymous namespace
    279 
    280 int ptrsCastable(
    281         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    282         const ast::TypeEnvironment & env
    283 ) {
    284         if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    285                 if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
    286                         return ptrsAssignable( src, eqvClass->bound, env );
    287                 }
    288         }
    289 
    290         if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
    291                 return objectCast( src, env, symtab );
    292         } else {
    293                 ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
    294                 src->accept( ptrs );
    295                 return ptrs.pass.result;
    296         }
    297 }
    298 
    299163} // namespace ResolvExpr
    300164
  • src/ResolvExpr/RenameVars.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:05:18 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Jun 20 17:39:00 2019
    13 // Update Count     : 8
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Mar  2 17:36:32 2016
     13// Update Count     : 5
    1414//
    1515
     
    1919#include <utility>                 // for pair
    2020
    21 #include "AST/Pass.hpp"
    22 #include "AST/Type.hpp"
    2321#include "Common/PassVisitor.h"
    24 #include "Common/ScopedMap.h"
    2522#include "Common/SemanticError.h"  // for SemanticError
    2623#include "RenameVars.h"
     
    3128
    3229namespace ResolvExpr {
     30        namespace {
     31                struct RenameVars {
     32                        RenameVars();
     33                        void reset();
    3334
    34 namespace {
    35         class RenamingData {
    36                 int level = 0;
    37                 int resetCount = 0;
    38                 ScopedMap< std::string, std::string > nameMap;
     35                        void previsit( TypeInstType * instType );
     36                        void previsit( Type * );
     37                        void postvisit( Type * );
    3938
    40         public:
    41                 void reset() {
    42                         level = 0;
    43                         ++resetCount;
     39                  private:
     40                        int level, resetCount;
     41                        std::list< std::map< std::string, std::string > > mapStack;
     42                };
     43
     44                PassVisitor<RenameVars> global_renamer;
     45        } // namespace
     46
     47        void renameTyVars( Type * t ) {
     48                t->accept( global_renamer );
     49        }
     50
     51        void resetTyVarRenaming() {
     52                global_renamer.pass.reset();
     53        }
     54
     55        namespace {
     56                RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) {
     57                        mapStack.push_front( std::map< std::string, std::string >() );
    4458                }
    4559
    46                 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
    47 
    48                 void rename( TypeInstType * type ) {
    49                         mapConstIterator it = nameMap.find( type->name );
    50                         if ( it != nameMap.end() ) {
    51                                 type->name = it->second;
    52                         }
     60                void RenameVars::reset() {
     61                        level = 0;
     62                        resetCount++;
    5363                }
    5464
    55                 void openLevel( Type * type ) {
     65                void RenameVars::previsit( TypeInstType * instType ) {
     66                        previsit( (Type *)instType );
     67                        std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name );
     68                        if ( i != mapStack.front().end() ) {
     69                                instType->name = i->second;
     70                        } // if
     71                }
     72
     73                void RenameVars::previsit( Type * type ) {
    5674                        if ( ! type->forall.empty() ) {
    57                                 nameMap.beginScope();
     75                                // copies current name mapping into new mapping
     76                                mapStack.push_front( mapStack.front() );
    5877                                // renames all "forall" type names to `_${level}_${name}'
    5978                                for ( auto td : type->forall ) {
     
    6180                                        output << "_" << resetCount << "_" << level << "_" << td->name;
    6281                                        std::string newname( output.str() );
    63                                         nameMap[ td->get_name() ] = newname;
     82                                        mapStack.front()[ td->get_name() ] = newname;
    6483                                        td->name = newname;
    6584                                        // ditto for assertion names, the next level in
     
    7089                }
    7190
    72                 void closeLevel( Type * type ) {
    73                         if ( !type->forall.empty() ) {
    74                                 nameMap.endScope();
    75                         }
     91                void RenameVars::postvisit( Type * type ) {
     92                        // clears name mapping added by typeBefore()
     93                        if ( ! type->forall.empty() ) {
     94                                mapStack.pop_front();
     95                        } // if
    7696                }
    77 
    78                 const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    79                         mapConstIterator it = nameMap.find( type->name );
    80                         if ( it != nameMap.end() ) {
    81                                 ast::TypeInstType * mutType = ast::mutate( type );
    82                                 mutType->name = it->second;
    83                     type = mutType;
    84                         }
    85                         return type;
    86                 }
    87 
    88                 template<typename NodeT>
    89                 const NodeT * openLevel( const NodeT * type ) {
    90                         if ( !type->forall.empty() ) {
    91                                 nameMap.beginScope();
    92                                 // Load new names from this forall clause and perform renaming.
    93                                 NodeT * mutType = ast::mutate( type );
    94                                 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
    95                                         std::ostringstream output;
    96                                         output << "_" << resetCount << "_" << level << "_" << td->name;
    97                                         std::string newname( output.str() );
    98                                         nameMap[ td->name ] = newname;
    99                                         ++level;
    100 
    101                                         ast::TypeDecl * decl = ast::mutate( td.get() );
    102                                         decl->name = newname;
    103                                         td = decl;
    104                                 }
    105                         }
    106                         return type;
    107                 }
    108 
    109                 template<typename NodeT>
    110                 const NodeT * closeLevel( const NodeT * type ) {
    111                         if ( !type->forall.empty() ) {
    112                                 nameMap.endScope();
    113                         }
    114                         return type;
    115                 }
    116         };
    117 
    118         // Global State:
    119         RenamingData renaming;
    120 
    121         struct RenameVars {
    122                 void previsit( TypeInstType * instType ) {
    123                         renaming.openLevel( (Type*)instType );
    124                         renaming.rename( instType );
    125                 }
    126                 void previsit( Type * type ) {
    127                         renaming.openLevel( type );
    128                 }
    129                 void postvisit( Type * type ) {
    130                         renaming.closeLevel( type );
    131                 }
    132 
    133                 const ast::FunctionType * previsit( const ast::FunctionType * type ) {
    134                         return renaming.openLevel( type );
    135                 }
    136                 const ast::StructInstType * previsit( const ast::StructInstType * type ) {
    137                         return renaming.openLevel( type );
    138                 }
    139                 const ast::UnionInstType * previsit( const ast::UnionInstType * type ) {
    140                         return renaming.openLevel( type );
    141                 }
    142                 const ast::TraitInstType * previsit( const ast::TraitInstType * type ) {
    143                         return renaming.openLevel( type );
    144                 }
    145                 const ast::TypeInstType * previsit( const ast::TypeInstType * type ) {
    146                         return renaming.rename( renaming.openLevel( type ) );
    147                 }
    148                 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
    149                         return renaming.closeLevel( type );
    150                 }
    151         };
    152 
    153 } // namespace
    154 
    155 void renameTyVars( Type * t ) {
    156         PassVisitor<RenameVars> renamer;
    157         t->accept( renamer );
    158 }
    159 
    160 const ast::Type * renameTyVars( const ast::Type * t ) {
    161         ast::Pass<RenameVars> renamer;
    162         return t->accept( renamer );
    163 }
    164 
    165 void resetTyVarRenaming() {
    166         renaming.reset();
    167 }
    168 
     97        } // namespace
    16998} // namespace ResolvExpr
    17099
  • src/ResolvExpr/RenameVars.h

    rb067d9b r7951100  
    2323#include "SynTree/Visitor.h"  // for Visitor
    2424
    25 namespace ast {
    26         class Type;
    27 }
    28 
    2925namespace ResolvExpr {
    3026        /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    3127        void renameTyVars( Type * );
    32         const ast::Type * renameTyVars( const ast::Type * );
    3328
    3429        /// resets internal state of renamer to avoid overflow
  • src/ResolvExpr/ResolveTypeof.cc

    rb067d9b r7951100  
    1818#include <cassert>               // for assert
    1919
    20 #include "AST/CVQualifiers.hpp"
    21 #include "AST/Node.hpp"
    22 #include "AST/Pass.hpp"
    23 #include "AST/Type.hpp"
    24 #include "AST/TypeEnvironment.hpp"
    2520#include "Common/PassVisitor.h"  // for PassVisitor
    26 #include "Common/utility.h"      // for copy
    2721#include "Resolver.h"            // for resolveInVoidContext
    2822#include "SynTree/Expression.h"  // for Expression
     
    4842        }
    4943
    50         class ResolveTypeof_old : public WithShortCircuiting {
     44        class ResolveTypeof : public WithShortCircuiting {
    5145          public:
    52                 ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
     46                ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
    5347                void premutate( TypeofType *typeofType );
    5448                Type * postmutate( TypeofType *typeofType );
     
    5953
    6054        Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
    61                 PassVisitor<ResolveTypeof_old> mutator( indexer );
     55                PassVisitor<ResolveTypeof> mutator( indexer );
    6256                return type->acceptMutator( mutator );
    6357        }
    6458
    65         void ResolveTypeof_old::premutate( TypeofType * ) {
     59        void ResolveTypeof::premutate( TypeofType * ) {
    6660                visit_children = false;
    6761        }
    6862
    69         Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
     63        Type * ResolveTypeof::postmutate( TypeofType *typeofType ) {
    7064#if 0
    7165                std::cerr << "resolving typeof: ";
     
    7367                std::cerr << std::endl;
    7468#endif
    75                 // pass on null expression
    76                 if ( ! typeofType->expr ) return typeofType;
    77 
    78                 bool isBasetypeof = typeofType->is_basetypeof;
    79                 auto oldQuals = typeofType->get_qualifiers().val;
    80 
    81                 Type* newType;
    82                 if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(typeofType->expr) ) {
    83                         // typeof wrapping type
    84                         newType = tyExpr->type;
    85                         tyExpr->type = nullptr;
    86                         delete tyExpr;
    87                 } else {
    88                         // typeof wrapping expression
     69                if ( typeofType->expr ) {
    8970                        Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
    9071                        assert( newExpr->result && ! newExpr->result->isVoid() );
    91                         newType = newExpr->result;
     72                        Type * newType = newExpr->result;
    9273                        newExpr->result = nullptr;
    9374                        delete typeofType;
    9475                        delete newExpr;
    95                 }
    96 
    97                 // clear qualifiers for base, combine with typeoftype quals in any case
    98                 if ( isBasetypeof ) {
    99                         // replace basetypeof(<enum>) by int
    100                         if ( dynamic_cast<EnumInstType*>(newType) ) {
    101                                 Type* newerType =
    102                                         new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
    103                                         newType->attributes };
    104                                 delete newType;
    105                                 newType = newerType;
    106                         }
    107                         newType->get_qualifiers().val
    108                                 = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
    109                 } else {
    110                         newType->get_qualifiers().val |= oldQuals;
    111                 }
    112                
    113                 return newType;
     76                        return newType;
     77                } // if
     78                return typeofType;
    11479        }
    115 
    116 namespace {
    117         struct ResolveTypeof_new : public ast::WithShortCircuiting {
    118                 const ast::SymbolTable & localSymtab;
    119 
    120                 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
    121 
    122                 void premutate( const ast::TypeofType * ) { visit_children = false; }
    123 
    124                 const ast::Type * postmutate( const ast::TypeofType * typeofType ) {
    125                         // pass on null expression
    126                         if ( ! typeofType->expr ) return typeofType;
    127 
    128                         ast::ptr< ast::Type > newType;
    129                         if ( auto tyExpr = typeofType->expr.as< ast::TypeExpr >() ) {
    130                                 // typeof wrapping type
    131                                 newType = tyExpr->type;
    132                         } else {
    133                                 // typeof wrapping expression
    134                                 ast::TypeEnvironment dummy;
    135                                 ast::ptr< ast::Expr > newExpr =
    136                                         resolveInVoidContext( typeofType->expr, localSymtab, dummy );
    137                                 assert( newExpr->result && ! newExpr->result->isVoid() );
    138                                 newType = newExpr->result;
    139                         }
    140 
    141                         // clear qualifiers for base, combine with typeoftype quals regardless
    142                         if ( typeofType->kind == ast::TypeofType::Basetypeof ) {
    143                                 // replace basetypeof(<enum>) by int
    144                                 if ( newType.as< ast::EnumInstType >() ) {
    145                                         newType = new ast::BasicType{
    146                                                 ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
    147                                 }
    148                                 reset_qualifiers(
    149                                         newType,
    150                                         ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
    151                         } else {
    152                                 add_qualifiers( newType, typeofType->qualifiers );
    153                         }
    154 
    155                         return newType;
    156                 }
    157         };
    158 } // anonymous namespace
    159 
    160 const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
    161         ast::Pass< ResolveTypeof_new > mutator{ symtab };
    162         return type->accept( mutator );
    163 }
    164 
    16580} // namespace ResolvExpr
    16681
  • src/ResolvExpr/ResolveTypeof.h

    rb067d9b r7951100  
    2020class Indexer;
    2121}  // namespace SymTab
    22 namespace ast {
    23         class Type;
    24         class SymbolTable;
    25 }
    2622
    2723namespace ResolvExpr {
    2824        Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
    29         const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & );
    3025} // namespace ResolvExpr
    3126
  • src/ResolvExpr/Resolver.cc

    rb067d9b r7951100  
    77// Resolver.cc --
    88//
    9 // Author           : Aaron B. Moss
     9// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed May 29 11:00:00 2019
    13 // Update Count     : 241
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb 17 11:19:40 2018
     13// Update Count     : 213
    1414//
    1515
     16#include <stddef.h>                      // for NULL
    1617#include <cassert>                       // for strict_dynamic_cast, assert
    1718#include <memory>                        // for allocator, allocator_traits<...
    1819#include <tuple>                         // for get
    19 #include <vector>                        // for vector
     20#include <vector>
    2021
    2122#include "Alternative.h"                 // for Alternative, AltList
    2223#include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
    23 #include "Candidate.hpp"
    24 #include "CandidateFinder.hpp"
    25 #include "CurrentObject.h"               // for CurrentObject
    26 #include "RenameVars.h"                  // for RenameVars, global_renamer
    27 #include "Resolver.h"
    28 #include "ResolvMode.h"                  // for ResolvMode
    29 #include "typeops.h"                     // for extractResultType
    30 #include "Unify.h"                       // for unify
    31 #include "AST/Chain.hpp"
    32 #include "AST/Decl.hpp"
    33 #include "AST/Init.hpp"
    34 #include "AST/Pass.hpp"
    35 #include "AST/Print.hpp"
    36 #include "AST/SymbolTable.hpp"
    37 #include "AST/Type.hpp"
    3824#include "Common/PassVisitor.h"          // for PassVisitor
    3925#include "Common/SemanticError.h"        // for SemanticError
    4026#include "Common/utility.h"              // for ValueGuard, group_iterate
     27#include "CurrentObject.h"               // for CurrentObject
    4128#include "InitTweak/GenInit.h"
    4229#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
     30#include "RenameVars.h"                  // for RenameVars, global_renamer
    4331#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     32#include "ResolveTypeof.h"               // for resolveTypeof
     33#include "Resolver.h"
    4434#include "SymTab/Autogen.h"              // for SizeType
    4535#include "SymTab/Indexer.h"              // for Indexer
     
    5242#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    5343#include "Tuples/Tuples.h"
    54 #include "Validate/FindSpecialDecls.h"   // for SizeType
     44#include "typeops.h"                     // for extractResultType
     45#include "Unify.h"                       // for unify
    5546
    5647using namespace std;
    5748
    5849namespace ResolvExpr {
    59         struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
    60                 Resolver_old() {}
    61                 Resolver_old( const SymTab::Indexer & other ) {
     50        struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {
     51                Resolver() {}
     52                Resolver( const SymTab::Indexer & other ) {
    6253                        indexer = other;
    6354                }
    6455
    65                 void previsit( FunctionDecl * functionDecl );
    66                 void postvisit( FunctionDecl * functionDecl );
    67                 void previsit( ObjectDecl * objectDecll );
     56                void previsit( FunctionDecl *functionDecl );
     57                void postvisit( FunctionDecl *functionDecl );
     58                void previsit( ObjectDecl *objectDecll );
     59                void previsit( TypeDecl *typeDecl );
    6860                void previsit( EnumDecl * enumDecl );
    6961                void previsit( StaticAssertDecl * assertDecl );
     
    7264                void previsit( PointerType * at );
    7365
    74                 void previsit( ExprStmt * exprStmt );
    75                 void previsit( AsmExpr * asmExpr );
    76                 void previsit( AsmStmt * asmStmt );
    77                 void previsit( IfStmt * ifStmt );
    78                 void previsit( WhileStmt * whileStmt );
    79                 void previsit( ForStmt * forStmt );
    80                 void previsit( SwitchStmt * switchStmt );
    81                 void previsit( CaseStmt * caseStmt );
    82                 void previsit( BranchStmt * branchStmt );
    83                 void previsit( ReturnStmt * returnStmt );
    84                 void previsit( ThrowStmt * throwStmt );
    85                 void previsit( CatchStmt * catchStmt );
     66                void previsit( ExprStmt *exprStmt );
     67                void previsit( AsmExpr *asmExpr );
     68                void previsit( AsmStmt *asmStmt );
     69                void previsit( IfStmt *ifStmt );
     70                void previsit( WhileStmt *whileStmt );
     71                void previsit( ForStmt *forStmt );
     72                void previsit( SwitchStmt *switchStmt );
     73                void previsit( CaseStmt *caseStmt );
     74                void previsit( BranchStmt *branchStmt );
     75                void previsit( ReturnStmt *returnStmt );
     76                void previsit( ThrowStmt *throwStmt );
     77                void previsit( CatchStmt *catchStmt );
    8678                void previsit( WaitForStmt * stmt );
    87 
    88                 void previsit( SingleInit * singleInit );
    89                 void previsit( ListInit * listInit );
    90                 void previsit( ConstructorInit * ctorInit );
     79                void previsit( WithStmt * withStmt );
     80
     81                void previsit( SingleInit *singleInit );
     82                void previsit( ListInit *listInit );
     83                void previsit( ConstructorInit *ctorInit );
    9184          private:
    9285                typedef std::list< Initializer * >::iterator InitIterator;
     
    9588                void handlePtrType( PtrType * type );
    9689
     90                void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    9791                void fallbackInit( ConstructorInit * ctorInit );
    9892
     
    10296        };
    10397
    104         struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
    105                 void previsit( FunctionDecl * );
    106                 void previsit( WithStmt * );
    107 
    108                 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    109         };
    110 
    11198        void resolve( std::list< Declaration * > translationUnit ) {
    112                 PassVisitor<Resolver_old> resolver;
     99                PassVisitor<Resolver> resolver;
    113100                acceptAll( translationUnit, resolver );
    114101        }
    115102
    116         void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
    117                 PassVisitor<Resolver_old> resolver( indexer );
     103        void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
     104                PassVisitor<Resolver> resolver( indexer );
    118105                maybeAccept( decl, resolver );
    119106        }
    120107
    121108        namespace {
    122                 struct DeleteFinder_old : public WithShortCircuiting    {
     109                struct DeleteFinder : public WithShortCircuiting        {
    123110                        DeletedExpr * delExpr = nullptr;
    124111                        void previsit( DeletedExpr * expr ) {
     
    134121
    135122        DeletedExpr * findDeletedExpr( Expression * expr ) {
    136                 PassVisitor<DeleteFinder_old> finder;
     123                PassVisitor<DeleteFinder> finder;
    137124                expr->accept( finder );
    138125                return finder.pass.delExpr;
     
    140127
    141128        namespace {
    142                 struct StripCasts_old {
     129                struct StripCasts {
    143130                        Expression * postmutate( CastExpr * castExpr ) {
    144131                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     
    153140
    154141                        static void strip( Expression *& expr ) {
    155                                 PassVisitor<StripCasts_old> stripper;
     142                                PassVisitor<StripCasts> stripper;
    156143                                expr = expr->acceptMutator( stripper );
    157144                        }
    158145                };
    159146
    160                 void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
     147                void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
    161148                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    162149                        env.makeSubstitution( *expr->env );
    163                         StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
     150                        StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
    164151                }
    165152
    166153                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    167154                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    168                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     155                                if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    169156                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
    170157                                        expr = castExpr->arg;
     
    178165
    179166        namespace {
    180                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
     167                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    181168                        assertf( untyped, "expected a non-null expression." );
    182 
    183                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    184                         static unsigned recursion_level = 0;
    185 
    186                         ++recursion_level;
    187169                        TypeEnvironment env;
    188170                        AlternativeFinder finder( indexer, env );
    189                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    190                         --recursion_level;
     171                        finder.find( untyped, adjust, prune, failFast );
    191172
    192173                        #if 0
     
    201182                        #endif
    202183
    203                         // produce filtered list of alternatives
    204184                        AltList candidates;
    205185                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    209189                        }
    210190
    211                         // produce invalid error if no candidates
    212                         if ( candidates.empty() ) {
     191                        // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
     192                        // choose the lowest cost expression among the candidates
     193                        AltList winners;
     194                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     195                        if ( winners.size() == 0 ) {
    213196                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    214                         }
    215 
    216                         // search for cheapest candidate
    217                         AltList winners;
    218                         bool seen_undeleted = false;
    219                         for ( unsigned i = 0; i < candidates.size(); ++i ) {
    220                                 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
    221 
    222                                 if ( c > 0 ) continue; // skip more expensive than winner
    223 
    224                                 if ( c < 0 ) {
    225                                         // reset on new cheapest
    226                                         seen_undeleted = ! findDeletedExpr( candidates[i].expr );
    227                                         winners.clear();
    228                                 } else /* if ( c == 0 ) */ {
    229                                         if ( findDeletedExpr( candidates[i].expr ) ) {
    230                                                 // skip deleted expression if already seen one equivalent-cost not
    231                                                 if ( seen_undeleted ) continue;
    232                                         } else if ( ! seen_undeleted ) {
    233                                                 // replace list of equivalent-cost deleted expressions with one non-deleted
    234                                                 winners.clear();
    235                                                 seen_undeleted = true;
    236                                         }
    237                                 }
    238 
    239                                 winners.emplace_back( std::move( candidates[i] ) );
    240                         }
    241 
    242                         // promote alternative.cvtCost to .cost
    243                         // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
    244                         for ( Alternative& winner : winners ) {
    245                                 winner.cost = winner.cvtCost;
    246                         }
    247 
    248                         // produce ambiguous errors, if applicable
    249                         if ( winners.size() != 1 ) {
     197                        } else if ( winners.size() != 1 ) {
    250198                                std::ostringstream stream;
    251199                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    256204                        }
    257205
    258                         // single selected choice
    259                         Alternative& choice = winners.front();
    260 
    261                         // fail on only expression deleted
    262                         if ( ! seen_undeleted ) {
     206                        // there is one unambiguous interpretation - move the expression into the with statement
     207                        Alternative & choice = winners.front();
     208                        if ( findDeletedExpr( choice.expr ) ) {
    263209                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    264210                        }
    265 
    266                         // xxx - check for ambiguous expressions
    267 
    268                         // output selected choice
    269211                        alt = std::move( choice );
    270212                }
    271213
    272214                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    273                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
     215                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    274216                        if ( ! untyped ) return;
    275217                        Alternative choice;
    276                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
     218                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
    277219                        finishExpr( choice.expr, choice.env, untyped->env );
    278220                        delete untyped;
     
    289231
    290232        // used in resolveTypeof
    291         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
     233        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
    292234                TypeEnvironment env;
    293235                return resolveInVoidContext( expr, indexer, env );
    294236        }
    295237
    296         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
     238        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
    297239                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    298240                // interpretations, an exception has already been thrown.
    299241                assertf( expr, "expected a non-null expression." );
    300242
    301                 CastExpr * untyped = new CastExpr( expr ); // cast to void
    302                 untyped->location = expr->location;
     243                static CastExpr untyped( nullptr ); // cast to void
     244                untyped.location = expr->location;
    303245
    304246                // set up and resolve expression cast to void
     247                untyped.arg = expr;
    305248                Alternative choice;
    306                 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
     249                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
    307250                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    308                 assert( castExpr );
    309251                env = std::move( choice.env );
    310252
     
    314256
    315257                // unlink the arg so that it isn't deleted twice at the end of the program
    316                 untyped->arg = nullptr;
     258                untyped.arg = nullptr;
    317259                return ret;
    318260        }
    319261
    320         void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     262        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    321263                resetTyVarRenaming();
    322264                TypeEnvironment env;
     
    327269        }
    328270
    329         void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     271        void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
    330272                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    331273        }
     
    346288                        if ( dynamic_cast< EnumInstType * >( type ) ) {
    347289                                return true;
    348                         } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
     290                        } else if ( BasicType *bt = dynamic_cast< BasicType * >( type ) ) {
    349291                                return bt->isInteger();
    350292                        } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
     
    355297                }
    356298
    357                 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
     299                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    358300                        findKindExpression( untyped, indexer, "condition", isIntegralType );
    359301                }
    360302        }
    361303
    362 
    363         bool isStructOrUnion( const Alternative & alt ) {
    364                 Type * t = alt.expr->result->stripReferences();
    365                 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    366         }
    367 
    368         void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
    369                 PassVisitor<ResolveWithExprs> resolver;
    370                 acceptAll( translationUnit, resolver );
    371         }
    372 
    373         void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
    374                 for ( Expression *& expr : withExprs )  {
    375                         // only struct- and union-typed expressions are viable candidates
    376                         findKindExpression( expr, indexer, "with statement", isStructOrUnion );
    377 
    378                         // if with expression might be impure, create a temporary so that it is evaluated once
    379                         if ( Tuples::maybeImpure( expr ) ) {
    380                                 static UniqueName tmpNamer( "_with_tmp_" );
    381                                 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
    382                                 expr = new VariableExpr( tmp );
    383                                 newStmts.push_back( new DeclStmt( tmp ) );
    384                                 if ( InitTweak::isConstructable( tmp->type ) ) {
    385                                         // generate ctor/dtor and resolve them
    386                                         tmp->init = InitTweak::genCtorInit( tmp );
    387                                         tmp->accept( *visitor );
    388                                 }
    389                         }
    390                 }
    391         }
    392 
    393         void ResolveWithExprs::previsit( WithStmt * withStmt ) {
    394                 resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
    395         }
    396 
    397         void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
     304        void Resolver::previsit( ObjectDecl *objectDecl ) {
     305                Type *new_type = resolveTypeof( objectDecl->get_type(), indexer );
     306                objectDecl->set_type( new_type );
     307                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
     308                // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes
     309                // initContext because of a function type can contain object declarations in the return and parameter types. So
     310                // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting
     311                // the RHS.
     312                GuardValue( currentObject );
     313                currentObject = CurrentObject( objectDecl->get_type() );
     314                if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
     315                        // enumerator initializers should not use the enum type to initialize, since
     316                        // the enum type is still incomplete at this point. Use signed int instead.
     317                        currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     318                }
     319        }
     320
     321        template< typename PtrType >
     322        void Resolver::handlePtrType( PtrType * type ) {
     323                if ( type->get_dimension() ) {
     324                        findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer );
     325                }
     326        }
     327
     328        void Resolver::previsit( ArrayType * at ) {
     329                handlePtrType( at );
     330        }
     331
     332        void Resolver::previsit( PointerType * pt ) {
     333                handlePtrType( pt );
     334        }
     335
     336        void Resolver::previsit( TypeDecl *typeDecl ) {
     337                if ( typeDecl->get_base() ) {
     338                        Type *new_type = resolveTypeof( typeDecl->get_base(), indexer );
     339                        typeDecl->set_base( new_type );
     340                } // if
     341        }
     342
     343        void Resolver::previsit( FunctionDecl *functionDecl ) {
     344#if 0
     345                std::cerr << "resolver visiting functiondecl ";
     346                functionDecl->print( std::cerr );
     347                std::cerr << std::endl;
     348#endif
     349                Type *new_type = resolveTypeof( functionDecl->type, indexer );
     350                functionDecl->set_type( new_type );
     351                GuardValue( functionReturn );
     352                functionReturn = ResolvExpr::extractResultType( functionDecl->type );
     353
    398354                {
    399355                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
     
    411367        }
    412368
    413         void Resolver_old::previsit( ObjectDecl * objectDecl ) {
    414                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    415                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    416                 // The second analysis changes initContext because of a function type can contain object
    417                 // declarations in the return and parameter types. So each value of initContext is
    418                 // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    419                 GuardValue( currentObject );
    420                 currentObject = CurrentObject( objectDecl->get_type() );
    421                 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
    422                         // enumerator initializers should not use the enum type to initialize, since
    423                         // the enum type is still incomplete at this point. Use signed int instead.
    424                         currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    425                 }
    426         }
    427 
    428         template< typename PtrType >
    429         void Resolver_old::handlePtrType( PtrType * type ) {
    430                 if ( type->get_dimension() ) {
    431                         findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
    432                 }
    433         }
    434 
    435         void Resolver_old::previsit( ArrayType * at ) {
    436                 handlePtrType( at );
    437         }
    438 
    439         void Resolver_old::previsit( PointerType * pt ) {
    440                 handlePtrType( pt );
    441         }
    442 
    443         void Resolver_old::previsit( FunctionDecl * functionDecl ) {
    444 #if 0
    445                 std::cerr << "resolver visiting functiondecl ";
    446                 functionDecl->print( std::cerr );
    447                 std::cerr << std::endl;
    448 #endif
    449                 GuardValue( functionReturn );
    450                 functionReturn = ResolvExpr::extractResultType( functionDecl->type );
    451         }
    452 
    453         void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
    454                 // default value expressions have an environment which shouldn't be there and trips up
    455                 // later passes.
    456                 // xxx - it might be necessary to somehow keep the information from this environment, but I
    457                 // can't currently see how it's useful.
     369        void Resolver::postvisit( FunctionDecl *functionDecl ) {
     370                // default value expressions have an environment which shouldn't be there and trips up later passes.
     371                // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
     372                // see how it's useful.
    458373                for ( Declaration * d : functionDecl->type->parameters ) {
    459374                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    466381        }
    467382
    468         void Resolver_old::previsit( EnumDecl * ) {
     383        void Resolver::previsit( EnumDecl * ) {
    469384                // in case we decide to allow nested enums
    470385                GuardValue( inEnumDecl );
     
    472387        }
    473388
    474         void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
     389        void Resolver::previsit( StaticAssertDecl * assertDecl ) {
    475390                findIntegralExpression( assertDecl->condition, indexer );
    476391        }
    477392
    478         void Resolver_old::previsit( ExprStmt * exprStmt ) {
     393        void Resolver::previsit( ExprStmt *exprStmt ) {
    479394                visit_children = false;
    480395                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
     
    482397        }
    483398
    484         void Resolver_old::previsit( AsmExpr * asmExpr ) {
     399        void Resolver::previsit( AsmExpr *asmExpr ) {
    485400                visit_children = false;
    486401                findVoidExpression( asmExpr->operand, indexer );
     
    490405        }
    491406
    492         void Resolver_old::previsit( AsmStmt * asmStmt ) {
     407        void Resolver::previsit( AsmStmt *asmStmt ) {
    493408                visit_children = false;
    494409                acceptAll( asmStmt->get_input(), *visitor );
     
    496411        }
    497412
    498         void Resolver_old::previsit( IfStmt * ifStmt ) {
     413        void Resolver::previsit( IfStmt *ifStmt ) {
    499414                findIntegralExpression( ifStmt->condition, indexer );
    500415        }
    501416
    502         void Resolver_old::previsit( WhileStmt * whileStmt ) {
     417        void Resolver::previsit( WhileStmt *whileStmt ) {
    503418                findIntegralExpression( whileStmt->condition, indexer );
    504419        }
    505420
    506         void Resolver_old::previsit( ForStmt * forStmt ) {
     421        void Resolver::previsit( ForStmt *forStmt ) {
    507422                if ( forStmt->condition ) {
    508423                        findIntegralExpression( forStmt->condition, indexer );
     
    514429        }
    515430
    516         void Resolver_old::previsit( SwitchStmt * switchStmt ) {
     431        void Resolver::previsit( SwitchStmt *switchStmt ) {
    517432                GuardValue( currentObject );
    518433                findIntegralExpression( switchStmt->condition, indexer );
     
    521436        }
    522437
    523         void Resolver_old::previsit( CaseStmt * caseStmt ) {
     438        void Resolver::previsit( CaseStmt *caseStmt ) {
    524439                if ( caseStmt->condition ) {
    525440                        std::list< InitAlternative > initAlts = currentObject.getOptions();
     
    540455        }
    541456
    542         void Resolver_old::previsit( BranchStmt * branchStmt ) {
     457        void Resolver::previsit( BranchStmt *branchStmt ) {
    543458                visit_children = false;
    544459                // must resolve the argument for a computed goto
     
    551466        }
    552467
    553         void Resolver_old::previsit( ReturnStmt * returnStmt ) {
     468        void Resolver::previsit( ReturnStmt *returnStmt ) {
    554469                visit_children = false;
    555470                if ( returnStmt->expr ) {
     
    558473        }
    559474
    560         void Resolver_old::previsit( ThrowStmt * throwStmt ) {
     475        void Resolver::previsit( ThrowStmt *throwStmt ) {
    561476                visit_children = false;
    562477                // TODO: Replace *exception type with &exception type.
    563478                if ( throwStmt->get_expr() ) {
    564                         const StructDecl * exception_decl = indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
     479                        StructDecl * exception_decl =
     480                                indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
    565481                        assert( exception_decl );
    566                         Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
     482                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) );
    567483                        findSingleExpression( throwStmt->expr, exceptType, indexer );
    568484                }
    569485        }
    570486
    571         void Resolver_old::previsit( CatchStmt * catchStmt ) {
     487        void Resolver::previsit( CatchStmt *catchStmt ) {
    572488                if ( catchStmt->cond ) {
    573489                        findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
     
    584500        }
    585501
    586         void Resolver_old::previsit( WaitForStmt * stmt ) {
     502        void Resolver::previsit( WaitForStmt * stmt ) {
    587503                visit_children = false;
    588504
     
    666582
    667583                                                        // Make sure we don't widen any existing bindings
    668                                                         resultEnv.forbidWidening();
     584                                                        for ( auto & i : resultEnv ) {
     585                                                                i.allowWidening = false;
     586                                                        }
    669587
    670588                                                        // Find any unbound type variables
     
    674592                                                        auto param_end = function->parameters.end();
    675593
    676                                                         int n_mutex_param = 0;
     594                                                        int n_mutex_arg = 0;
    677595
    678596                                                        // For every arguments of its set, check if it matches one of the parameter
     
    684602                                                                        // We ran out of parameters but still have arguments
    685603                                                                        // this function doesn't match
    686                                                                         SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
     604                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_arg, "\n" ));
    687605                                                                }
    688606
    689                                                                 n_mutex_param++;
     607                                                                n_mutex_arg++;
    690608
    691609                                                                // Check if the argument matches the parameter type in the current scope
     
    710628                                                        // Check if parameters are missing
    711629                                                        if( advance_to_mutex( param, param_end ) ) {
    712                                                                 do {
    713                                                                         n_mutex_param++;
    714                                                                         param++;
    715                                                                 } while( advance_to_mutex( param, param_end ) );
    716 
    717630                                                                // We ran out of arguments but still have parameters left
    718631                                                                // this function doesn't match
    719                                                                 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
     632                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_arg, "\n" ));
    720633                                                        }
    721634
     
    733646
    734647                                                }
    735                                                 catch( SemanticErrorException & e ) {
     648                                                catch( SemanticErrorException &e ) {
    736649                                                        errors.append( e );
    737650                                                }
    738651                                        }
    739652                                }
    740                                 catch( SemanticErrorException & e ) {
     653                                catch( SemanticErrorException &e ) {
    741654                                        errors.append( e );
    742655                                }
     
    781694        }
    782695
    783         bool isCharType( Type * t ) {
     696        bool isStructOrUnion( const Alternative & alt ) {
     697                Type * t = alt.expr->result->stripReferences();
     698                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     699        }
     700
     701        void Resolver::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
     702                for ( Expression *& expr : withExprs )  {
     703                        // only struct- and union-typed expressions are viable candidates
     704                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
     705
     706                        // if with expression might be impure, create a temporary so that it is evaluated once
     707                        if ( Tuples::maybeImpure( expr ) ) {
     708                                static UniqueName tmpNamer( "_with_tmp_" );
     709                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
     710                                expr = new VariableExpr( tmp );
     711                                newStmts.push_back( new DeclStmt( tmp ) );
     712                                if ( InitTweak::isConstructable( tmp->type ) ) {
     713                                        // generate ctor/dtor and resolve them
     714                                        tmp->init = InitTweak::genCtorInit( tmp );
     715                                        tmp->accept( *visitor );
     716                                }
     717                        }
     718                }
     719        }
     720
     721        void Resolver::previsit( WithStmt * withStmt ) {
     722                resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
     723        }
     724
     725        template< typename T >
     726        bool isCharType( T t ) {
    784727                if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
    785728                        return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
     
    789732        }
    790733
    791         void Resolver_old::previsit( SingleInit * singleInit ) {
     734        void Resolver::previsit( SingleInit *singleInit ) {
    792735                visit_children = false;
    793736                // resolve initialization using the possibilities as determined by the currentObject cursor
     
    803746                initExpr->expr = nullptr;
    804747                std::swap( initExpr->env, newExpr->env );
    805                 // InitExpr may have inferParams in the case where the expression specializes a function
    806                 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
    807                 // sufficient.
     748                // InitExpr may have inferParams in the case where the expression specializes a function pointer,
     749                // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
    808750                newExpr->spliceInferParams( initExpr );
    809751                delete initExpr;
    810752
    811                 // get the actual object's type (may not exactly match what comes back from the resolver
    812                 // due to conversions)
     753                // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
    813754                Type * initContext = currentObject.getCurrentType();
    814755
     
    821762                                if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
    822763                                        if ( isCharType( pt->get_base() ) ) {
    823                                                 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    824                                                         // strip cast if we're initializing a char[] with a char *,
    825                                                         // e.g.  char x[] = "hello";
     764                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
     765                                                        // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
    826766                                                        newExpr = ce->get_arg();
    827767                                                        ce->set_arg( nullptr );
     
    841781        }
    842782
    843         void Resolver_old::previsit( ListInit * listInit ) {
     783        void Resolver::previsit( ListInit * listInit ) {
    844784                visit_children = false;
    845785                // move cursor into brace-enclosed initializer-list
    846786                currentObject.enterListInit();
    847                 // xxx - fix this so that the list isn't copied, iterator should be used to change current
    848                 // element
     787                // xxx - fix this so that the list isn't copied, iterator should be used to change current element
    849788                std::list<Designation *> newDesignations;
    850789                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    851                         // iterate designations and initializers in pairs, moving the cursor to the current
    852                         // designated object and resolving the initializer against that object.
     790                        // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
     791                        // the initializer against that object.
    853792                        Designation * des = std::get<0>(p);
    854793                        Initializer * init = std::get<1>(p);
     
    876815
    877816        // ConstructorInit - fall back on C-style initializer
    878         void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
     817        void Resolver::fallbackInit( ConstructorInit * ctorInit ) {
    879818                // could not find valid constructor, or found an intrinsic constructor
    880819                // fall back on C-style initializer
    881820                delete ctorInit->get_ctor();
    882                 ctorInit->set_ctor( nullptr );
     821                ctorInit->set_ctor( NULL );
    883822                delete ctorInit->get_dtor();
    884                 ctorInit->set_dtor( nullptr );
     823                ctorInit->set_dtor( NULL );
    885824                maybeAccept( ctorInit->get_init(), *visitor );
    886825        }
     
    889828        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
    890829                assert( ctorInit );
    891                 PassVisitor<Resolver_old> resolver( indexer );
     830                PassVisitor<Resolver> resolver( indexer );
    892831                ctorInit->accept( resolver );
    893832        }
     
    895834        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
    896835                assert( stmtExpr );
    897                 PassVisitor<Resolver_old> resolver( indexer );
     836                PassVisitor<Resolver> resolver( indexer );
    898837                stmtExpr->accept( resolver );
    899838                stmtExpr->computeResult();
     
    901840        }
    902841
    903         void Resolver_old::previsit( ConstructorInit * ctorInit ) {
     842        void Resolver::previsit( ConstructorInit *ctorInit ) {
    904843                visit_children = false;
    905844                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
     
    925864
    926865                // xxx - todo -- what about arrays?
    927                 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     866                // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    928867                //      // can reduce the constructor down to a SingleInit using the
    929868                //      // second argument from the ctor call, since
    930869                //      delete ctorInit->get_ctor();
    931                 //      ctorInit->set_ctor( nullptr );
     870                //      ctorInit->set_ctor( NULL );
    932871
    933872                //      Expression * arg =
     
    935874                // }
    936875        }
    937 
    938         ///////////////////////////////////////////////////////////////////////////
    939         //
    940         // *** NEW RESOLVER ***
    941         //
    942         ///////////////////////////////////////////////////////////////////////////
    943 
    944         namespace {
    945                 /// Finds deleted expressions in an expression tree
    946                 struct DeleteFinder_new final : public ast::WithShortCircuiting {
    947                         const ast::DeletedExpr * delExpr = nullptr;
    948 
    949                         void previsit( const ast::DeletedExpr * expr ) {
    950                                 if ( delExpr ) { visit_children = false; }
    951                                 else { delExpr = expr; }
    952                         }
    953 
    954                         void previsit( const ast::Expr * ) {
    955                                 if ( delExpr ) { visit_children = false; }
    956                         }
    957                 };
    958         } // anonymous namespace
    959 
    960         /// Check if this expression is or includes a deleted expression
    961         const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
    962                 ast::Pass<DeleteFinder_new> finder;
    963                 expr->accept( finder );
    964                 return finder.pass.delExpr;
    965         }
    966 
    967         namespace {
    968                 /// always-accept candidate filter
    969                 bool anyCandidate( const Candidate & ) { return true; }
    970 
    971                 /// Calls the CandidateFinder and finds the single best candidate
    972                 CandidateRef findUnfinishedKindExpression(
    973                         const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
    974                         std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
    975                 ) {
    976                         if ( ! untyped ) return nullptr;
    977 
    978                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    979                         static unsigned recursion_level = 0;
    980 
    981                         ++recursion_level;
    982                         ast::TypeEnvironment env;
    983                         CandidateFinder finder{ symtab, env };
    984                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    985                         --recursion_level;
    986 
    987                         // produce a filtered list of candidates
    988                         CandidateList candidates;
    989                         for ( auto & cand : finder.candidates ) {
    990                                 if ( pred( *cand ) ) { candidates.emplace_back( cand ); }
    991                         }
    992 
    993                         // produce invalid error if no candidates
    994                         if ( candidates.empty() ) {
    995                                 SemanticError( untyped,
    996                                         toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),
    997                                         "expression: ") );
    998                         }
    999 
    1000                         // search for cheapest candidate
    1001                         CandidateList winners;
    1002                         bool seen_undeleted = false;
    1003                         for ( CandidateRef & cand : candidates ) {
    1004                                 int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );
    1005 
    1006                                 if ( c > 0 ) continue;  // skip more expensive than winner
    1007 
    1008                                 if ( c < 0 ) {
    1009                                         // reset on new cheapest
    1010                                         seen_undeleted = ! findDeletedExpr( cand->expr );
    1011                                         winners.clear();
    1012                                 } else /* if ( c == 0 ) */ {
    1013                                         if ( findDeletedExpr( cand->expr ) ) {
    1014                                                 // skip deleted expression if already seen one equivalent-cost not
    1015                                                 if ( seen_undeleted ) continue;
    1016                                         } else if ( ! seen_undeleted ) {
    1017                                                 // replace list of equivalent-cost deleted expressions with one non-deleted
    1018                                                 winners.clear();
    1019                                                 seen_undeleted = true;
    1020                                         }
    1021                                 }
    1022 
    1023                                 winners.emplace_back( std::move( cand ) );
    1024                         }
    1025 
    1026                         // promote candidate.cvtCost to .cost
    1027                         promoteCvtCost( winners );
    1028 
    1029                         // produce ambiguous errors, if applicable
    1030                         if ( winners.size() != 1 ) {
    1031                                 std::ostringstream stream;
    1032                                 stream << "Cannot choose between " << winners.size() << " alternatives for "
    1033                                         << kind << (kind != "" ? " " : "") << "expression\n";
    1034                                 ast::print( stream, untyped );
    1035                                 stream << " Alternatives are:\n";
    1036                                 print( stream, winners, 1 );
    1037                                 SemanticError( untyped->location, stream.str() );
    1038                         }
    1039 
    1040                         // single selected choice
    1041                         CandidateRef & choice = winners.front();
    1042 
    1043                         // fail on only expression deleted
    1044                         if ( ! seen_undeleted ) {
    1045                                 SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "
    1046                                 "includes deleted identifier in " );
    1047                         }
    1048 
    1049                         return std::move( choice );
    1050                 }
    1051 
    1052                 /// Strips extraneous casts out of an expression
    1053                 struct StripCasts_new final {
    1054                         const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
    1055                                 if (
    1056                                         castExpr->isGenerated
    1057                                         && typesCompatible( castExpr->arg->result, castExpr->result )
    1058                                 ) {
    1059                                         // generated cast is the same type as its argument, remove it after keeping env
    1060                                         return ast::mutate_field(
    1061                                                 castExpr->arg.get(), &ast::Expr::env, castExpr->env );
    1062                                 }
    1063                                 return castExpr;
    1064                         }
    1065 
    1066                         static void strip( ast::ptr< ast::Expr > & expr ) {
    1067                                 ast::Pass< StripCasts_new > stripper;
    1068                                 expr = expr->accept( stripper );
    1069                         }
    1070                 };
    1071 
    1072                 /// Swaps argument into expression pointer, saving original environment
    1073                 void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {
    1074                         ast::ptr< ast::TypeSubstitution > env = expr->env;
    1075                         expr.set_and_mutate( newExpr )->env = env;
    1076                 }
    1077 
    1078                 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
    1079                 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
    1080                         if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
    1081                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
    1082                                         // cast is to the same type as its argument, remove it
    1083                                         swap_and_save_env( expr, castExpr->arg );
    1084                                 }
    1085                         }
    1086                 }
    1087 
    1088                 /// Establish post-resolver invariants for expressions
    1089                 void finishExpr(
    1090                         ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
    1091                         const ast::TypeSubstitution * oldenv = nullptr
    1092                 ) {
    1093                         // set up new type substitution for expression
    1094                         ast::ptr< ast::TypeSubstitution > newenv =
    1095                                  oldenv ? oldenv : new ast::TypeSubstitution{};
    1096                         env.writeToSubstitution( *newenv.get_and_mutate() );
    1097                         expr.get_and_mutate()->env = std::move( newenv );
    1098                         // remove unncecessary casts
    1099                         StripCasts_new::strip( expr );
    1100                 }
    1101         } // anonymous namespace
    1102 
    1103 
    1104         ast::ptr< ast::Expr > resolveInVoidContext(
    1105                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
    1106         ) {
    1107                 assertf( expr, "expected a non-null expression" );
    1108 
    1109                 // set up and resolve expression cast to void
    1110                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
    1111                 CandidateRef choice = findUnfinishedKindExpression(
    1112                         untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
    1113 
    1114                 // a cast expression has either 0 or 1 interpretations (by language rules);
    1115                 // if 0, an exception has already been thrown, and this code will not run
    1116                 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
    1117                 env = std::move( choice->env );
    1118 
    1119                 return castExpr->arg;
    1120         }
    1121 
    1122         namespace {
    1123                 /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    1124                 /// context.
    1125                 ast::ptr< ast::Expr > findVoidExpression(
    1126                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1127                 ) {
    1128                         resetTyVarRenaming();
    1129                         ast::TypeEnvironment env;
    1130                         ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
    1131                         finishExpr( newExpr, env, untyped->env );
    1132                         return newExpr;
    1133                 }
    1134 
    1135                 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    1136                 /// lowest cost, returning the resolved version
    1137                 ast::ptr< ast::Expr > findKindExpression(
    1138                         const ast::Expr * untyped, const ast::SymbolTable & symtab,
    1139                         std::function<bool(const Candidate &)> pred = anyCandidate,
    1140                         const std::string & kind = "", ResolvMode mode = {}
    1141                 ) {
    1142                         if ( ! untyped ) return {};
    1143                         CandidateRef choice =
    1144                                 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
    1145                         finishExpr( choice->expr, choice->env, untyped->env );
    1146                         return std::move( choice->expr );
    1147                 }
    1148 
    1149                 /// Resolve `untyped` to the single expression whose candidate is the best match
    1150                 ast::ptr< ast::Expr > findSingleExpression(
    1151                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1152                 ) {
    1153                         return findKindExpression( untyped, symtab );
    1154                 }
    1155         } // anonymous namespace
    1156 
    1157                 ast::ptr< ast::Expr > findSingleExpression(
    1158                         const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
    1159                 ) {
    1160                         assert( untyped && type );
    1161                         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    1162                         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    1163                         removeExtraneousCast( newExpr, symtab );
    1164                         return newExpr;
    1165                 }
    1166 
    1167         namespace {
    1168                 /// Predicate for "Candidate has integral type"
    1169                 bool hasIntegralType( const Candidate & i ) {
    1170                         const ast::Type * type = i.expr->result;
    1171 
    1172                         if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {
    1173                                 return bt->isInteger();
    1174                         } else if (
    1175                                 dynamic_cast< const ast::EnumInstType * >( type )
    1176                                 || dynamic_cast< const ast::ZeroType * >( type )
    1177                                 || dynamic_cast< const ast::OneType * >( type )
    1178                         ) {
    1179                                 return true;
    1180                         } else return false;
    1181                 }
    1182 
    1183                 /// Resolve `untyped` as an integral expression, returning the resolved version
    1184                 ast::ptr< ast::Expr > findIntegralExpression(
    1185                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1186                 ) {
    1187                         return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
    1188                 }
    1189 
    1190                 /// check if a type is a character type
    1191                 bool isCharType( const ast::Type * t ) {
    1192                         if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {
    1193                                 return bt->kind == ast::BasicType::Char
    1194                                         || bt->kind == ast::BasicType::SignedChar
    1195                                         || bt->kind == ast::BasicType::UnsignedChar;
    1196                         }
    1197                         return false;
    1198                 }
    1199 
    1200                 /// Advance a type itertor to the next mutex parameter
    1201                 template<typename Iter>
    1202                 inline bool nextMutex( Iter & it, const Iter & end ) {
    1203                         while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
    1204                         return it != end;
    1205                 }
    1206         }
    1207 
    1208         class Resolver_new final
    1209         : public ast::WithSymbolTable, public ast::WithGuards,
    1210           public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
    1211           public ast::WithStmtsToAdd<> {
    1212 
    1213                 ast::ptr< ast::Type > functionReturn = nullptr;
    1214                 ast::CurrentObject currentObject;
    1215                 bool inEnumDecl = false;
    1216 
    1217         public:
    1218                 Resolver_new() = default;
    1219                 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
    1220 
    1221                 void previsit( const ast::FunctionDecl * );
    1222                 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
    1223                 void previsit( const ast::ObjectDecl * );
    1224                 void previsit( const ast::EnumDecl * );
    1225                 const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
    1226 
    1227                 const ast::ArrayType * previsit( const ast::ArrayType * );
    1228                 const ast::PointerType * previsit( const ast::PointerType * );
    1229 
    1230                 const ast::ExprStmt *        previsit( const ast::ExprStmt * );
    1231                 const ast::AsmExpr *         previsit( const ast::AsmExpr * );
    1232                 const ast::AsmStmt *         previsit( const ast::AsmStmt * );
    1233                 const ast::IfStmt *          previsit( const ast::IfStmt * );
    1234                 const ast::WhileStmt *       previsit( const ast::WhileStmt * );
    1235                 const ast::ForStmt *         previsit( const ast::ForStmt * );
    1236                 const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
    1237                 const ast::CaseStmt *        previsit( const ast::CaseStmt * );
    1238                 const ast::BranchStmt *      previsit( const ast::BranchStmt * );
    1239                 const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
    1240                 const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
    1241                 const ast::CatchStmt *       previsit( const ast::CatchStmt * );
    1242                 const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
    1243 
    1244                 const ast::SingleInit *      previsit( const ast::SingleInit * );
    1245                 const ast::ListInit *        previsit( const ast::ListInit * );
    1246                 const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
    1247         };
    1248 
    1249         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
    1250                 ast::Pass< Resolver_new > resolver;
    1251                 accept_all( translationUnit, resolver );
    1252         }
    1253 
    1254         ast::ptr< ast::Init > resolveCtorInit(
    1255                 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab
    1256         ) {
    1257                 assert( ctorInit );
    1258                 ast::Pass< Resolver_new > resolver{ symtab };
    1259                 return ctorInit->accept( resolver );
    1260         }
    1261 
    1262         ast::ptr< ast::Expr > resolveStmtExpr(
    1263                 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab
    1264         ) {
    1265                 assert( stmtExpr );
    1266                 ast::Pass< Resolver_new > resolver{ symtab };
    1267                 ast::ptr< ast::Expr > ret = stmtExpr;
    1268                 ret = ret->accept( resolver );
    1269                 strict_dynamic_cast< ast::StmtExpr * >( ret.get_and_mutate() )->computeResult();
    1270                 return ret;
    1271         }
    1272 
    1273         void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
    1274                 GuardValue( functionReturn );
    1275                 functionReturn = extractResultType( functionDecl->type );
    1276         }
    1277 
    1278         const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) {
    1279                 // default value expressions have an environment which shouldn't be there and trips up
    1280                 // later passes.
    1281                 ast::ptr< ast::FunctionDecl > ret = functionDecl;
    1282                 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1283                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
    1284 
    1285                         if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
    1286                                 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    1287                                         if ( init->value->env == nullptr ) continue;
    1288                                         // clone initializer minus the initializer environment
    1289                                         ast::chain_mutate( ret )
    1290                                                 ( &ast::FunctionDecl::type )
    1291                                                         ( &ast::FunctionType::params )[i]
    1292                                                                 ( &ast::ObjectDecl::init )
    1293                                                                         ( &ast::SingleInit::value )->env = nullptr;
    1294 
    1295                                         assert( functionDecl != ret.get() || functionDecl->unique() );
    1296                                         assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );
    1297                                 }
    1298                         }
    1299                 }
    1300                 return ret.get();
    1301         }
    1302 
    1303         void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    1304                 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
    1305                 // class-variable `initContext` is changed multiple times because the LHS is analyzed
    1306                 // twice. The second analysis changes `initContext` because a function type can contain
    1307                 // object declarations in the return and parameter types. Therefore each value of
    1308                 // `initContext` is retained so the type on the first analysis is preserved and used for
    1309                 // selecting the RHS.
    1310                 GuardValue( currentObject );
    1311                 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
    1312                 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
    1313                         // enumerator initializers should not use the enum type to initialize, since the
    1314                         // enum type is still incomplete at this point. Use `int` instead.
    1315                         currentObject = ast::CurrentObject{
    1316                                 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
    1317                 }
    1318         }
    1319 
    1320         void Resolver_new::previsit( const ast::EnumDecl * ) {
    1321                 // in case we decide to allow nested enums
    1322                 GuardValue( inEnumDecl );
    1323                 inEnumDecl = false;
    1324         }
    1325 
    1326         const ast::StaticAssertDecl * Resolver_new::previsit(
    1327                 const ast::StaticAssertDecl * assertDecl
    1328         ) {
    1329                 return ast::mutate_field(
    1330                         assertDecl, &ast::StaticAssertDecl::cond,
    1331                         findIntegralExpression( assertDecl->cond, symtab ) );
    1332         }
    1333 
    1334         template< typename PtrType >
    1335         const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
    1336                 if ( type->dimension ) {
    1337                         #warning should use new equivalent to Validate::SizeType rather than sizeType here
    1338                         ast::ptr< ast::Type > sizeType = new ast::BasicType{ ast::BasicType::LongUnsignedInt };
    1339                         ast::mutate_field(
    1340                                 type, &PtrType::dimension,
    1341                                 findSingleExpression( type->dimension, sizeType, symtab ) );
    1342                 }
    1343                 return type;
    1344         }
    1345 
    1346         const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
    1347                 return handlePtrType( at, symtab );
    1348         }
    1349 
    1350         const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
    1351                 return handlePtrType( pt, symtab );
    1352         }
    1353 
    1354         const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
    1355                 visit_children = false;
    1356                 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
    1357 
    1358                 return ast::mutate_field(
    1359                         exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
    1360         }
    1361 
    1362         const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
    1363                 visit_children = false;
    1364 
    1365                 asmExpr = ast::mutate_field(
    1366                         asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
    1367 
    1368                 if ( asmExpr->inout ) {
    1369                         asmExpr = ast::mutate_field(
    1370                                 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) );
    1371                 }
    1372 
    1373                 return asmExpr;
    1374         }
    1375 
    1376         const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
    1377                 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
    1378                 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
    1379                 visit_children = false;
    1380                 return asmStmt;
    1381         }
    1382 
    1383         const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
    1384                 return ast::mutate_field(
    1385                         ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
    1386         }
    1387 
    1388         const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
    1389                 return ast::mutate_field(
    1390                         whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );
    1391         }
    1392 
    1393         const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
    1394                 if ( forStmt->cond ) {
    1395                         forStmt = ast::mutate_field(
    1396                                 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
    1397                 }
    1398 
    1399                 if ( forStmt->inc ) {
    1400                         forStmt = ast::mutate_field(
    1401                                 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
    1402                 }
    1403 
    1404                 return forStmt;
    1405         }
    1406 
    1407         const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
    1408                 GuardValue( currentObject );
    1409                 switchStmt = ast::mutate_field(
    1410                         switchStmt, &ast::SwitchStmt::cond,
    1411                         findIntegralExpression( switchStmt->cond, symtab ) );
    1412                 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
    1413                 return switchStmt;
    1414         }
    1415 
    1416         const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
    1417                 if ( caseStmt->cond ) {
    1418                         std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
    1419                         assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
    1420                                 "expression." );
    1421 
    1422                         ast::ptr< ast::Expr > untyped =
    1423                                 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1424                         ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
    1425 
    1426                         // case condition cannot have a cast in C, so it must be removed here, regardless of
    1427                         // whether it would perform a conversion.
    1428                         if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
    1429                                 swap_and_save_env( newExpr, castExpr->arg );
    1430                         }
    1431 
    1432                         caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr );
    1433                 }
    1434                 return caseStmt;
    1435         }
    1436 
    1437         const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
    1438                 visit_children = false;
    1439                 // must resolve the argument of a computed goto
    1440                 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    1441                         // computed goto argument is void*
    1442                         ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    1443                         branchStmt = ast::mutate_field(
    1444                                 branchStmt, &ast::BranchStmt::computedTarget,
    1445                                 findSingleExpression( branchStmt->computedTarget, target, symtab ) );
    1446                 }
    1447                 return branchStmt;
    1448         }
    1449 
    1450         const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
    1451                 visit_children = false;
    1452                 if ( returnStmt->expr ) {
    1453                         returnStmt = ast::mutate_field(
    1454                                 returnStmt, &ast::ReturnStmt::expr,
    1455                                 findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
    1456                 }
    1457                 return returnStmt;
    1458         }
    1459 
    1460         const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
    1461                 visit_children = false;
    1462                 if ( throwStmt->expr ) {
    1463                         const ast::StructDecl * exceptionDecl =
    1464                                 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" );
    1465                         assert( exceptionDecl );
    1466                         ast::ptr< ast::Type > exceptType =
    1467                                 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
    1468                         throwStmt = ast::mutate_field(
    1469                                 throwStmt, &ast::ThrowStmt::expr,
    1470                                 findSingleExpression( throwStmt->expr, exceptType, symtab ) );
    1471                 }
    1472                 return throwStmt;
    1473         }
    1474 
    1475         const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
    1476                 if ( catchStmt->cond ) {
    1477                         ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
    1478                         catchStmt = ast::mutate_field(
    1479                                 catchStmt, &ast::CatchStmt::cond,
    1480                                 findSingleExpression( catchStmt->cond, boolType, symtab ) );
    1481                 }
    1482                 return catchStmt;
    1483         }
    1484 
    1485         const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
    1486                 visit_children = false;
    1487 
    1488                 // Resolve all clauses first
    1489                 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
    1490                         const ast::WaitForStmt::Clause & clause = stmt->clauses[i];
    1491 
    1492                         ast::TypeEnvironment env;
    1493                         CandidateFinder funcFinder{ symtab, env };
    1494 
    1495                         // Find all candidates for a function in canonical form
    1496                         funcFinder.find( clause.target.func, ResolvMode::withAdjustment() );
    1497 
    1498                         if ( funcFinder.candidates.empty() ) {
    1499                                 stringstream ss;
    1500                                 ss << "Use of undeclared indentifier '";
    1501                                 ss << clause.target.func.strict_as< ast::NameExpr >()->name;
    1502                                 ss << "' in call to waitfor";
    1503                                 SemanticError( stmt->location, ss.str() );
    1504                         }
    1505 
    1506                         if ( clause.target.args.empty() ) {
    1507                                 SemanticError( stmt->location,
    1508                                         "Waitfor clause must have at least one mutex parameter");
    1509                         }
    1510 
    1511                         // Find all alternatives for all arguments in canonical form
    1512                         std::vector< CandidateFinder > argFinders =
    1513                                 funcFinder.findSubExprs( clause.target.args );
    1514 
    1515                         // List all combinations of arguments
    1516                         std::vector< CandidateList > possibilities;
    1517                         combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );
    1518 
    1519                         // For every possible function:
    1520                         // * try matching the arguments to the parameters, not the other way around because
    1521                         //   more arguments than parameters
    1522                         CandidateList funcCandidates;
    1523                         std::vector< CandidateList > argsCandidates;
    1524                         SemanticErrorException errors;
    1525                         for ( CandidateRef & func : funcFinder.candidates ) {
    1526                                 try {
    1527                                         auto pointerType = dynamic_cast< const ast::PointerType * >(
    1528                                                 func->expr->result->stripReferences() );
    1529                                         if ( ! pointerType ) {
    1530                                                 SemanticError( stmt->location, func->expr->result.get(),
    1531                                                         "candidate not viable: not a pointer type\n" );
    1532                                         }
    1533 
    1534                                         auto funcType = pointerType->base.as< ast::FunctionType >();
    1535                                         if ( ! funcType ) {
    1536                                                 SemanticError( stmt->location, func->expr->result.get(),
    1537                                                         "candidate not viable: not a function type\n" );
    1538                                         }
    1539 
    1540                                         {
    1541                                                 auto param    = funcType->params.begin();
    1542                                                 auto paramEnd = funcType->params.end();
    1543 
    1544                                                 if( ! nextMutex( param, paramEnd ) ) {
    1545                                                         SemanticError( stmt->location, funcType,
    1546                                                                 "candidate function not viable: no mutex parameters\n");
    1547                                                 }
    1548                                         }
    1549 
    1550                                         CandidateRef func2{ new Candidate{ *func } };
    1551                                         // strip reference from function
    1552                                         func2->expr = referenceToRvalueConversion( func->expr, func2->cost );
    1553 
    1554                                         // Each argument must be matched with a parameter of the current candidate
    1555                                         for ( auto & argsList : possibilities ) {
    1556                                                 try {
    1557                                                         // Declare data structures needed for resolution
    1558                                                         ast::OpenVarSet open;
    1559                                                         ast::AssertionSet need, have;
    1560                                                         ast::TypeEnvironment resultEnv{ func->env };
    1561                                                         // Add all type variables as open so that those not used in the
    1562                                                         // parameter list are still considered open
    1563                                                         resultEnv.add( funcType->forall );
    1564 
    1565                                                         // load type variables from arguments into one shared space
    1566                                                         for ( auto & arg : argsList ) {
    1567                                                                 resultEnv.simpleCombine( arg->env );
    1568                                                         }
    1569 
    1570                                                         // Make sure we don't widen any existing bindings
    1571                                                         resultEnv.forbidWidening();
    1572 
    1573                                                         // Find any unbound type variables
    1574                                                         resultEnv.extractOpenVars( open );
    1575 
    1576                                                         auto param = funcType->params.begin();
    1577                                                         auto paramEnd = funcType->params.end();
    1578 
    1579                                                         unsigned n_mutex_param = 0;
    1580 
    1581                                                         // For every argument of its set, check if it matches one of the
    1582                                                         // parameters. The order is important
    1583                                                         for ( auto & arg : argsList ) {
    1584                                                                 // Ignore non-mutex arguments
    1585                                                                 if ( ! nextMutex( param, paramEnd ) ) {
    1586                                                                         // We ran out of parameters but still have arguments.
    1587                                                                         // This function doesn't match
    1588                                                                         SemanticError( stmt->location, funcType,
    1589                                                                                 toString("candidate function not viable: too many mutex "
    1590                                                                                 "arguments, expected ", n_mutex_param, "\n" ) );
    1591                                                                 }
    1592 
    1593                                                                 ++n_mutex_param;
    1594 
    1595                                                                 // Check if the argument matches the parameter type in the current
    1596                                                                 // scope
    1597                                                                 ast::ptr< ast::Type > paramType = (*param)->get_type();
    1598                                                                 if (
    1599                                                                         ! unify(
    1600                                                                                 arg->expr->result, paramType, resultEnv, need, have, open,
    1601                                                                                 symtab )
    1602                                                                 ) {
    1603                                                                         // Type doesn't match
    1604                                                                         stringstream ss;
    1605                                                                         ss << "candidate function not viable: no known conversion "
    1606                                                                                 "from '";
    1607                                                                         ast::print( ss, (*param)->get_type() );
    1608                                                                         ss << "' to '";
    1609                                                                         ast::print( ss, arg->expr->result );
    1610                                                                         ss << "' with env '";
    1611                                                                         ast::print( ss, resultEnv );
    1612                                                                         ss << "'\n";
    1613                                                                         SemanticError( stmt->location, funcType, ss.str() );
    1614                                                                 }
    1615 
    1616                                                                 ++param;
    1617                                                         }
    1618 
    1619                                                         // All arguments match!
    1620 
    1621                                                         // Check if parameters are missing
    1622                                                         if ( nextMutex( param, paramEnd ) ) {
    1623                                                                 do {
    1624                                                                         ++n_mutex_param;
    1625                                                                         ++param;
    1626                                                                 } while ( nextMutex( param, paramEnd ) );
    1627 
    1628                                                                 // We ran out of arguments but still have parameters left; this
    1629                                                                 // function doesn't match
    1630                                                                 SemanticError( stmt->location, funcType,
    1631                                                                         toString( "candidate function not viable: too few mutex "
    1632                                                                         "arguments, expected ", n_mutex_param, "\n" ) );
    1633                                                         }
    1634 
    1635                                                         // All parameters match!
    1636 
    1637                                                         // Finish the expressions to tie in proper environments
    1638                                                         finishExpr( func2->expr, resultEnv );
    1639                                                         for ( CandidateRef & arg : argsList ) {
    1640                                                                 finishExpr( arg->expr, resultEnv );
    1641                                                         }
    1642 
    1643                                                         // This is a match, store it and save it for later
    1644                                                         funcCandidates.emplace_back( std::move( func2 ) );
    1645                                                         argsCandidates.emplace_back( std::move( argsList ) );
    1646 
    1647                                                 } catch ( SemanticErrorException & e ) {
    1648                                                         errors.append( e );
    1649                                                 }
    1650                                         }
    1651                                 } catch ( SemanticErrorException & e ) {
    1652                                         errors.append( e );
    1653                                 }
    1654                         }
    1655 
    1656                         // Make sure correct number of arguments
    1657                         if( funcCandidates.empty() ) {
    1658                                 SemanticErrorException top( stmt->location,
    1659                                         "No alternatives for function in call to waitfor" );
    1660                                 top.append( errors );
    1661                                 throw top;
    1662                         }
    1663 
    1664                         if( argsCandidates.empty() ) {
    1665                                 SemanticErrorException top( stmt->location,
    1666                                         "No alternatives for arguments in call to waitfor" );
    1667                                 top.append( errors );
    1668                                 throw top;
    1669                         }
    1670 
    1671                         if( funcCandidates.size() > 1 ) {
    1672                                 SemanticErrorException top( stmt->location,
    1673                                         "Ambiguous function in call to waitfor" );
    1674                                 top.append( errors );
    1675                                 throw top;
    1676                         }
    1677                         if( argsCandidates.size() > 1 ) {
    1678                                 SemanticErrorException top( stmt->location,
    1679                                         "Ambiguous arguments in call to waitfor" );
    1680                                 top.append( errors );
    1681                                 throw top;
    1682                         }
    1683                         // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    1684 
    1685                         // build new clause
    1686                         ast::WaitForStmt::Clause clause2;
    1687 
    1688                         clause2.target.func = funcCandidates.front()->expr;
    1689 
    1690                         clause2.target.args.reserve( clause.target.args.size() );
    1691                         for ( auto arg : argsCandidates.front() ) {
    1692                                 clause2.target.args.emplace_back( std::move( arg->expr ) );
    1693                         }
    1694 
    1695                         // Resolve the conditions as if it were an IfStmt, statements normally
    1696                         clause2.cond = findSingleExpression( clause.cond, symtab );
    1697                         clause2.stmt = clause.stmt->accept( *visitor );
    1698 
    1699                         // set results into stmt
    1700                         auto n = mutate( stmt );
    1701                         n->clauses[i] = std::move( clause2 );
    1702                         stmt = n;
    1703                 }
    1704 
    1705                 if ( stmt->timeout.stmt ) {
    1706                         // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
    1707                         ast::WaitForStmt::Timeout timeout2;
    1708 
    1709                         ast::ptr< ast::Type > target =
    1710                                 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
    1711                         timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab );
    1712                         timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab );
    1713                         timeout2.stmt = stmt->timeout.stmt->accept( *visitor );
    1714 
    1715                         // set results into stmt
    1716                         auto n = mutate( stmt );
    1717                         n->timeout = std::move( timeout2 );
    1718                         stmt = n;
    1719                 }
    1720 
    1721                 if ( stmt->orElse.stmt ) {
    1722                         // resolve the condition like IfStmt, stmts normally
    1723                         ast::WaitForStmt::OrElse orElse2;
    1724 
    1725                         orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab );
    1726                         orElse2.stmt = stmt->orElse.stmt->accept( *visitor );
    1727 
    1728                         // set results into stmt
    1729                         auto n = mutate( stmt );
    1730                         n->orElse = std::move( orElse2 );
    1731                         stmt = n;
    1732                 }
    1733 
    1734                 return stmt;
    1735         }
    1736 
    1737 
    1738 
    1739         const ast::SingleInit * Resolver_new::previsit( const ast::SingleInit * singleInit ) {
    1740                 visit_children = false;
    1741                 // resolve initialization using the possibilities as determined by the `currentObject`
    1742                 // cursor.
    1743                 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    1744                         singleInit->location, singleInit->value, currentObject.getOptions() };
    1745                 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
    1746                 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    1747 
    1748                 // move cursor to the object that is actually initialized
    1749                 currentObject.setNext( initExpr->designation );
    1750 
    1751                 // discard InitExpr wrapper and retain relevant pieces.
    1752                 // `initExpr` may have inferred params in the case where the expression specialized a
    1753                 // function pointer, and newExpr may already have inferParams of its own, so a simple
    1754                 // swap is not sufficient
    1755                 ast::Expr::InferUnion inferred = initExpr->inferred;
    1756                 swap_and_save_env( newExpr, initExpr->expr );
    1757                 newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );
    1758 
    1759                 // get the actual object's type (may not exactly match what comes back from the resolver
    1760                 // due to conversions)
    1761                 const ast::Type * initContext = currentObject.getCurrentType();
    1762 
    1763                 removeExtraneousCast( newExpr, symtab );
    1764 
    1765                 // check if actual object's type is char[]
    1766                 if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {
    1767                         if ( isCharType( at->base ) ) {
    1768                                 // check if the resolved type is char*
    1769                                 if ( auto pt = newExpr->result.as< ast::PointerType >() ) {
    1770                                         if ( isCharType( pt->base ) ) {
    1771                                                 // strip cast if we're initializing a char[] with a char*
    1772                                                 // e.g. char x[] = "hello"
    1773                                                 if ( auto ce = newExpr.as< ast::CastExpr >() ) {
    1774                                                         swap_and_save_env( newExpr, ce->arg );
    1775                                                 }
    1776                                         }
    1777                                 }
    1778                         }
    1779                 }
    1780 
    1781                 // move cursor to next object in preparation for next initializer
    1782                 currentObject.increment();
    1783 
    1784                 // set initializer expression to resolved expression
    1785                 return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );
    1786         }
    1787 
    1788         const ast::ListInit * Resolver_new::previsit( const ast::ListInit * listInit ) {
    1789                 // move cursor into brace-enclosed initializer-list
    1790                 currentObject.enterListInit( listInit->location );
    1791 
    1792                 assert( listInit->designations.size() == listInit->initializers.size() );
    1793                 for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {
    1794                         // iterate designations and initializers in pairs, moving the cursor to the current
    1795                         // designated object and resolving the initializer against that object
    1796                         listInit = ast::mutate_field_index(
    1797                                 listInit, &ast::ListInit::designations, i,
    1798                                 currentObject.findNext( listInit->designations[i] ) );
    1799                         listInit = ast::mutate_field_index(
    1800                                 listInit, &ast::ListInit::initializers, i,
    1801                                 listInit->initializers[i]->accept( *visitor ) );
    1802                 }
    1803 
    1804                 // move cursor out of brace-enclosed initializer-list
    1805                 currentObject.exitListInit();
    1806 
    1807                 visit_children = false;
    1808                 return listInit;
    1809         }
    1810 
    1811         const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {
    1812                 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );
    1813                 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );
    1814 
    1815                 // found a constructor - can get rid of C-style initializer
    1816                 // xxx - Rob suggests this field is dead code
    1817                 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );
    1818 
    1819                 // intrinsic single-parameter constructors and destructors do nothing. Since this was
    1820                 // implicitly generated, there's no way for it to have side effects, so get rid of it to
    1821                 // clean up generated code
    1822                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
    1823                         ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );
    1824                 }
    1825                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
    1826                         ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );
    1827                 }
    1828 
    1829                 return ctorInit;
    1830         }
    1831 
    1832876} // namespace ResolvExpr
    1833877
  • src/ResolvExpr/Resolver.h

    rb067d9b r7951100  
    1010// Created On       : Sun May 17 12:18:34 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Feb 18 20:40:38 2019
    13 // Update Count     : 4
     12// Last Modified On : Sat Jul 22 09:36:57 2017
     13// Update Count     : 3
    1414//
    1515
    1616#pragma once
    1717
    18 #include <list>          // for list
    19 
    20 #include "AST/Node.hpp"  // for ptr
     18#include <list>  // for list
    2119
    2220class ConstructorInit;
     
    2523class StmtExpr;
    2624namespace SymTab {
    27         class Indexer;
    28 } // namespace SymTab
    29 
    30 namespace ast {
    31         class ConstructorInit;
    32         class Decl;
    33         class DeletedExpr;
    34         class Init;
    35         class StmtExpr;
    36         class SymbolTable;
    37         class Type;
    38         class TypeEnvironment;
    39 } // namespace ast
     25class Indexer;
     26}  // namespace SymTab
    4027
    4128namespace ResolvExpr {
    4229        /// Checks types and binds syntactic constructs to typed representations
    4330        void resolve( std::list< Declaration * > translationUnit );
    44         void resolveDecl( Declaration *, const SymTab::Indexer & indexer );
    45         Expression *resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer );
    46         void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer );
    47         void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer );
    48         void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer );
     31        void resolveDecl( Declaration *, const SymTab::Indexer &indexer );
     32        Expression *resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer );
     33        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer );
     34        void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer );
     35        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer &indexer );
    4936        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    5037        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
    51         /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    52         DeletedExpr * findDeletedExpr( Expression * expr );
    53         /// Resolves with-stmts and with-clauses on functions
    54         void resolveWithExprs( std::list< Declaration * > & translationUnit );
    55 
    56         /// Checks types and binds syntactic constructs to typed representations
    57         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
    58         /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    59         const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr );
    60         /// Find the expression candidate that is the unique best match for `untyped` in a `void`
    61         /// context.
    62         ast::ptr< ast::Expr > resolveInVoidContext(
    63                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
    64         /// Resolve `untyped` to the single expression whose candidate is the best match for the
    65         /// given type.
    66         ast::ptr< ast::Expr > findSingleExpression(
    67                 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
    68         /// Resolves a constructor init expression
    69         ast::ptr< ast::Init > resolveCtorInit(
    70                 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
    71         /// Resolves a statement expression
    72         ast::ptr< ast::Expr > resolveStmtExpr(
    73                 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
    7438} // namespace ResolvExpr
    7539
  • src/ResolvExpr/TypeEnvironment.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:19:47 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 18 14:27:00 2019
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun May 17 12:23:36 2015
     13// Update Count     : 3
    1414//
    1515
     
    1717#include <algorithm>                   // for copy, set_intersection
    1818#include <iterator>                    // for ostream_iterator, insert_iterator
    19 #include <memory>                      // for unique_ptr
    2019#include <utility>                     // for pair, move
    2120
     
    2322#include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
    2423#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    25 #include "Tuples/Tuples.h"             // for isTtype
    2624#include "TypeEnvironment.h"
    27 #include "typeops.h"                   // for occurs
    28 #include "Unify.h"                     // for unifyInexact
    2925
    3026namespace ResolvExpr {
     
    6965        }
    7066
    71         EqvClass::EqvClass( EqvClass &&other )
    72         : vars{std::move(other.vars)}, type{other.type},
    73           allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} {
    74                   other.type = nullptr;
    75         }
    76 
    7767        EqvClass &EqvClass::operator=( const EqvClass &other ) {
    7868                if ( this == &other ) return *this;
     
    8272        }
    8373
    84         EqvClass &EqvClass::operator=( EqvClass &&other ) {
    85                 if ( this == &other ) return *this;
    86                 delete type;
    87 
    88                 vars = std::move(other.vars);
    89                 type = other.type;
    90                 other.type = nullptr;
    91                 allowWidening = std::move(other.allowWidening);
    92                 data = std::move(other.data);
    93 
    94                 return *this;
    95         }
    96 
    9774        EqvClass::~EqvClass() {
    9875                delete type;
    99         }
    100 
    101         void EqvClass::set_type( Type* ty ) {
    102                 if ( ty == type ) return;
    103                 delete type;
    104                 type = ty;
    10576        }
    10677
     
    12091
    12192        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    122                 for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {
    123                         if ( i->vars.find( var ) != i->vars.end() ) return &*i;
     93                for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
     94                        if ( i->vars.find( var ) != i->vars.end() ) {
     95///       std::cout << var << " is in class ";
     96///       i->print( std::cout );
     97                                return &*i;
     98                        }
     99///     std::cout << var << " is not in class ";
     100///     i->print( std::cout );
    124101                } // for
    125102                return nullptr;
     
    132109                        ++next;
    133110                        std::set<std::string> intersection;
    134                         std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(),
     111                        std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(), 
    135112                                std::inserter( intersection, intersection.begin() ) );
    136113                        if ( ! intersection.empty() ) { env.erase( i ); }
    137114                        i = next;
    138115                }
     116        }
     117
     118        void TypeEnvironment::add( const EqvClass &eqvClass ) {
     119                filterOverlappingClasses( env, eqvClass );
     120                env.push_back( eqvClass );
    139121        }
    140122
     
    149131                        newClass.vars.insert( (*i)->get_name() );
    150132                        newClass.data = TypeDecl::Data{ (*i) };
    151                         env.push_back( std::move(newClass) );
     133                        env.push_back( newClass );
    152134                } // for
    153135        }
     
    163145                        // transition to TypeSubstitution
    164146                        newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
    165                         add( std::move(newClass) );
     147                        add( newClass );
    166148                }
    167149        }
    168150
    169151        void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const {
    170                 for ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
     152                for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    171153                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
     154///       std::cerr << "adding " << *theVar;
    172155                                if ( theClass->type ) {
     156///         std::cerr << " bound to ";
     157///         theClass->type->print( std::cerr );
     158///         std::cerr << std::endl;
    173159                                        sub.add( *theVar, theClass->type );
    174160                                } else if ( theVar != theClass->vars.begin() ) {
    175161                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
     162///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
    176163                                        sub.add( *theVar, newTypeInst );
    177164                                        delete newTypeInst;
     
    179166                        } // for
    180167                } // for
     168///   std::cerr << "input env is:" << std::endl;
     169///   print( std::cerr, 8 );
     170///   std::cerr << "sub is:" << std::endl;
     171///   sub.print( std::cerr, 8 );
    181172                sub.normalize();
    182173        }
     
    188179        }
    189180
    190         TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
    191                 for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) {
    192                         if ( i->vars.count( var ) ) return i;
     181        std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
     182                for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {
     183                        if ( i->vars.find( var ) == i->vars.end() ) {
     184                                return i;
     185                        } // if
    193186                } // for
    194187                return env.end();
     
    199192        }
    200193
    201         // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
    202         bool TypeEnvironment::mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
    203                 if ( from.type ) {
    204                         if ( to.type ) {
    205                                 // attempt to unify bound types
    206                                 std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() };
    207                                 WidenMode widen{ to.allowWidening, from.allowWidening };
    208                                 Type* common = nullptr;
    209                                 AssertionSet need, have;
    210                                 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen, indexer, common ) ) {
    211                                         // unifies, set common type if necessary
    212                                         if ( common ) {
    213                                                 common->get_qualifiers() = Type::Qualifiers{};
    214                                                 to.set_type( common );
    215                                         }
    216                                 } else return false; // cannot unify
    217                         } else {
    218                                 to.type = from.type->clone();
    219                         }
    220                 }
    221 
    222                 // unify widening if matches
    223                 to.allowWidening &= from.allowWidening;
    224                 return true;
    225         }
    226 
    227         // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
    228         bool TypeEnvironment::mergeClasses( TypeEnvironment::ClassList::iterator to, TypeEnvironment::ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
    229                 EqvClass& r = *to;
    230                 EqvClass& s = *from;
    231 
    232                 // ensure bounds match
    233                 if ( ! mergeBound( r, s, openVars, indexer ) ) return false;
    234 
    235                 // check safely bindable
    236                 if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false;
    237                
    238                 // merge classes in
    239                 r.vars.insert( s.vars.begin(), s.vars.end() );
    240                 r.allowWidening &= s.allowWidening;
    241                 env.erase( from );
    242 
    243                 return true;
    244         }
    245 
    246         bool TypeEnvironment::combine( const TypeEnvironment& o, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
    247                 // short-circuit easy cases
    248                 if ( o.isEmpty() ) return true;
    249                 if ( isEmpty() ) {
    250                         simpleCombine( o );
    251                         return true;
    252                 }
    253 
    254                 // merge classes
    255                 for ( auto ct = o.env.begin(); ct != o.env.end(); ++ct ) {
    256                         const EqvClass& c = *ct;
    257 
    258                         // typeclass in local environment bound to c
    259                         auto rt = env.end();
    260 
    261                         // look for first existing bound variable
    262                         auto vt = c.vars.begin();
    263                         for ( ; vt != c.vars.end(); ++vt ) {
    264                                 rt = internal_lookup( *vt );
    265                                 if ( rt != env.end() ) break;
    266                         }
    267 
    268                         if ( rt != env.end() ) {  // c needs to be merged into *rt
    269                                 EqvClass& r = *rt;
    270                                 // merge bindings
    271                                 if ( ! mergeBound( r, c, openVars, indexer ) ) return false;
    272                                 // merge previous unbound variables into this class, checking occurs if needed
    273                                 if ( r.type ) for ( auto ut = c.vars.begin(); ut != vt; ++ut ) {
    274                                         if ( occurs( r.type, *ut, *this ) ) return false;
    275                                         r.vars.insert( *ut );
    276                                 } else { r.vars.insert( c.vars.begin(), vt ); }
    277                                 // merge subsequent variables into this class (skipping *vt, already there)
    278                                 while ( ++vt != c.vars.end() ) {
    279                                         auto st = internal_lookup( *vt );
    280                                         if ( st == env.end() ) {
    281                                                 // unbound, safe to add if passes occurs
    282                                                 if ( r.type && occurs( r.type, *vt, *this ) ) return false;
    283                                                 r.vars.insert( *vt );
    284                                         } else if ( st != rt ) {
    285                                                 // bound, but not to the same class
    286                                                 if ( ! mergeClasses( rt, st, openVars, indexer ) ) return false;
    287                                         }   // ignore bound into the same class
    288                                 }
    289                         } else {  // no variables in c bound; just copy up
    290                                 env.push_back( c );
    291                         }
    292                 }
    293 
    294                 // merged all classes
    295                 return true;
     194        void TypeEnvironment::combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ) {
     195                TypeEnvironment secondCopy( second );
     196                for ( std::list< EqvClass >::iterator firstClass = env.begin(); firstClass != env.end(); ++firstClass ) {
     197                        EqvClass &newClass = *firstClass;
     198                        std::set< std::string > newVars;
     199                        for ( std::set< std::string >::const_iterator var = firstClass->vars.begin(); var != firstClass->vars.end(); ++var ) {
     200                                std::list< EqvClass >::iterator secondClass = secondCopy.internal_lookup( *var );
     201                                if ( secondClass != secondCopy.env.end() ) {
     202                                        newVars.insert( secondClass->vars.begin(), secondClass->vars.end() );
     203                                        if ( secondClass->type ) {
     204                                                if ( newClass.type ) {
     205                                                        Type *newType = combineFunc( newClass.type, secondClass->type );
     206                                                        delete newClass.type;
     207                                                        newClass.type = newType;
     208                                                        newClass.allowWidening = newClass.allowWidening && secondClass->allowWidening;
     209                                                } else {
     210                                                        newClass.type = secondClass->type->clone();
     211                                                        newClass.allowWidening = secondClass->allowWidening;
     212                                                } // if
     213                                        } // if
     214                                        secondCopy.env.erase( secondClass );
     215                                } // if
     216                        } // for
     217                        newClass.vars.insert( newVars.begin(), newVars.end() );
     218                } // for
     219                for ( std::list< EqvClass >::iterator secondClass = secondCopy.env.begin(); secondClass != secondCopy.env.end(); ++secondClass ) {
     220                        env.push_back( *secondClass );
     221                } // for
    296222        }
    297223
    298224        void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const {
    299                 for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
     225                for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
    300226                        for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {
    301227                                openVars[ *var ] = eqvClass->data;
     
    315241        }
    316242
    317         bool isFtype( const Type * type ) {
    318                 if ( dynamic_cast< const FunctionType * >( type ) ) {
    319                         return true;
    320                 } else if ( const TypeInstType *typeInst = dynamic_cast< const TypeInstType * >( type ) ) {
    321                         return typeInst->get_isFtype();
    322                 } // if
    323                 return false;
    324         }
    325 
    326         bool tyVarCompatible( const TypeDecl::Data & data, const Type * type ) {
    327                 switch ( data.kind ) {
    328                   case TypeDecl::Dtype:
    329                         // to bind to an object type variable, the type must not be a function type.
    330                         // if the type variable is specified to be a complete type then the incoming
    331                         // type must also be complete
    332                         // xxx - should this also check that type is not a tuple type and that it's not a ttype?
    333                         return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
    334                   case TypeDecl::Ftype:
    335                         return isFtype( type );
    336                   case TypeDecl::Ttype:
    337                         // ttype unifies with any tuple type
    338                         return dynamic_cast< const TupleType * >( type ) || Tuples::isTtype( type );
    339                   default:
    340                         assertf(false, "Unhandled tyvar kind: %d", data.kind);
    341                 } // switch
    342                 return false;
    343         }
    344 
    345         bool TypeEnvironment::bindVar( const TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    346 
    347                 // remove references from other, so that type variables can only bind to value types
    348                 bindTo = bindTo->stripReferences();
    349                 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    350                 assert( tyvar != openVars.end() );
    351                 if ( ! tyVarCompatible( tyvar->second, bindTo ) ) {
    352                         return false;
    353                 } // if
    354                 if ( occurs( bindTo, typeInst->get_name(), *this ) ) {
    355                         return false;
    356                 } // if
    357                 auto curClass = internal_lookup( typeInst->get_name() );
    358                 if ( curClass != env.end() ) {
    359                         if ( curClass->type ) {
    360                                 Type *common = 0;
    361                                 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
    362                                 std::unique_ptr< Type > newType( curClass->type->clone() );
    363                                 newType->tq = typeInst->tq;
    364                                 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
    365                                         if ( common ) {
    366                                                 common->get_qualifiers() = Type::Qualifiers{};
    367                                                 curClass->set_type( common );
    368                                         } // if
    369                                 } else return false;
    370                         } else {
    371                                 Type* newType = bindTo->clone();
    372                                 newType->get_qualifiers() = Type::Qualifiers{};
    373                                 curClass->set_type( newType );
    374                                 curClass->allowWidening = widen.first && widen.second;
    375                         } // if
    376                 } else {
    377                         EqvClass newClass;
    378                         newClass.vars.insert( typeInst->get_name() );
    379                         newClass.type = bindTo->clone();
    380                         newClass.type->get_qualifiers() = Type::Qualifiers();
    381                         newClass.allowWidening = widen.first && widen.second;
    382                         newClass.data = data;
    383                         env.push_back( std::move(newClass) );
    384                 } // if
    385                 return true;
    386         }
    387 
    388         bool TypeEnvironment::bindVarToVar( const TypeInstType * var1, const TypeInstType * var2,
    389                         TypeDecl::Data && data, AssertionSet &need, AssertionSet &have,
    390                         const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    391 
    392                 auto class1 = internal_lookup( var1->get_name() );
    393                 auto class2 = internal_lookup( var2->get_name() );
    394 
    395                 // exit early if variables already bound together
    396                 if ( class1 != env.end() && class1 == class2 ) {
    397                         class1->allowWidening &= widen;
    398                         return true;
    399                 }
    400 
    401                 bool widen1 = false, widen2 = false;
    402                 const Type *type1 = nullptr, *type2 = nullptr;
    403 
    404                 // check for existing bindings, perform occurs check
    405                 if ( class1 != env.end() ) {
    406                         if ( class1->type ) {
    407                                 if ( occurs( class1->type, var2->get_name(), *this ) ) return false;
    408                                 type1 = class1->type;
    409                         } // if
    410                         widen1 = widen.first && class1->allowWidening;
    411                 } // if
    412                 if ( class2 != env.end() ) {
    413                         if ( class2->type ) {
    414                                 if ( occurs( class2->type, var1->get_name(), *this ) ) return false;
    415                                 type2 = class2->type;
    416                         } // if
    417                         widen2 = widen.second && class2->allowWidening;
    418                 } // if
    419 
    420                 if ( type1 && type2 ) {
    421                         // both classes bound, merge if bound types can be unified
    422                         std::unique_ptr<Type> newType1{ type1->clone() }, newType2{ type2->clone() };
    423                         WidenMode newWidenMode{ widen1, widen2 };
    424                         Type *common = 0;
    425                         if ( unifyInexact( newType1.get(), newType2.get(), *this, need, have, openVars, newWidenMode, indexer, common ) ) {
    426                                 class1->vars.insert( class2->vars.begin(), class2->vars.end() );
    427                                 class1->allowWidening = widen1 && widen2;
    428                                 if ( common ) {
    429                                         common->get_qualifiers() = Type::Qualifiers{};
    430                                         class1->set_type( common );
    431                                 }
    432                                 class1->data.isComplete |= data.isComplete;
    433                                 env.erase( class2 );
    434                         } else return false;
    435                 } else if ( class1 != env.end() && class2 != env.end() ) {
    436                         // both classes exist, at least one unbound, merge unconditionally
    437                         if ( type1 ) {
    438                                 class1->vars.insert( class2->vars.begin(), class2->vars.end() );
    439                                 class1->allowWidening = widen1;
    440                                 class1->data.isComplete |= data.isComplete;
    441                                 env.erase( class2 );
    442                         } else {
    443                                 class2->vars.insert( class1->vars.begin(), class1->vars.end() );
    444                                 class2->allowWidening = widen2;
    445                                 class2->data.isComplete |= data.isComplete;
    446                                 env.erase( class1 );
    447                         } // if
    448                 } else if ( class1 != env.end() ) {
    449                         // var2 unbound, add to class1
    450                         class1->vars.insert( var2->get_name() );
    451                         class1->allowWidening = widen1;
    452                         class1->data.isComplete |= data.isComplete;
    453                 } else if ( class2 != env.end() ) {
    454                         // var1 unbound, add to class2
    455                         class2->vars.insert( var1->get_name() );
    456                         class2->allowWidening = widen2;
    457                         class2->data.isComplete |= data.isComplete;
    458                 } else {
    459                         // neither var bound, create new class
    460                         EqvClass newClass;
    461                         newClass.vars.insert( var1->get_name() );
    462                         newClass.vars.insert( var2->get_name() );
    463                         newClass.allowWidening = widen1 && widen2;
    464                         newClass.data = data;
    465                         env.push_back( std::move(newClass) );
    466                 } // if
    467                 return true;
    468         }
    469 
    470         void TypeEnvironment::forbidWidening() {
    471                 for ( EqvClass& c : env ) c.allowWidening = false;
    472         }
    473 
    474243        std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {
    475244                env.print( out );
  • src/ResolvExpr/TypeEnvironment.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:24:58 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 19 17:00:10 2019
    13 // Update Count     : 10
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:35:45 2017
     13// Update Count     : 3
    1414//
    1515
     
    1818#include <iostream>                    // for ostream
    1919#include <list>                        // for list, list<>::iterator, list<>...
    20 #include <map>                                             // for map, map<>::value_compare
    21 #include <unordered_map>
    22 #include <set>                                             // for set
     20#include <map>                         // for map, map<>::value_compare
     21#include <set>                         // for set
    2322#include <string>                      // for string
    24 #include <utility>                     // for move, swap
    25 
    26 #include "WidenMode.h"                 // for WidenMode
    2723
    2824#include "SynTree/Declaration.h"       // for TypeDecl::Data, DeclarationWit...
     
    4036        // declarations.
    4137        //
    42         // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
    43         // comparator.
     38        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
    4439        //
    4540        // Note: since this compares pointers for position, minor changes in the source file that affect
    4641        // memory layout can alter compilation time in unpredictable ways. For example, the placement
    4742        // of a line directive can reorder type pointers with respect to each other so that assertions
    48         // are seen in different orders, causing a potentially different number of unification calls
    49         // when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering
    50         // line directives alone, so it would be nice to fix this comparison so that assertions compare
    51         // more consistently. I've tried to modify this to compare on mangle name instead of type as
    52         // the second comparator, but this causes some assertions to never be recorded. More
    53         // investigation is needed.
     43        // are seen in different orders, causing a potentially different number of unification calls when
     44        // resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering line directives
     45        // alone, so it would be nice to fix this comparison so that assertions compare more consistently.
     46        // I've tried to modify this to compare on mangle name instead of type as the second comparator, but
     47        // this causes some assertions to never be recorded. More investigation is needed.
    5448        struct AssertCompare {
    55                 bool operator()( const DeclarationWithType * d1, const DeclarationWithType * d2 ) const {
     49                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
    5650                        int cmp = d1->get_name().compare( d2->get_name() );
    5751                        return cmp < 0 ||
     
    6054        };
    6155        struct AssertionSetValue {
    62                 bool isUsed;        ///< True if assertion needs to be resolved
    63                 UniqueId resnSlot;  ///< ID of slot assertion belongs to
    64 
    65                 AssertionSetValue() : isUsed(false), resnSlot(0) {}
     56                bool isUsed;
     57                // chain of Unique IDs of the assertion declarations. The first ID in the chain is the ID of an assertion on the current type,
     58                // with each successive ID being the ID of an assertion pulled in by the previous ID. The last ID in the chain is
     59                // the ID of the assertion that pulled in the current assertion.
     60                std::list< UniqueId > idChain;
    6661        };
    67         typedef std::map< const DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet;
    68         typedef std::unordered_map< std::string, TypeDecl::Data > OpenVarSet;
    69 
    70         /// merges one set of open vars into another
    71         static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) {
    72                 for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; }
    73         }
     62        typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet;
     63        typedef std::map< std::string, TypeDecl::Data > OpenVarSet;
    7464
    7565        void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 );
     
    7868        struct EqvClass {
    7969                std::set< std::string > vars;
    80                 Type * type;
     70                Type *type;
    8171                bool allowWidening;
    8272                TypeDecl::Data data;
     
    8777                EqvClass( const EqvClass &other );
    8878                EqvClass( const EqvClass &other, const Type *ty );
    89                 EqvClass( EqvClass &&other );
    9079                EqvClass &operator=( const EqvClass &other );
    91                 EqvClass &operator=( EqvClass &&other );
    9280                ~EqvClass();
    9381                void print( std::ostream &os, Indenter indent = {} ) const;
    94 
    95                 /// Takes ownership of `ty`, freeing old `type`
    96                 void set_type(Type* ty);
    9782        };
    9883
    9984        class TypeEnvironment {
    100                 using ClassList = std::list< EqvClass >;
    10185          public:
    10286                const EqvClass* lookup( const std::string &var ) const;
    103           private:
     87                void add( const EqvClass &eqvClass );
    10488                void add( EqvClass &&eqvClass  );
    105           public:
    10689                void add( const Type::ForallList &tyDecls );
    10790                void add( const TypeSubstitution & sub );
     
    11194                bool isEmpty() const { return env.empty(); }
    11295                void print( std::ostream &os, Indenter indent = {} ) const;
    113 
    114                 /// Simply concatenate the second environment onto this one; no safety checks performed
     96                void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
    11597                void simpleCombine( const TypeEnvironment &second );
    116 
    117           private:
    118                 /// Unifies the type bound of to with the type bound of from, returning false if fails
    119                 bool mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
    120 
    121                 /// Merges two type classes from local environment, returning false if fails
    122                 bool mergeClasses( ClassList::iterator to, ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
    123 
    124           public:
    125                 /// Merges the second environment with this one, checking compatibility.
    126                 /// Returns false if fails, but does NOT roll back partial changes.
    127                 bool combine( const TypeEnvironment& second, OpenVarSet& openVars, const SymTab::Indexer& indexer );
    128 
    12998                void extractOpenVars( OpenVarSet &openVars ) const;
    13099                TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
     
    134103                void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
    135104
    136                 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add
    137                 /// the class if needed. Returns false on failure.
    138                 bool bindVar( const TypeInstType * typeInst, Type * bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    139 
    140                 /// Binds the type classes represented by `var1` and `var2` together; will add
    141                 /// one or both classes if needed. Returns false on failure.
    142                 bool bindVarToVar( const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    143 
    144                 /// Disallows widening for all bindings in the environment
    145                 void forbidWidening();
    146 
    147                 using iterator = ClassList::const_iterator;
    148                 iterator begin() const { return env.begin(); }
    149                 iterator end() const { return env.end(); }
    150 
     105                typedef std::list< EqvClass >::iterator iterator;
     106                iterator begin() { return env.begin(); }
     107                iterator end() { return env.end(); }
     108                typedef std::list< EqvClass >::const_iterator const_iterator;
     109                const_iterator begin() const { return env.begin(); }
     110                const_iterator end() const { return env.end(); }
    151111          private:
    152                 ClassList env;
    153 
    154                 ClassList::iterator internal_lookup( const std::string &var );
     112                std::list< EqvClass > env;
     113                std::list< EqvClass >::iterator internal_lookup( const std::string &var );
    155114        };
    156115
  • src/ResolvExpr/Unify.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Sep  4 10:00:00 2019
    13 // Update Count     : 44
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Mar 16 16:22:54 2017
     13// Update Count     : 42
    1414//
    1515
     16#include <cassert>                // for assertf, assert
     17#include <iterator>               // for back_insert_iterator, back_inserter
     18#include <map>                    // for _Rb_tree_const_iterator, _Rb_tree_i...
     19#include <memory>                 // for unique_ptr
     20#include <set>                    // for set
     21#include <string>                 // for string, operator==, operator!=, bas...
     22#include <utility>                // for pair, move
     23
     24#include "Common/PassVisitor.h"   // for PassVisitor
     25#include "FindOpenVars.h"         // for findOpenVars
     26#include "Parser/LinkageSpec.h"   // for C
     27#include "SynTree/Constant.h"     // for Constant
     28#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data, Declarati...
     29#include "SynTree/Expression.h"   // for TypeExpr, Expression, ConstantExpr
     30#include "SynTree/Mutator.h"      // for Mutator
     31#include "SynTree/Type.h"         // for Type, TypeInstType, FunctionType
     32#include "SynTree/Visitor.h"      // for Visitor
     33#include "Tuples/Tuples.h"        // for isTtype
     34#include "TypeEnvironment.h"      // for EqvClass, AssertionSet, OpenVarSet
    1635#include "Unify.h"
    17 
    18 #include <cassert>                  // for assertf, assert
    19 #include <iterator>                 // for back_insert_iterator, back_inserter
    20 #include <map>                      // for _Rb_tree_const_iterator, _Rb_tree_i...
    21 #include <memory>                   // for unique_ptr
    22 #include <set>                      // for set
    23 #include <string>                   // for string, operator==, operator!=, bas...
    24 #include <utility>                  // for pair, move
    25 #include <vector>
    26 
    27 #include "AST/Decl.hpp"
    28 #include "AST/Node.hpp"
    29 #include "AST/Pass.hpp"
    30 #include "AST/Type.hpp"
    31 #include "AST/TypeEnvironment.hpp"
    32 #include "Common/PassVisitor.h"     // for PassVisitor
    33 #include "FindOpenVars.h"           // for findOpenVars
    34 #include "Parser/LinkageSpec.h"     // for C
    35 #include "SynTree/Constant.h"       // for Constant
    36 #include "SynTree/Declaration.h"    // for TypeDecl, TypeDecl::Data, Declarati...
    37 #include "SynTree/Expression.h"     // for TypeExpr, Expression, ConstantExpr
    38 #include "SynTree/Mutator.h"        // for Mutator
    39 #include "SynTree/Type.h"           // for Type, TypeInstType, FunctionType
    40 #include "SynTree/Visitor.h"        // for Visitor
    41 #include "Tuples/Tuples.h"          // for isTtype
    42 #include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
    43 #include "typeops.h"                // for flatten, occurs, commonType
    44 
    45 namespace ast {
    46         class SymbolTable;
    47 }
     36#include "typeops.h"              // for flatten, occurs, commonType
    4837
    4938namespace SymTab {
     
    5544namespace ResolvExpr {
    5645
    57         struct Unify_old : public WithShortCircuiting {
    58                 Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
     46        struct Unify : public WithShortCircuiting {
     47                Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    5948
    6049                bool get_result() const { return result; }
     
    8877                AssertionSet &haveAssertions;
    8978                const OpenVarSet &openVars;
    90                 WidenMode widen;
     79                WidenMode widenMode;
    9180                const SymTab::Indexer &indexer;
    9281        };
     
    9483        /// Attempts an inexact unification of type1 and type2.
    9584        /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
    96         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    97         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    98 
    99         bool unifyExact(
    100                 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    101                 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    102                 WidenMode widen, const ast::SymbolTable & symtab );
    103 
    104         bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     85        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
     86        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     87
     88        bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    10589                TypeEnvironment newEnv;
    10690                OpenVarSet openVars, closedVars; // added closedVars
    10791                AssertionSet needAssertions, haveAssertions;
    108                 Type * newFirst = first->clone(), * newSecond = second->clone();
     92                Type *newFirst = first->clone(), *newSecond = second->clone();
    10993                env.apply( newFirst );
    11094                env.apply( newSecond );
     
    121105        }
    122106
    123         bool typesCompatible(
    124                         const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
    125                         const ast::TypeEnvironment & env ) {
    126                 ast::TypeEnvironment newEnv;
    127                 ast::OpenVarSet open, closed;
    128                 ast::AssertionSet need, have;
    129 
    130                 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
    131                 env.apply( newFirst );
    132                 env.apply( newSecond );
    133 
    134                 findOpenVars( newFirst, open, closed, need, have, FirstClosed );
    135                 findOpenVars( newSecond, open, closed, need, have, FirstOpen );
    136 
    137                 return unifyExact(
    138                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    139         }
    140 
    141         bool typesCompatibleIgnoreQualifiers( const Type * first, const Type * second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     107        bool typesCompatibleIgnoreQualifiers( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    142108                TypeEnvironment newEnv;
    143109                OpenVarSet openVars;
     
    163129        }
    164130
    165         bool typesCompatibleIgnoreQualifiers(
    166                         const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
    167                         const ast::TypeEnvironment & env ) {
    168                 ast::TypeEnvironment newEnv;
    169                 ast::OpenVarSet open;
    170                 ast::AssertionSet need, have;
    171 
    172                 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
    173                 env.apply( newFirst );
    174                 env.apply( newSecond );
    175                 reset_qualifiers( newFirst );
    176                 reset_qualifiers( newSecond );
    177 
    178                 return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     131        bool isFtype( Type *type ) {
     132                if ( dynamic_cast< FunctionType* >( type ) ) {
     133                        return true;
     134                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
     135                        return typeInst->get_isFtype();
     136                } // if
     137                return false;
     138        }
     139
     140        bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
     141                switch ( data.kind ) {
     142                  case TypeDecl::Dtype:
     143                        // to bind to an object type variable, the type must not be a function type.
     144                        // if the type variable is specified to be a complete type then the incoming
     145                        // type must also be complete
     146                        // xxx - should this also check that type is not a tuple type and that it's not a ttype?
     147                        return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
     148                  case TypeDecl::Ftype:
     149                        return isFtype( type );
     150                  case TypeDecl::Ttype:
     151                        // ttype unifies with any tuple type
     152                        return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
     153                } // switch
     154                return false;
     155        }
     156
     157        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     158                // remove references from other, so that type variables can only bind to value types
     159                other = other->stripReferences();
     160                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
     161                assert( tyvar != openVars.end() );
     162                if ( ! tyVarCompatible( tyvar->second, other ) ) {
     163                        return false;
     164                } // if
     165                if ( occurs( other, typeInst->get_name(), env ) ) {
     166                        return false;
     167                } // if
     168                if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) {
     169                        if ( curClass->type ) {
     170                                Type *common = 0;
     171                                // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
     172                                std::unique_ptr< Type > newType( curClass->type->clone() );
     173                                newType->get_qualifiers() = typeInst->get_qualifiers();
     174                                if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
     175                                        if ( common ) {
     176                                                common->get_qualifiers() = Type::Qualifiers();
     177                                                env.add( EqvClass{ *curClass, common } );
     178                                        } // if
     179                                        return true;
     180                                } else {
     181                                        return false;
     182                                } // if
     183                        } else {
     184                                EqvClass newClass { *curClass, other };
     185                                newClass.type->get_qualifiers() = Type::Qualifiers();
     186                                newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     187                                env.add( std::move(newClass) );
     188                        } // if
     189                } else {
     190                        EqvClass newClass;
     191                        newClass.vars.insert( typeInst->get_name() );
     192                        newClass.type = other->clone();
     193                        newClass.type->get_qualifiers() = Type::Qualifiers();
     194                        newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     195                        newClass.data = data;
     196                        env.add( newClass );
     197                } // if
     198                return true;
     199        }
     200
     201        bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     202                bool result = true;
     203                const EqvClass *class1 = env.lookup( var1->get_name() );
     204                const EqvClass *class2 = env.lookup( var2->get_name() );
     205                bool widen1 = false, widen2 = false;
     206                Type *type1 = nullptr, *type2 = nullptr;
     207
     208                if ( class1 ) {
     209                        if ( class1->type ) {
     210                                if ( occurs( class1->type, var2->get_name(), env ) ) {
     211                                        return false;
     212                                } // if
     213                                type1 = class1->type->clone();
     214                        } // if
     215                        widen1 = widenMode.widenFirst && class1->allowWidening;
     216                } // if
     217                if ( class2 ) {
     218                        if ( class2->type ) {
     219                                if ( occurs( class2->type, var1->get_name(), env ) ) {
     220                                        return false;
     221                                } // if
     222                                type2 = class2->type->clone();
     223                        } // if
     224                        widen2 = widenMode.widenSecond && class2->allowWidening;
     225                } // if
     226
     227                if ( type1 && type2 ) {
     228//    std::cerr << "has type1 && type2" << std::endl;
     229                        WidenMode newWidenMode ( widen1, widen2 );
     230                        Type *common = 0;
     231                        if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
     232                                EqvClass newClass1 = *class1;
     233                                newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
     234                                newClass1.allowWidening = widen1 && widen2;
     235                                if ( common ) {
     236                                        common->get_qualifiers() = Type::Qualifiers();
     237                                        delete newClass1.type;
     238                                        newClass1.type = common;
     239                                } // if
     240                                env.add( std::move(newClass1) );
     241                        } else {
     242                                result = false;
     243                        } // if
     244                } else if ( class1 && class2 ) {
     245                        if ( type1 ) {
     246                                EqvClass newClass1 = *class1;
     247                                newClass1.vars.insert( class2->vars.begin(), class2->vars.end() );
     248                                newClass1.allowWidening = widen1;
     249                                env.add( std::move(newClass1) );
     250                        } else {
     251                                EqvClass newClass2 = *class2;
     252                                newClass2.vars.insert( class1->vars.begin(), class1->vars.end() );
     253                                newClass2.allowWidening = widen2;
     254                                env.add( std::move(newClass2) );
     255                        } // if
     256                } else if ( class1 ) {
     257                        EqvClass newClass1 = *class1;
     258                        newClass1.vars.insert( var2->get_name() );
     259                        newClass1.allowWidening = widen1;
     260                        env.add( std::move(newClass1) );
     261                } else if ( class2 ) {
     262                        EqvClass newClass2 = *class2;
     263                        newClass2.vars.insert( var1->get_name() );
     264                        newClass2.allowWidening = widen2;
     265                        env.add( std::move(newClass2) );
     266                } else {
     267                        EqvClass newClass;
     268                        newClass.vars.insert( var1->get_name() );
     269                        newClass.vars.insert( var2->get_name() );
     270                        newClass.allowWidening = widen1 && widen2;
     271                        newClass.data = data;
     272                        env.add( newClass );
     273                } // if
     274                delete type1;
     275                delete type2;
     276                return result;
    180277        }
    181278
     
    202299        }
    203300
    204         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
     301        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    205302#ifdef DEBUG
    206303                TypeEnvironment debugEnv( env );
     
    223320                bool isopen2 = var2 && ( entry2 != openVars.end() );
    224321
    225                 if ( isopen1 && isopen2 ) {
    226                         if ( entry1->second.kind != entry2->second.kind ) {
    227                                 result = false;
    228                         } else {
    229                                 result = env.bindVarToVar(
    230                                         var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions,
    231                                         haveAssertions, openVars, widen, indexer );
    232                         }
     322                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
     323                        result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    233324                } else if ( isopen1 ) {
    234                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer );
    235                 } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped?
    236                         result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer );
     325                        result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     326                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
     327                        result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    237328                } else {
    238                         PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );
     329                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    239330                        type1->accept( comparator );
    240331                        result = comparator.pass.get_result();
     
    261352        }
    262353
    263         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) {
     354        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ) {
    264355                Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
    265356                type1->get_qualifiers() = Type::Qualifiers();
     
    273364                std::cerr << std::endl;
    274365#endif
    275                 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) {
     366                if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) {
    276367#ifdef DEBUG
    277368                        std::cerr << "unifyInexact: no exact unification found" << std::endl;
    278369#endif
    279                         if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) {
    280                                 common->tq = tq1.unify( tq2 );
     370                        if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
     371                                common->get_qualifiers() = tq1 | tq2;
    281372#ifdef DEBUG
    282373                                std::cerr << "unifyInexact: common type is ";
     
    293384                } else {
    294385                        if ( tq1 != tq2 ) {
    295                                 if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) {
     386                                if ( ( tq1 > tq2 || widenMode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {
    296387                                        common = type1->clone();
    297                                         common->tq = tq1.unify( tq2 );
     388                                        common->get_qualifiers() = tq1 | tq2;
    298389                                        result = true;
    299390                                } else {
     
    302393                        } else {
    303394                                common = type1->clone();
    304                                 common->tq = tq1.unify( tq2 );
     395                                common->get_qualifiers() = tq1 | tq2;
    305396                                result = true;
    306397                        } // if
     
    311402        }
    312403
    313         Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer )
    314                 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) {
    315         }
    316 
    317         void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) {
     404        Unify::Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )
     405                : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widenMode( widenMode ), indexer( indexer ) {
     406        }
     407
     408        void Unify::postvisit( __attribute__((unused)) VoidType *voidType) {
    318409                result = dynamic_cast< VoidType* >( type2 );
    319410        }
    320411
    321         void Unify_old::postvisit(BasicType *basicType) {
     412        void Unify::postvisit(BasicType *basicType) {
    322413                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    323414                        result = basicType->get_kind() == otherBasic->get_kind();
     
    347438        }
    348439
    349         void Unify_old::postvisit(PointerType *pointerType) {
     440        void Unify::postvisit(PointerType *pointerType) {
    350441                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    351442                        result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    355446        }
    356447
    357         void Unify_old::postvisit(ReferenceType *refType) {
     448        void Unify::postvisit(ReferenceType *refType) {
    358449                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    359450                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    363454        }
    364455
    365         void Unify_old::postvisit(ArrayType *arrayType) {
     456        void Unify::postvisit(ArrayType *arrayType) {
    366457                ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    367458                // to unify, array types must both be VLA or both not VLA
     
    443534        /// If this isn't done then argument lists can have wildly different
    444535        /// size and structure, when they should be compatible.
    445         struct TtypeExpander_old : public WithShortCircuiting {
     536        struct TtypeExpander : public WithShortCircuiting {
    446537                TypeEnvironment & tenv;
    447                 TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {}
     538                TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {}
    448539                void premutate( TypeInstType * ) { visit_children = false; }
    449540                Type * postmutate( TypeInstType * typeInst ) {
     
    464555                dst.clear();
    465556                for ( DeclarationWithType * dcl : src ) {
    466                         PassVisitor<TtypeExpander_old> expander( env );
     557                        PassVisitor<TtypeExpander> expander( env );
    467558                        dcl->acceptMutator( expander );
    468559                        std::list< Type * > types;
     
    479570        }
    480571
    481         void Unify_old::postvisit(FunctionType *functionType) {
     572        void Unify::postvisit(FunctionType *functionType) {
    482573                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    483574                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
     
    490581
    491582                        // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    492                         if (
    493                                         (flatFunc->parameters.size() == flatOther->parameters.size() &&
    494                                                 flatFunc->returnVals.size() == flatOther->returnVals.size())
    495                                         || flatFunc->isTtype()
    496                                         || flatOther->isTtype()
    497                         ) {
     583                        if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
    498584                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    499585                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     
    511597
    512598        template< typename RefType >
    513         void Unify_old::handleRefType( RefType *inst, Type *other ) {
     599        void Unify::handleRefType( RefType *inst, Type *other ) {
    514600                // check that other type is compatible and named the same
    515601                RefType *otherStruct = dynamic_cast< RefType* >( other );
     
    518604
    519605        template< typename RefType >
    520         void Unify_old::handleGenericRefType( RefType *inst, Type *other ) {
     606        void Unify::handleGenericRefType( RefType *inst, Type *other ) {
    521607                // Check that other type is compatible and named the same
    522608                handleRefType( inst, other );
     
    586672        }
    587673
    588         void Unify_old::postvisit(StructInstType *structInst) {
     674        void Unify::postvisit(StructInstType *structInst) {
    589675                handleGenericRefType( structInst, type2 );
    590676        }
    591677
    592         void Unify_old::postvisit(UnionInstType *unionInst) {
     678        void Unify::postvisit(UnionInstType *unionInst) {
    593679                handleGenericRefType( unionInst, type2 );
    594680        }
    595681
    596         void Unify_old::postvisit(EnumInstType *enumInst) {
     682        void Unify::postvisit(EnumInstType *enumInst) {
    597683                handleRefType( enumInst, type2 );
    598684        }
    599685
    600         void Unify_old::postvisit(TraitInstType *contextInst) {
     686        void Unify::postvisit(TraitInstType *contextInst) {
    601687                handleRefType( contextInst, type2 );
    602688        }
    603689
    604         void Unify_old::postvisit(TypeInstType *typeInst) {
     690        void Unify::postvisit(TypeInstType *typeInst) {
    605691                assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    606692                TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
     
    657743        }
    658744
    659         void Unify_old::postvisit(TupleType *tupleType) {
     745        void Unify::postvisit(TupleType *tupleType) {
    660746                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    661747                        std::unique_ptr<TupleType> flat1( tupleType->clone() );
     
    663749                        std::list<Type *> types1, types2;
    664750
    665                         PassVisitor<TtypeExpander_old> expander( env );
     751                        PassVisitor<TtypeExpander> expander( env );
    666752                        flat1->acceptMutator( expander );
    667753                        flat2->acceptMutator( expander );
     
    674760        }
    675761
    676         void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
     762        void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    677763                result = dynamic_cast< VarArgsType* >( type2 );
    678764        }
    679765
    680         void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
     766        void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    681767                result = dynamic_cast< ZeroType* >( type2 );
    682768        }
    683769
    684         void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) {
     770        void Unify::postvisit( __attribute__((unused)) OneType *oneType ) {
    685771                result = dynamic_cast< OneType* >( type2 );
    686772        }
    687773
     774        // xxx - compute once and store in the FunctionType?
    688775        Type * extractResultType( FunctionType * function ) {
    689776                if ( function->get_returnVals().size() == 0 ) {
     
    699786                }
    700787        }
    701 
    702         class Unify_new final : public ast::WithShortCircuiting {
    703                 const ast::Type * type2;
    704                 ast::TypeEnvironment & tenv;
    705                 ast::AssertionSet & need;
    706                 ast::AssertionSet & have;
    707                 const ast::OpenVarSet & open;
    708                 WidenMode widen;
    709                 const ast::SymbolTable & symtab;
    710         public:
    711                 bool result;
    712 
    713                 Unify_new(
    714                         const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
    715                         ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,
    716                         const ast::SymbolTable & symtab )
    717                 : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),
    718                   symtab(symtab), result(false) {}
    719 
    720                 void previsit( const ast::Node * ) { visit_children = false; }
    721 
    722                 void postvisit( const ast::VoidType * ) {
    723                         result = dynamic_cast< const ast::VoidType * >( type2 );
    724                 }
    725 
    726                 void postvisit( const ast::BasicType * basic ) {
    727                         if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {
    728                                 result = basic->kind == basic2->kind;
    729                         }
    730                 }
    731 
    732                 void postvisit( const ast::PointerType * pointer ) {
    733                         if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
    734                                 result = unifyExact(
    735                                         pointer->base, pointer2->base, tenv, need, have, open,
    736                                         noWiden(), symtab );
    737                         }
    738                 }
    739 
    740                 void postvisit( const ast::ArrayType * array ) {
    741                         auto array2 = dynamic_cast< const ast::ArrayType * >( type2 );
    742                         if ( ! array2 ) return;
    743 
    744                         // to unify, array types must both be VLA or both not VLA and both must have a
    745                         // dimension expression or not have a dimension
    746                         if ( array->isVarLen != array2->isVarLen ) return;
    747                         if ( ! array->isVarLen && ! array2->isVarLen
    748                                         && array->dimension && array2->dimension ) {
    749                                 auto ce1 = array->dimension.as< ast::ConstantExpr >();
    750                                 auto ce2 = array2->dimension.as< ast::ConstantExpr >();
    751 
    752                                 // see C11 Reference Manual 6.7.6.2.6
    753                                 // two array types with size specifiers that are integer constant expressions are
    754                                 // compatible if both size specifiers have the same constant value
    755                                 if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return;
    756                         }
    757 
    758                         result = unifyExact(
    759                                 array->base, array2->base, tenv, need, have, open, noWiden(),
    760                                 symtab );
    761                 }
    762 
    763                 void postvisit( const ast::ReferenceType * ref ) {
    764                         if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    765                                 result = unifyExact(
    766                                         ref->base, ref2->base, tenv, need, have, open, noWiden(),
    767                                         symtab );
    768                         }
    769                 }
    770 
    771         private:
    772                 /// Replaces ttype variables with their bound types.
    773                 /// If this isn't done when satifying ttype assertions, then argument lists can have
    774                 /// different size and structure when they should be compatible.
    775                 struct TtypeExpander_new : public ast::WithShortCircuiting {
    776                         ast::TypeEnvironment & tenv;
    777 
    778                         TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
    779 
    780                         const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    781                                 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
    782                                         // expand ttype parameter into its actual type
    783                                         if ( clz->data.kind == ast::TypeVar::Ttype && clz->bound ) {
    784                                                 return clz->bound;
    785                                         }
    786                                 }
    787                                 return typeInst;
    788                         }
    789                 };
    790 
    791                 /// returns flattened version of `src`
    792                 static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
    793                         const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
    794                 ) {
    795                         std::vector< ast::ptr< ast::DeclWithType > > dst;
    796                         dst.reserve( src.size() );
    797                         for ( const ast::DeclWithType * d : src ) {
    798                                 ast::Pass<TtypeExpander_new> expander{ env };
    799                                 d = d->accept( expander );
    800                                 auto types = flatten( d->get_type() );
    801                                 for ( ast::ptr< ast::Type > & t : types ) {
    802                                         // outermost const, volatile, _Atomic qualifiers in parameters should not play
    803                                         // a role in the unification of function types, since they do not determine
    804                                         // whether a function is callable.
    805                                         // NOTE: **must** consider at least mutex qualifier, since functions can be
    806                                         // overloaded on outermost mutex and a mutex function has different
    807                                         // requirements than a non-mutex function
    808                                         remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    809                                         dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
    810                                 }
    811                         }
    812                         return dst;
    813                 }
    814 
    815                 /// Creates a tuple type based on a list of DeclWithType
    816                 template< typename Iter >
    817                 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
    818                         std::vector< ast::ptr< ast::Type > > types;
    819                         while ( crnt != end ) {
    820                                 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    821                                 // that this results in a flat tuple
    822                                 flatten( (*crnt)->get_type(), types );
    823 
    824                                 ++crnt;
    825                         }
    826 
    827                         return { new ast::TupleType{ std::move(types) } };
    828                 }
    829 
    830                 template< typename Iter >
    831                 static bool unifyDeclList(
    832                         Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    833                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    834                         const ast::SymbolTable & symtab
    835                 ) {
    836                         while ( crnt1 != end1 && crnt2 != end2 ) {
    837                                 const ast::Type * t1 = (*crnt1)->get_type();
    838                                 const ast::Type * t2 = (*crnt2)->get_type();
    839                                 bool isTuple1 = Tuples::isTtype( t1 );
    840                                 bool isTuple2 = Tuples::isTtype( t2 );
    841 
    842                                 // assumes here that ttype *must* be last parameter
    843                                 if ( isTuple1 && ! isTuple2 ) {
    844                                         // combine remainder of list2, then unify
    845                                         return unifyExact(
    846                                                 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    847                                                 noWiden(), symtab );
    848                                 } else if ( ! isTuple1 && isTuple2 ) {
    849                                         // combine remainder of list1, then unify
    850                                         return unifyExact(
    851                                                 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    852                                                 noWiden(), symtab );
    853                                 }
    854 
    855                                 if ( ! unifyExact(
    856                                         t1, t2, env, need, have, open, noWiden(), symtab )
    857                                 ) return false;
    858 
    859                                 ++crnt1; ++crnt2;
    860                         }
    861 
    862                         // May get to the end of one argument list before the other. This is only okay if the
    863                         // other is a ttype
    864                         if ( crnt1 != end1 ) {
    865                                 // try unifying empty tuple with ttype
    866                                 const ast::Type * t1 = (*crnt1)->get_type();
    867                                 if ( ! Tuples::isTtype( t1 ) ) return false;
    868                                 return unifyExact(
    869                                         t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    870                                         noWiden(), symtab );
    871                         } else if ( crnt2 != end2 ) {
    872                                 // try unifying empty tuple with ttype
    873                                 const ast::Type * t2 = (*crnt2)->get_type();
    874                                 if ( ! Tuples::isTtype( t2 ) ) return false;
    875                                 return unifyExact(
    876                                         tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    877                                         noWiden(), symtab );
    878                         }
    879 
    880                         return true;
    881                 }
    882 
    883                 static bool unifyDeclList(
    884                         const std::vector< ast::ptr< ast::DeclWithType > > & list1,
    885                         const std::vector< ast::ptr< ast::DeclWithType > > & list2,
    886                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    887                         const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    888                 ) {
    889                         return unifyDeclList(
    890                                 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    891                                 symtab );
    892                 }
    893 
    894                 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {
    895                         auto i = assns.find( assn );
    896                         if ( i != assns.end() ) {
    897                                 i->second.isUsed = true;
    898                         }
    899                 }
    900 
    901                 /// mark all assertions in `type` used in both `assn1` and `assn2`
    902                 static void markAssertions(
    903                         ast::AssertionSet & assn1, ast::AssertionSet & assn2,
    904                         const ast::ParameterizedType * type
    905                 ) {
    906                         for ( const auto & tyvar : type->forall ) {
    907                                 for ( const ast::DeclWithType * assert : tyvar->assertions ) {
    908                                         markAssertionSet( assn1, assert );
    909                                         markAssertionSet( assn2, assert );
    910                                 }
    911                         }
    912                 }
    913 
    914         public:
    915                 void postvisit( const ast::FunctionType * func ) {
    916                         auto func2 = dynamic_cast< const ast::FunctionType * >( type2 );
    917                         if ( ! func2 ) return;
    918 
    919                         if ( func->isVarArgs != func2->isVarArgs ) return;
    920 
    921                         // Flatten the parameter lists for both functions so that tuple structure does not
    922                         // affect unification. Does not actually mutate function parameters.
    923                         auto params = flattenList( func->params, tenv );
    924                         auto params2 = flattenList( func2->params, tenv );
    925 
    926                         // sizes don't have to match if ttypes are involved; need to be more precise w.r.t.
    927                         // where the ttype is to prevent errors
    928                         if (
    929                                 ( params.size() != params2.size() || func->returns.size() != func2->returns.size() )
    930                                 && ! func->isTtype()
    931                                 && ! func2->isTtype()
    932                         ) return;
    933 
    934                         if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
    935                         if ( ! unifyDeclList(
    936                                 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    937 
    938                         markAssertions( have, need, func );
    939                         markAssertions( have, need, func2 );
    940 
    941                         result = true;
    942                 }
    943 
    944         private:
    945                 template< typename RefType >
    946                 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
    947                         // check that the other type is compatible and named the same
    948                         auto otherInst = dynamic_cast< const RefType * >( other );
    949                         result = otherInst && inst->name == otherInst->name;
    950                         return otherInst;
    951                 }
    952 
    953                 /// Creates a tuple type based on a list of TypeExpr
    954                 template< typename Iter >
    955                 static const ast::Type * tupleFromExprs(
    956                         const ast::TypeExpr * param, Iter & crnt, Iter end, ast::CV::Qualifiers qs
    957                 ) {
    958                         std::vector< ast::ptr< ast::Type > > types;
    959                         do {
    960                                 types.emplace_back( param->type );
    961 
    962                                 ++crnt;
    963                                 if ( crnt == end ) break;
    964                                 param = strict_dynamic_cast< const ast::TypeExpr * >( crnt->get() );
    965                         } while(true);
    966 
    967                         return new ast::TupleType{ std::move(types), qs };
    968                 }
    969 
    970                 template< typename RefType >
    971                 void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
    972                         // check that other type is compatible and named the same
    973                         const RefType * inst2 = handleRefType( inst, other );
    974                         if ( ! inst2 ) return;
    975 
    976                         // check that parameters of types unify, if any
    977                         const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    978                         const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
    979 
    980                         auto it = params.begin();
    981                         auto jt = params2.begin();
    982                         for ( ; it != params.end() && jt != params2.end(); ++it, ++jt ) {
    983                                 auto param = strict_dynamic_cast< const ast::TypeExpr * >( it->get() );
    984                                 auto param2 = strict_dynamic_cast< const ast::TypeExpr * >( jt->get() );
    985 
    986                                 ast::ptr< ast::Type > pty = param->type;
    987                                 ast::ptr< ast::Type > pty2 = param2->type;
    988 
    989                                 bool isTuple = Tuples::isTtype( pty );
    990                                 bool isTuple2 = Tuples::isTtype( pty2 );
    991 
    992                                 if ( isTuple && isTuple2 ) {
    993                                         ++it; ++jt;  // skip ttype parameters before break
    994                                 } else if ( isTuple ) {
    995                                         // bundle remaining params into tuple
    996                                         pty2 = tupleFromExprs( param2, jt, params2.end(), pty->qualifiers );
    997                                         ++it;  // skip ttype parameter for break
    998                                 } else if ( isTuple2 ) {
    999                                         // bundle remaining params into tuple
    1000                                         pty = tupleFromExprs( param, it, params.end(), pty2->qualifiers );
    1001                                         ++jt;  // skip ttype parameter for break
    1002                                 }
    1003 
    1004                                 if ( ! unifyExact(
    1005                                                 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
    1006                                         result = false;
    1007                                         return;
    1008                                 }
    1009 
    1010                                 // ttype parameter should be last
    1011                                 if ( isTuple || isTuple2 ) break;
    1012                         }
    1013                         result = it == params.end() && jt == params2.end();
    1014                 }
    1015 
    1016         public:
    1017                 void postvisit( const ast::StructInstType * aggrType ) {
    1018                         handleGenericRefType( aggrType, type2 );
    1019                 }
    1020 
    1021                 void postvisit( const ast::UnionInstType * aggrType ) {
    1022                         handleGenericRefType( aggrType, type2 );
    1023                 }
    1024 
    1025                 void postvisit( const ast::EnumInstType * aggrType ) {
    1026                         handleRefType( aggrType, type2 );
    1027                 }
    1028 
    1029                 void postvisit( const ast::TraitInstType * aggrType ) {
    1030                         handleRefType( aggrType, type2 );
    1031                 }
    1032 
    1033                 void postvisit( const ast::TypeInstType * typeInst ) {
    1034                         assert( open.find( typeInst->name ) == open.end() );
    1035                         handleRefType( typeInst, type2 );
    1036                 }
    1037 
    1038         private:
    1039                 /// Creates a tuple type based on a list of Type
    1040                 static ast::ptr< ast::Type > tupleFromTypes(
    1041                         const std::vector< ast::ptr< ast::Type > > & tys
    1042                 ) {
    1043                         std::vector< ast::ptr< ast::Type > > out;
    1044                         for ( const ast::Type * ty : tys ) {
    1045                                 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    1046                                 // that this results in a flat tuple
    1047                                 flatten( ty, out );
    1048                         }
    1049 
    1050                         return { new ast::TupleType{ std::move(out) } };
    1051                 }
    1052 
    1053                 static bool unifyList(
    1054                         const std::vector< ast::ptr< ast::Type > > & list1,
    1055                         const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,
    1056                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1057                         const ast::SymbolTable & symtab
    1058                 ) {
    1059                         auto crnt1 = list1.begin();
    1060                         auto crnt2 = list2.begin();
    1061                         while ( crnt1 != list1.end() && crnt2 != list2.end() ) {
    1062                                 const ast::Type * t1 = *crnt1;
    1063                                 const ast::Type * t2 = *crnt2;
    1064                                 bool isTuple1 = Tuples::isTtype( t1 );
    1065                                 bool isTuple2 = Tuples::isTtype( t2 );
    1066 
    1067                                 // assumes ttype must be last parameter
    1068                                 if ( isTuple1 && ! isTuple2 ) {
    1069                                         // combine entirety of list2, then unify
    1070                                         return unifyExact(
    1071                                                 t1, tupleFromTypes( list2 ), env, need, have, open,
    1072                                                 noWiden(), symtab );
    1073                                 } else if ( ! isTuple1 && isTuple2 ) {
    1074                                         // combine entirety of list1, then unify
    1075                                         return unifyExact(
    1076                                                 tupleFromTypes( list1 ), t2, env, need, have, open,
    1077                                                 noWiden(), symtab );
    1078                                 }
    1079 
    1080                                 if ( ! unifyExact(
    1081                                         t1, t2, env, need, have, open, noWiden(), symtab )
    1082                                 ) return false;
    1083 
    1084                                 ++crnt1; ++crnt2;
    1085                         }
    1086 
    1087                         if ( crnt1 != list1.end() ) {
    1088                                 // try unifying empty tuple type with ttype
    1089                                 const ast::Type * t1 = *crnt1;
    1090                                 if ( ! Tuples::isTtype( t1 ) ) return false;
    1091                                 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported
    1092                                 // from Rob's code
    1093                                 return unifyExact(
    1094                                                 t1, tupleFromTypes( list2 ), env, need, have, open,
    1095                                                 noWiden(), symtab );
    1096                         } else if ( crnt2 != list2.end() ) {
    1097                                 // try unifying empty tuple with ttype
    1098                                 const ast::Type * t2 = *crnt2;
    1099                                 if ( ! Tuples::isTtype( t2 ) ) return false;
    1100                                 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported
    1101                                 // from Rob's code
    1102                                 return unifyExact(
    1103                                                 tupleFromTypes( list1 ), t2, env, need, have, open,
    1104                                                 noWiden(), symtab );
    1105                         }
    1106 
    1107                         return true;
    1108                 }
    1109 
    1110         public:
    1111                 void postvisit( const ast::TupleType * tuple ) {
    1112                         auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 );
    1113                         if ( ! tuple2 ) return;
    1114 
    1115                         ast::Pass<TtypeExpander_new> expander{ tenv };
    1116                         const ast::Type * flat = tuple->accept( expander );
    1117                         const ast::Type * flat2 = tuple2->accept( expander );
    1118 
    1119                         auto types = flatten( flat );
    1120                         auto types2 = flatten( flat2 );
    1121 
    1122                         result = unifyList( types, types2, tenv, need, have, open, symtab );
    1123                 }
    1124 
    1125                 void postvisit( const ast::VarArgsType * ) {
    1126                         result = dynamic_cast< const ast::VarArgsType * >( type2 );
    1127                 }
    1128 
    1129                 void postvisit( const ast::ZeroType * ) {
    1130                         result = dynamic_cast< const ast::ZeroType * >( type2 );
    1131                 }
    1132 
    1133                 void postvisit( const ast::OneType * ) {
    1134                         result = dynamic_cast< const ast::OneType * >( type2 );
    1135                 }
    1136 
    1137           private:
    1138                 template< typename RefType > void handleRefType( RefType *inst, Type *other );
    1139                 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
    1140         };
    1141 
    1142         bool unify(
    1143                         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    1144                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1145                         ast::OpenVarSet & open, const ast::SymbolTable & symtab
    1146         ) {
    1147                 ast::ptr<ast::Type> common;
    1148                 return unify( type1, type2, env, need, have, open, symtab, common );
    1149         }
    1150 
    1151         bool unify(
    1152                         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    1153                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1154                         ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
    1155         ) {
    1156                 ast::OpenVarSet closed;
    1157                 findOpenVars( type1, open, closed, need, have, FirstClosed );
    1158                 findOpenVars( type2, open, closed, need, have, FirstOpen );
    1159                 return unifyInexact(
    1160                         type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common );
    1161         }
    1162 
    1163         bool unifyExact(
    1164                         const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    1165                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1166                         WidenMode widen, const ast::SymbolTable & symtab
    1167         ) {
    1168                 if ( type1->qualifiers != type2->qualifiers ) return false;
    1169 
    1170                 auto var1 = dynamic_cast< const ast::TypeInstType * >( type1 );
    1171                 auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
    1172                 ast::OpenVarSet::const_iterator
    1173                         entry1 = var1 ? open.find( var1->name ) : open.end(),
    1174                         entry2 = var2 ? open.find( var2->name ) : open.end();
    1175                 bool isopen1 = entry1 != open.end();
    1176                 bool isopen2 = entry2 != open.end();
    1177 
    1178                 if ( isopen1 && isopen2 ) {
    1179                         if ( entry1->second.kind != entry2->second.kind ) return false;
    1180                         return env.bindVarToVar(
    1181                                 var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have,
    1182                                 open, widen, symtab );
    1183                 } else if ( isopen1 ) {
    1184                         return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab );
    1185                 } else if ( isopen2 ) {
    1186                         return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );
    1187                 } else {
    1188                         ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
    1189                         type1->accept( comparator );
    1190                         return comparator.pass.result;
    1191                 }
    1192         }
    1193 
    1194         bool unifyInexact(
    1195                         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    1196                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1197                         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
    1198                         ast::ptr<ast::Type> & common
    1199         ) {
    1200                 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
    1201 
    1202                 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    1203                 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    1204                 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
    1205                 reset_qualifiers( t1 );
    1206                 reset_qualifiers( t2 );
    1207 
    1208                 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    1209                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1210 
    1211                         // if exact unification on unqualified types, try to merge qualifiers
    1212                         if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
    1215                                 return true;
    1216                         } else {
    1217                                 return false;
    1218                         }
    1219 
    1220                 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    1223                         // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
    1225                         return true;
    1226                 } else {
    1227                         return false;
    1228                 }
    1229         }
    1230 
    1231         ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    1232                 if ( func->returns.empty() ) return new ast::VoidType{};
    1233                 if ( func->returns.size() == 1 ) return func->returns[0]->get_type();
    1234 
    1235                 std::vector<ast::ptr<ast::Type>> tys;
    1236                 for ( const ast::DeclWithType * decl : func->returns ) {
    1237                         tys.emplace_back( decl->get_type() );
    1238                 }
    1239                 return new ast::TupleType{ std::move(tys) };
    1240         }
    1241788} // namespace ResolvExpr
    1242789
  • src/ResolvExpr/Unify.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul 21 23:09:34 2017
     13// Update Count     : 3
    1414//
    1515
     
    1818#include <list>                   // for list
    1919
    20 #include "AST/Node.hpp"             // for ptr
    21 #include "AST/TypeEnvironment.hpp"  // for TypeEnvironment, AssertionSet, OpenVarSet
    2220#include "Common/utility.h"       // for deleteAll
    2321#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2422#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
    25 #include "WidenMode.h"              // for WidenMode
    2623
    2724class Type;
    2825class TypeInstType;
    2926namespace SymTab {
    30         class Indexer;
    31 }
    32 
    33 namespace ast {
    34         class SymbolTable;
    35         class Type;
    36 }
     27class Indexer;
     28}  // namespace SymTab
    3729
    3830namespace ResolvExpr {
     31        struct WidenMode {
     32                WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}
     33                WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }
     34                WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }
     35                WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }
     36                WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
     37                operator bool() { return widenFirst && widenSecond; }
     38
     39                bool widenFirst : 1, widenSecond : 1;
     40        };
     41
     42        bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    3943        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    4044        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    4145        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 );
    4346
    4447        template< typename Iterator1, typename Iterator2 >
     
    6972        }
    7073
    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 );
    75 
    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 );
    80 
    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 );
    85 
    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 );
    91 
    9274} // namespace ResolvExpr
    9375
  • src/ResolvExpr/module.mk

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 SRC_RESOLVEXPR = \
    18       ResolvExpr/AdjustExprType.cc \
    19       ResolvExpr/Alternative.cc \
    20       ResolvExpr/AlternativeFinder.cc \
    21       ResolvExpr/Candidate.cpp \
    22       ResolvExpr/CandidateFinder.cpp \
    23       ResolvExpr/CastCost.cc \
    24       ResolvExpr/CommonType.cc \
    25       ResolvExpr/ConversionCost.cc \
    26       ResolvExpr/CurrentObject.cc \
    27       ResolvExpr/ExplodedActual.cc \
    28       ResolvExpr/ExplodedArg.cpp \
    29       ResolvExpr/FindOpenVars.cc \
    30       ResolvExpr/Occurs.cc \
    31       ResolvExpr/PolyCost.cc \
    32       ResolvExpr/PtrsAssignable.cc \
    33       ResolvExpr/PtrsCastable.cc \
    34       ResolvExpr/RenameVars.cc \
    35       ResolvExpr/ResolveAssertions.cc \
    36       ResolvExpr/Resolver.cc \
    37       ResolvExpr/ResolveTypeof.cc \
    38       ResolvExpr/SatisfyAssertions.cpp \
    39       ResolvExpr/SpecCost.cc \
    40       ResolvExpr/TypeEnvironment.cc \
    41       ResolvExpr/Unify.cc
    42 
    43 SRC += $(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc
    44 SRCDEMANGLE += $(SRC_RESOLVEXPR)
     17SRC += ResolvExpr/AlternativeFinder.cc \
     18       ResolvExpr/Alternative.cc \
     19       ResolvExpr/Unify.cc \
     20       ResolvExpr/PtrsAssignable.cc \
     21       ResolvExpr/CommonType.cc \
     22       ResolvExpr/ConversionCost.cc \
     23       ResolvExpr/CastCost.cc \
     24       ResolvExpr/PtrsCastable.cc \
     25       ResolvExpr/AdjustExprType.cc \
     26       ResolvExpr/AlternativePrinter.cc \
     27       ResolvExpr/Resolver.cc \
     28       ResolvExpr/ResolveTypeof.cc \
     29       ResolvExpr/RenameVars.cc \
     30       ResolvExpr/FindOpenVars.cc \
     31       ResolvExpr/PolyCost.cc \
     32       ResolvExpr/Occurs.cc \
     33       ResolvExpr/TypeEnvironment.cc \
     34       ResolvExpr/CurrentObject.cc \
     35       ResolvExpr/ExplodedActual.cc
  • src/ResolvExpr/typeops.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 07:28:22 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:36:00 2019
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:36:18 2017
     13// Update Count     : 3
    1414//
    1515
     
    1818#include <vector>
    1919
     20#include "SynTree/SynTree.h"
     21#include "SynTree/Type.h"
     22#include "SymTab/Indexer.h"
    2023#include "Cost.h"
    2124#include "TypeEnvironment.h"
    22 #include "WidenMode.h"
    23 #include "AST/Fwd.hpp"
    24 #include "AST/Node.hpp"
    25 #include "AST/SymbolTable.hpp"
    26 #include "AST/Type.hpp"
    27 #include "AST/TypeEnvironment.hpp"
    28 #include "SynTree/SynTree.h"
    29 #include "SynTree/Type.h"
    30 
    31 namespace SymTab {
    32         class Indexer;
    33 }
    3425
    3526namespace ResolvExpr {
     
    6354        // in AdjustExprType.cc
    6455        /// 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 );
     56        void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    6657
    6758        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
     
    6960
    7061        template< typename ForwardIterator >
    71         void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
     62        void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    7263                while ( begin != end ) {
    7364                        adjustExprType( *begin++, env, indexer );
     
    7566        }
    7667
    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 
    8168        // 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, const ast::SymbolTable & symtab,
    86                 const ast::TypeEnvironment & env );
     69        Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    8770
    8871        // 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, const ast::SymbolTable & symtab,
    93                 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 );
     72        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    9873
    9974        // 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 );
     75        int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env );
    10376
    10477        // 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 );
     78        int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    10979
    11080        // 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 );
     81        bool isFtype( Type *type );
     82        bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     83        bool typesCompatibleIgnoreQualifiers( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    11384
    114         inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
     85        inline bool typesCompatible( Type *t1, Type *t2, const SymTab::Indexer &indexer ) {
    11586                TypeEnvironment env;
    11687                return typesCompatible( t1, t2, indexer, env );
    11788        }
    11889
    119         inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
     90        inline bool typesCompatibleIgnoreQualifiers( Type *t1, Type *t2, const SymTab::Indexer &indexer ) {
    12091                TypeEnvironment env;
    12192                return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
    12293        }
    12394
    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 
    13295        /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
    13396        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 );
    13697
    13798        // 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, WidenMode widen,
    141                 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
     99        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    142100
    143101        // in PolyCost.cc
    144         int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
    145         int polyCost(
    146                 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    147 
    148         // in SpecCost.cc
    149         int specCost( Type * type );
    150         int specCost( const ast::Type * type );
     102        int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    151103
    152104        // in Occurs.cc
    153         bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
    154         // new AST version in TypeEnvironment.cpp (only place it was used in old AST)
    155 
    156         template<typename Iter>
    157         bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) {
    158                 while ( begin != end ) {
    159                         if ( occurs( ty, *begin, env ) ) return true;
    160                         ++begin;
    161                 }
    162                 return false;
    163         }
     105        bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
    164106
    165107        // in AlternativeFinder.cc
    166108        void referenceToRvalueConversion( Expression *& expr, Cost & cost );
    167         // in CandidateFinder.cpp
    168         const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );
    169109
    170         /// flatten tuple type into list of types
     110        // flatten tuple type into list of types
    171111        template< typename OutputIterator >
    172112        void flatten( Type * type, OutputIterator out ) {
     
    179119                }
    180120        }
    181 
    182         /// flatten tuple type into existing list of types
    183         static inline void flatten(
    184                 const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out
    185         ) {
    186                 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) {
    187                         for ( const ast::Type * t : tupleType->types ) {
    188                                 flatten( t, out );
    189                         }
    190                 } else {
    191                         out.emplace_back( type );
    192                 }
    193         }
    194 
    195         /// flatten tuple type into list of types
    196         static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {
    197                 std::vector< ast::ptr< ast::Type > > out;
    198                 out.reserve( type->size() );
    199                 flatten( type, out );
    200                 return out;
    201         }
    202 
    203         // in TypeEnvironment.cc
    204         bool isFtype( const Type * type );
    205121} // namespace ResolvExpr
    206 
    207 namespace ast {
    208         // in TypeEnvironment.cpp
    209         bool isFtype( const ast::Type * type );
    210 } // namespace ast
    211122
    212123// Local Variables: //
  • src/SymTab/Autogen.cc

    rb067d9b r7951100  
    2424#include <vector>                  // for vector
    2525
    26 #include "AST/Decl.hpp"
    2726#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2827#include "Common/PassVisitor.h"    // for PassVisitor
     
    4241
    4342namespace SymTab {
     43        Type * SizeType = 0;
     44
    4445        /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
    4546        struct FuncData {
    46                 typedef FunctionType * (*TypeGen)( Type *, bool );
     47                typedef FunctionType * (*TypeGen)( Type * );
    4748                FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
    4849                std::string fname;
     
    210211        }
    211212
    212         bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
    213                 return obj && obj->name.empty() && obj->bitfieldWidth;
    214         }
    215 
    216213        /// inserts a forward declaration for functionDecl into declsToAdd
    217214        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
     
    234231
    235232        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    236         FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
     233        FunctionType * genDefaultType( Type * paramType ) {
     234                const auto & typeParams = getGenericParams( paramType );
    237235                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    238                 if ( maybePolymorphic ) {
    239                         // only copy in
    240                         const auto & typeParams = getGenericParams( paramType );
    241                         cloneAll( typeParams, ftype->forall );
    242                 }
     236                cloneAll( typeParams, ftype->forall );
    243237                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    244238                ftype->parameters.push_back( dstParam );
     
    247241
    248242        /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
    249         FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
    250                 FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
     243        FunctionType * genCopyType( Type * paramType ) {
     244                FunctionType *ftype = genDefaultType( paramType );
    251245                ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    252246                ftype->parameters.push_back( srcParam );
     
    255249
    256250        /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
    257         FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
    258                 FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
     251        FunctionType * genAssignType( Type * paramType ) {
     252                FunctionType *ftype = genCopyType( paramType );
    259253                ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    260254                ftype->returnVals.push_back( returnVal );
     
    314308                for ( const FuncData & d : data ) {
    315309                        // generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
    316                         FunctionType * ftype = d.genType( type, true );
     310                        FunctionType * ftype = d.genType( type );
    317311
    318312                        // destructor for concurrent type must be mutex
     
    393387
    394388        void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) {
    395                 InitTweak::InitExpander_old srcParam( src );
     389                InitTweak::InitExpander srcParam( src );
    396390
    397391                // assign to destination
  • src/SymTab/Autogen.h

    rb067d9b r7951100  
    1717
    1818#include <cassert>                // for assert
    19 #include <iterator>               // for back_inserter
    2019#include <string>                 // for string
    2120
    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"
    2821#include "CodeGen/OperatorTable.h"
    2922#include "Common/UniqueName.h"    // for UniqueName
    30 #include "Common/utility.h"       // for splice
    3123#include "InitTweak/InitTweak.h"  // for InitExpander
    3224#include "SynTree/Constant.h"     // for Constant
     
    4436        /// returns true if obj's name is the empty string and it has a bitfield width
    4537        bool isUnnamedBitfield( ObjectDecl * obj );
    46         bool isUnnamedBitfield( const ast::ObjectDecl * obj );
    47 
    48         /// generate the type of an assignment function for paramType.
    49         /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    50         FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
    51 
    52         /// generate the type of a default constructor or destructor for paramType.
    53         /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    54         FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
    55 
    56         /// generate the type of a copy constructor for paramType.
    57         /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    58         FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    59 
    60         /// Enum for loop direction
    61         enum LoopDirection { LoopBackward, LoopForward };
     38
     39        /// size_t type - set when size_t typedef is seen. Useful in a few places,
     40        /// such as in determining array dimension type
     41        extern Type * SizeType;
     42
     43        /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
     44        /// Useful for creating dereference ApplicationExprs without a full resolver pass.
     45        extern FunctionDecl * dereferenceOperator;
     46
     47        // generate the type of an assignment function for paramType
     48        FunctionType * genAssignType( Type * paramType );
     49
     50        // generate the type of a default constructor or destructor for paramType
     51        FunctionType * genDefaultType( Type * paramType );
     52
     53        // generate the type of a copy constructor for paramType
     54        FunctionType * genCopyType( Type * paramType );
    6255
    6356        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    6457        template< typename OutputIterator >
    65         Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
    66 
    67         template< typename OutIter >
    68         ast::ptr< ast::Stmt > genCall(
    69                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    70                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    71                 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
     58        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
    7259
    7360        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    7461        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    7562        template< typename OutputIterator >
    76         Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
     63        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
    7764                bool isReferenceCtorDtor = false;
    7865                if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     
    9784                        //   type->get_qualifiers() = Type::Qualifiers();
    9885                        Type * castType = addCast->clone();
    99                         castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     86                        castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    10087                        // castType->set_lvalue( true ); // xxx - might not need this
    10188                        dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
     
    124111        }
    125112
    126         /// inserts into out a generated call expression to function fname with arguments dstParam and
    127         /// srcParam. Should only be called with non-array types.
    128         /// optionally returns a statement which must be inserted prior to the containing loop, if
    129         /// there is one
    130         template< typename OutIter >
    131         ast::ptr< ast::Stmt > genScalarCall(
    132                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    133                 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
    134                 const ast::Type * addCast = nullptr
    135         ) {
    136                 bool isReferenceCtorDtor = false;
    137                 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
    138                         // reference constructors are essentially application of the rebind operator.
    139                         // apply & to both arguments, do not need a cast
    140                         fname = "?=?";
    141                         dstParam = new ast::AddressExpr{ dstParam };
    142                         addCast = nullptr;
    143                         isReferenceCtorDtor = true;
    144                 }
    145 
    146                 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
    147                 // "?=?", "?{}", or "^?{}"
    148                 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };
    149 
    150                 if ( addCast ) {
    151                         // cast to T& with qualifiers removed, so that qualified objects can be constructed and
    152                         // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
    153                         // is considered a qualifier - for AddressExpr to resolve, its argument must have an
    154                         // lvalue-qualified type, so remove all qualifiers except lvalue.
    155                         // xxx -- old code actually removed lvalue too...
    156                         ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
    157                         ast::ptr< ast::Type > castType = addCast;
    158                         ast::remove_qualifiers(
    159                                 castType,
    160                                 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
    161                         dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
    162                 }
    163                 fExpr->args.emplace_back( dstParam );
    164 
    165                 const ast::Stmt * listInit = srcParam.buildListInit( fExpr );
    166 
    167                 // fetch next set of arguments
    168                 ++srcParam;
    169 
    170                 // return if adding reference fails -- will happen on default ctor and dtor
    171                 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
    172 
    173                 std::vector< ast::ptr< ast::Expr > > args = *srcParam;
    174                 splice( fExpr->args, args );
    175 
    176                 *out++ = new ast::ExprStmt{ loc, fExpr };
    177 
    178                 srcParam.clearArrayIndices();
    179                
    180                 return listInit;
    181         }
    182 
    183113        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    184114        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    185115        template< typename OutputIterator >
    186         void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
     116        void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
    187117                static UniqueName indexName( "_index" );
    188118
     
    245175        }
    246176
    247         /// Store in out a loop which calls fname on each element of the array with srcParam and
    248         /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
    249         template< typename OutIter >
    250         void genArrayCall(
    251                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    252                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    253                 const ast::ArrayType * array, const ast::Type * addCast = nullptr,
    254                 LoopDirection forward = LoopForward
    255         ) {
    256                 static UniqueName indexName( "_index" );
    257 
    258                 // for a flexible array member nothing is done -- user must define own assignment
    259                 if ( ! array->dimension ) return;
    260 
    261                 if ( addCast ) {
    262                         // peel off array layer from cast
    263                         addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
    264                 }
    265 
    266                 ast::ptr< ast::Expr > begin, end, cmp, update;
    267 
    268                 if ( forward ) {
    269                         // generate: for ( int i = 0; i < N; ++i )
    270                         begin = ast::ConstantExpr::from_int( loc, 0 );
    271                         end = array->dimension;
    272                         cmp = new ast::NameExpr{ loc, "?<?" };
    273                         update = new ast::NameExpr{ loc, "++?" };
    274                 } else {
    275                         // generate: for ( int i = N-1; i >= 0; --i )
    276                         begin = new ast::UntypedExpr{
    277                                 loc, new ast::NameExpr{ loc, "?-?" },
    278                                 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
    279                         end = ast::ConstantExpr::from_int( loc, 0 );
    280                         cmp = new ast::NameExpr{ loc, "?>=?" };
    281                         update = new ast::NameExpr{ loc, "--?" };
    282                 }
    283 
    284                 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
    285                         loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    286                         new ast::SingleInit{ loc, begin } };
    287                
    288                 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
    289                         loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
    290                
    291                 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
    292                         loc, update, { new ast::VariableExpr{ loc, index } } };
    293                
    294                 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
    295                         loc, new ast::NameExpr{ loc, "?[?]" },
    296                         { dstParam, new ast::VariableExpr{ loc, index } } };
    297                
    298                 // srcParam must keep track of the array indices to build the source parameter and/or
    299                 // array list initializer
    300                 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
    301 
    302                 // for stmt's body, eventually containing call
    303                 ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
    304                 ast::ptr< ast::Stmt > listInit = genCall(
    305                         srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
    306                         forward );
    307                
    308                 // block containing the stmt and index variable
    309                 ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
    310                 block->push_back( new ast::DeclStmt{ loc, index } );
    311                 if ( listInit ) { block->push_back( listInit ); }
    312                 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );
    313 
    314                 *out++ = block;
    315         }
    316 
    317         template< typename OutputIterator >
    318         Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     177        template< typename OutputIterator >
     178        Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
    319179                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    320180                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     
    325185        }
    326186
    327         template< typename OutIter >
    328         ast::ptr< ast::Stmt > genCall(
    329                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    330                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    331                 const ast::Type * type, const ast::Type * addCast, LoopDirection forward
    332         ) {
    333                 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
    334                         genArrayCall(
    335                                 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
    336                                 forward );
    337                         return {};
    338                 } else {
    339                         return genScalarCall(
    340                                 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
    341                 }
    342         }
    343 
    344187        /// inserts into out a generated call expression to function fname with arguments dstParam
    345188        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     
    347190        /// ImplicitCtorDtorStmt node.
    348191        template< typename OutputIterator >
    349         void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     192        void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    350193                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    351194                assert( obj );
     
    375218                }
    376219        }
    377 
    378         static inline ast::ptr< ast::Stmt > genImplicitCall(
    379                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    380                 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
    381                 LoopDirection forward = LoopForward
    382         ) {
    383                 // unnamed bit fields are not copied as they cannot be accessed
    384                 if ( isUnnamedBitfield( obj ) ) return {};
    385 
    386                 ast::ptr< ast::Type > addCast = nullptr;
    387                 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    388                         assert( dstParam->result );
    389                         addCast = dstParam->result;
    390                 }
    391 
    392                 std::vector< ast::ptr< ast::Stmt > > stmts;
    393                 genCall(
    394                         srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
    395 
    396                 if ( stmts.empty() ) {
    397                         return {};
    398                 } else if ( stmts.size() == 1 ) {
    399                         const ast::Stmt * callStmt = stmts.front();
    400                         if ( addCast ) {
    401                                 // implicitly generated ctor/dtor calls should be wrapped so that later passes are
    402                                 // aware they were generated.
    403                                 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
    404                         }
    405                         return callStmt;
    406                 } else {
    407                         assert( false );
    408                         return {};
    409                 }
    410         }
    411220} // namespace SymTab
    412221
  • src/SymTab/FixFunction.cc

    rb067d9b r7951100  
    1818#include <list>                   // for list
    1919
    20 #include "AST/Decl.hpp"
    21 #include "AST/Pass.hpp"
    22 #include "AST/Type.hpp"
    23 #include "Common/utility.h"       // for maybeClone, copy
     20#include "Common/utility.h"       // for maybeClone
    2421#include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
    2522#include "SynTree/Expression.h"   // for Expression
     
    2724
    2825namespace SymTab {
    29         class FixFunction_old : public WithShortCircuiting {
    30                 typedef Mutator Parent;
    31           public:
    32                 FixFunction_old() : isVoid( false ) {}
     26        FixFunction::FixFunction() : isVoid( false ) {}
    3327
    34                 void premutate(FunctionDecl *functionDecl);
    35                 DeclarationWithType* postmutate(FunctionDecl *functionDecl);
    3628
    37                 Type * postmutate(ArrayType * arrayType);
    38 
    39                 void premutate(ArrayType * arrayType);
    40                 void premutate(VoidType * voidType);
    41                 void premutate(BasicType * basicType);
    42                 void premutate(PointerType * pointerType);
    43                 void premutate(StructInstType * aggregateUseType);
    44                 void premutate(UnionInstType * aggregateUseType);
    45                 void premutate(EnumInstType * aggregateUseType);
    46                 void premutate(TraitInstType * aggregateUseType);
    47                 void premutate(TypeInstType * aggregateUseType);
    48                 void premutate(TupleType * tupleType);
    49                 void premutate(VarArgsType * varArgsType);
    50                 void premutate(ZeroType * zeroType);
    51                 void premutate(OneType * oneType);
    52 
    53                 bool isVoid;
    54         };
    55 
    56         DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) {
     29        DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
    5730                // can't delete function type because it may contain assertions, so transfer ownership to new object
    5831                ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
    59                 pointer->location = functionDecl->location;
    6032                functionDecl->attributes.clear();
    6133                functionDecl->type = nullptr;
     
    6840        // does not cause an error
    6941
    70         Type * FixFunction_old::postmutate(ArrayType *arrayType) {
     42        Type * FixFunction::postmutate(ArrayType *arrayType) {
    7143                // need to recursively mutate the base type in order for multi-dimensional arrays to work.
    7244                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
    73                 pointerType->location = arrayType->location;
    7445                arrayType->base = nullptr;
    7546                arrayType->dimension = nullptr;
     
    7849        }
    7950
    80         void FixFunction_old::premutate(VoidType *) {
     51        void FixFunction::premutate(VoidType *) {
    8152                isVoid = true;
    8253        }
    8354
    84         void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; }
    85         void FixFunction_old::premutate(ArrayType *) { visit_children = false; }
    86         void FixFunction_old::premutate(BasicType *) { visit_children = false; }
    87         void FixFunction_old::premutate(PointerType *) { visit_children = false; }
    88         void FixFunction_old::premutate(StructInstType *) { visit_children = false; }
    89         void FixFunction_old::premutate(UnionInstType *) { visit_children = false; }
    90         void FixFunction_old::premutate(EnumInstType *) { visit_children = false; }
    91         void FixFunction_old::premutate(TraitInstType *) { visit_children = false; }
    92         void FixFunction_old::premutate(TypeInstType *) { visit_children = false; }
    93         void FixFunction_old::premutate(TupleType *) { visit_children = false; }
    94         void FixFunction_old::premutate(VarArgsType *) { visit_children = false; }
    95         void FixFunction_old::premutate(ZeroType *) { visit_children = false; }
    96         void FixFunction_old::premutate(OneType *) { visit_children = false; }
     55        void FixFunction::premutate(FunctionDecl *) { visit_children = false; }
     56        void FixFunction::premutate(ArrayType *) { visit_children = false; }
     57        void FixFunction::premutate(BasicType *) { visit_children = false; }
     58        void FixFunction::premutate(PointerType *) { visit_children = false; }
     59        void FixFunction::premutate(StructInstType *) { visit_children = false; }
     60        void FixFunction::premutate(UnionInstType *) { visit_children = false; }
     61        void FixFunction::premutate(EnumInstType *) { visit_children = false; }
     62        void FixFunction::premutate(TraitInstType *) { visit_children = false; }
     63        void FixFunction::premutate(TypeInstType *) { visit_children = false; }
     64        void FixFunction::premutate(TupleType *) { visit_children = false; }
     65        void FixFunction::premutate(VarArgsType *) { visit_children = false; }
     66        void FixFunction::premutate(ZeroType *) { visit_children = false; }
     67        void FixFunction::premutate(OneType *) { visit_children = false; }
    9768
    9869        bool fixFunction( DeclarationWithType *& dwt ) {
    99                 PassVisitor<FixFunction_old> fixer;
     70                PassVisitor<FixFunction> fixer;
    10071                dwt = dwt->acceptMutator( fixer );
    10172                return fixer.pass.isVoid;
    10273        }
    103 
    104 namespace {
    105         struct FixFunction_new final : public ast::WithShortCircuiting {
    106                 bool isVoid = false;
    107 
    108                 void premutate( const ast::FunctionDecl * ) { visit_children = false; }
    109 
    110                 const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) {
    111                         return new ast::ObjectDecl{
    112                                 func->location, func->name, new ast::PointerType{ func->type }, nullptr,
    113                                 func->storage, func->linkage, nullptr, copy( func->attributes ) };
    114                 }
    115 
    116                 void premutate( const ast::ArrayType * ) { visit_children = false; }
    117 
    118                 const ast::Type * postmutate( const ast::ArrayType * array ) {
    119                         return new ast::PointerType{
    120                                 array->base, array->dimension, array->isVarLen, array->isStatic,
    121                                 array->qualifiers };
    122                 }
    123 
    124                 void premutate( const ast::VoidType * ) { isVoid = true; }
    125 
    126                 void premutate( const ast::BasicType * ) { visit_children = false; }
    127                 void premutate( const ast::PointerType * ) { visit_children = false; }
    128                 void premutate( const ast::StructInstType * ) { visit_children = false; }
    129                 void premutate( const ast::UnionInstType * ) { visit_children = false; }
    130                 void premutate( const ast::EnumInstType * ) { visit_children = false; }
    131                 void premutate( const ast::TraitInstType * ) { visit_children = false; }
    132                 void premutate( const ast::TypeInstType * ) { visit_children = false; }
    133                 void premutate( const ast::TupleType * ) { visit_children = false; }
    134                 void premutate( const ast::VarArgsType * ) { visit_children = false; }
    135                 void premutate( const ast::ZeroType * ) { visit_children = false; }
    136                 void premutate( const ast::OneType * ) { visit_children = false; }
    137         };
    138 } // anonymous namespace
    139 
    140 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ) {
    141         ast::Pass< FixFunction_new > fixer;
    142         dwt = dwt->accept( fixer );
    143         isVoid |= fixer.pass.isVoid;
    144         return dwt;
    145 }
    146 
    14774} // namespace SymTab
    14875
  • src/SymTab/FixFunction.h

    rb067d9b r7951100  
    1919#include "SynTree/SynTree.h"    // for Types
    2020
    21 namespace ast {
    22         class DeclWithType;
    23 }
     21namespace SymTab {
     22        /// Replaces function and array types by equivalent pointer types.
     23        class FixFunction : public WithShortCircuiting {
     24                typedef Mutator Parent;
     25          public:
     26                FixFunction();
    2427
    25 namespace SymTab {
    26         /// Replaces function and array types by equivalent pointer types. Returns true if type is
    27         /// void
     28                void premutate(FunctionDecl *functionDecl);
     29                DeclarationWithType* postmutate(FunctionDecl *functionDecl);
     30
     31                Type * postmutate(ArrayType * arrayType);
     32
     33                void premutate(ArrayType * arrayType);
     34                void premutate(VoidType * voidType);
     35                void premutate(BasicType * basicType);
     36                void premutate(PointerType * pointerType);
     37                void premutate(StructInstType * aggregateUseType);
     38                void premutate(UnionInstType * aggregateUseType);
     39                void premutate(EnumInstType * aggregateUseType);
     40                void premutate(TraitInstType * aggregateUseType);
     41                void premutate(TypeInstType * aggregateUseType);
     42                void premutate(TupleType * tupleType);
     43                void premutate(VarArgsType * varArgsType);
     44                void premutate(ZeroType * zeroType);
     45                void premutate(OneType * oneType);
     46
     47                bool isVoid;
     48        };
     49
    2850        bool fixFunction( DeclarationWithType *& );
    29 
    30         /// Returns declaration with function and array types replaced by equivalent pointer types.
    31         /// Sets isVoid to true if type is void
    32         const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid );
    3351} // namespace SymTab
    3452
  • src/SymTab/Indexer.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:37:33 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Mar  8 13:55:00 2019
    13 // Update Count     : 21
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Aug 17 16:08:40 2017
     13// Update Count     : 20
    1414//
    1515
     
    1717
    1818#include <cassert>                 // for assert, strict_dynamic_cast
     19#include <iostream>                // for operator<<, basic_ostream, ostream
    1920#include <string>                  // for string, operator<<, operator!=
    20 #include <memory>                  // for shared_ptr, make_shared
    2121#include <unordered_map>           // for operator!=, unordered_map<>::const...
    2222#include <unordered_set>           // for unordered_set
    2323#include <utility>                 // for pair, make_pair, move
    24 #include <vector>                  // for vector
    2524
    2625#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2726#include "Common/SemanticError.h"  // for SemanticError
    2827#include "Common/utility.h"        // for cloneAll
    29 #include "Common/Stats/Counter.h"  // for counters
    30 #include "GenPoly/GenPoly.h"       // for getFunctionType
     28#include "GenPoly/GenPoly.h"
    3129#include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
    3230#include "Mangler.h"               // for Mangler
     
    4038#include "SynTree/Type.h"          // for Type, StructInstType, UnionInstType
    4139
     40#define debugPrint(x) if ( doDebug ) { std::cerr << x; }
     41
    4242namespace SymTab {
    43 
    44         // Statistics block
    45         namespace {
    46                 static inline auto stats() {
    47                         using namespace Stats::Counters;
    48                         static auto group   = build<CounterGroup>("Indexers");
    49                         static struct {
    50                                 SimpleCounter * count;
    51                                 AverageCounter<double> * size;
    52                                 SimpleCounter * new_scopes;
    53                                 SimpleCounter * lazy_scopes;
    54                                 AverageCounter<double> * avg_scope_depth;
    55                                 MaxCounter<size_t> * max_scope_depth;
    56                                 SimpleCounter * add_calls;
    57                                 SimpleCounter * lookup_calls;
    58                                 SimpleCounter * map_lookups;
    59                                 SimpleCounter * map_mutations;
    60                         } ret = {
    61                                 .count   = build<SimpleCounter>("Count", group),
    62                                 .size    = build<AverageCounter<double>>("Average Size", group),
    63                                 .new_scopes = build<SimpleCounter>("Scopes", group),
    64                                 .lazy_scopes = build<SimpleCounter>("Lazy Scopes", group),
    65                                 .avg_scope_depth = build<AverageCounter<double>>("Average Scope", group),
    66                                 .max_scope_depth = build<MaxCounter<size_t>>("Max Scope", group),
    67                                 .add_calls = build<SimpleCounter>("Add Calls", group),
    68                                 .lookup_calls = build<SimpleCounter>("Lookup Calls", group),
    69                                 .map_lookups = build<SimpleCounter>("Map Lookups", group),
    70                                 .map_mutations = build<SimpleCounter>("Map Mutations", group)
     43        std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) {
     44                return out << "(" << data.id << "," << data.baseExpr << ")";
     45        }
     46
     47        typedef std::unordered_map< std::string, Indexer::IdData > MangleTable;
     48        typedef std::unordered_map< std::string, MangleTable > IdTable;
     49        typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
     50        typedef std::unordered_map< std::string, StructDecl* > StructTable;
     51        typedef std::unordered_map< std::string, EnumDecl* > EnumTable;
     52        typedef std::unordered_map< std::string, UnionDecl* > UnionTable;
     53        typedef std::unordered_map< std::string, TraitDecl* > TraitTable;
     54
     55        void dump( const IdTable &table, std::ostream &os ) {
     56                for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) {
     57                        for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) {
     58                                os << mangle->second << std::endl;
     59                        }
     60                }
     61        }
     62
     63        template< typename Decl >
     64        void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) {
     65                for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) {
     66                        os << it->second << std::endl;
     67                } // for
     68        }
     69
     70        struct Indexer::Impl {
     71                Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(),
     72                                idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
     73                Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ),
     74                                idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
     75                unsigned long refCount;   ///< Number of references to these tables
     76                unsigned long scope;      ///< Scope these tables are associated with
     77                unsigned long size;       ///< Number of elements stored in this table
     78                const Indexer base;       ///< Base indexer this extends
     79
     80                IdTable idTable;          ///< Identifier namespace
     81                TypeTable typeTable;      ///< Type namespace
     82                StructTable structTable;  ///< Struct namespace
     83                EnumTable enumTable;      ///< Enum namespace
     84                UnionTable unionTable;    ///< Union namespace
     85                TraitTable traitTable;    ///< Trait namespace
     86        };
     87
     88        Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) {
     89                if ( ! toClone ) return 0;
     90
     91                // shorten the search chain by skipping empty links
     92                Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone;
     93                if ( ret ) { ++ret->refCount; }
     94
     95                return ret;
     96        }
     97
     98        void Indexer::deleteRef( Indexer::Impl *toFree ) {
     99                if ( ! toFree ) return;
     100
     101                if ( --toFree->refCount == 0 ) delete toFree;
     102        }
     103
     104        void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const {
     105                // only need to perform this step for constructors, destructors, and assignment functions
     106                if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
     107
     108                // helpful data structure to organize properties for a type
     109                struct ValueType {
     110                        struct DeclBall { // properties for this particular decl
     111                                IdData decl;
     112                                bool isUserDefinedFunc;
     113                                bool isCopyFunc;
    71114                        };
    72                         return ret;
    73                 }
    74         }
    75 
    76         Indexer::Indexer()
    77         : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(),
    78           prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; }
     115                        // properties for this type
     116                        bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
     117                        BaseSyntaxNode * deleteStmt = nullptr;     // non-null if a user-defined function is found
     118                        std::list< DeclBall > decls;
     119
     120                        // another FunctionDecl for the current type was found - determine
     121                        // if it has special properties and update data structure accordingly
     122                        ValueType & operator+=( IdData data ) {
     123                                DeclarationWithType * function = data.id;
     124                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
     125                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->name );
     126                                decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
     127                                existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
     128                                if ( isUserDefinedFunc && ! data.deleteStmt ) {
     129                                        // any user-defined function can act as an implicit delete statement for generated constructors.
     130                                        // a delete stmt should not act as an implicit delete statement.
     131                                        deleteStmt = data.id;
     132                                }
     133                                return *this;
     134                        }
     135                }; // ValueType
     136
     137                std::list< IdData > copy;
     138                copy.splice( copy.end(), out );
     139
     140                // organize discovered declarations by type
     141                std::unordered_map< std::string, ValueType > funcMap;
     142                for ( auto decl : copy ) {
     143                        if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
     144                                std::list< DeclarationWithType * > & params = function->type->parameters;
     145                                assert( ! params.empty() );
     146                                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
     147                                Type * base = InitTweak::getPointerBase( params.front()->get_type() );
     148                                assert( base );
     149                                funcMap[ Mangler::mangle( base ) ] += decl;
     150                        } else {
     151                                out.push_back( decl );
     152                        }
     153                }
     154
     155                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine
     156                // the set of ctor/dtor/assign that can be used  by the requester. In particular, if the user defines
     157                // a default ctor, then the generated default ctor is unavailable, likewise for copy ctor
     158                // and dtor. If the user defines any ctor/dtor, then no generated field ctors are available.
     159                // If the user defines any ctor then the generated default ctor is unavailable (intrinsic default
     160                // ctor must be overridden exactly). If the user defines anything that looks like a copy constructor,
     161                // then the generated copy constructor is unavailable, and likewise for the assignment operator.
     162                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
     163                        ValueType & val = pair.second;
     164                        for ( ValueType::DeclBall ball : val.decls ) {
     165                                bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic;
     166                                bool isCopyFunc = ball.isCopyFunc;
     167                                bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc;
     168                                // only implicitly delete non-user defined functions that are  not intrinsic, and are
     169                                // not copy functions (assignment or copy constructor), unless a user-defined copy function exists.
     170                                // deleteStmt will be non-null only if a user-defined function is found.
     171                                if (isNotUserDefinedFunc && (! isCopyFunc || existsUserDefinedCopyFunc)) {
     172                                        ball.decl.deleteStmt = val.deleteStmt;
     173                                }
     174                                out.push_back( ball.decl );
     175                        }
     176                }
     177        }
     178
     179        void Indexer::makeWritable() {
     180                if ( ! tables ) {
     181                        // create indexer if not yet set
     182                        tables = new Indexer::Impl( scope );
     183                } else if ( tables->refCount > 1 || tables->scope != scope ) {
     184                        // make this indexer the base of a fresh indexer at the current scope
     185                        tables = new Indexer::Impl( scope, std::move( *this ) );
     186                }
     187        }
     188
     189        Indexer::Indexer() : tables( 0 ), scope( 0 ) {}
     190
     191        Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) {}
     192
     193        Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) {
     194                that.tables = 0;
     195        }
    79196
    80197        Indexer::~Indexer() {
    81                 stats().size->push( idTable ? idTable->size() : 0 );
    82         }
    83 
    84         void Indexer::lazyInitScope() {
    85                 if ( repScope < scope ) {
    86                         ++* stats().lazy_scopes;
    87                         // create rollback
    88                         prevScope = std::make_shared<Indexer>( * this );
    89                         // update repScope
    90                         repScope = scope;
    91                 }
    92         }
    93 
    94         void Indexer::enterScope() {
    95                 ++scope;
    96 
    97                 ++* stats().new_scopes;
    98                 stats().avg_scope_depth->push( scope );
    99                 stats().max_scope_depth->push( scope );
    100         }
    101 
    102         void Indexer::leaveScope() {
    103                 if ( repScope == scope ) {
    104                         Ptr prev = prevScope;           // make sure prevScope stays live
    105                         * this = std::move(* prevScope);  // replace with previous scope
    106                 }
    107 
    108                 --scope;
    109         }
    110 
    111         void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const {
    112                 ++* stats().lookup_calls;
    113                 if ( ! idTable ) return;
    114 
    115                 ++* stats().map_lookups;
    116                 auto decls = idTable->find( id );
    117                 if ( decls == idTable->end() ) return;
    118 
    119                 for ( auto decl : *(decls->second) ) {
    120                         out.push_back( decl.second );
    121                 }
    122         }
    123 
    124         const NamedTypeDecl * Indexer::lookupType( const std::string & id ) const {
    125                 ++* stats().lookup_calls;
    126                 if ( ! typeTable ) return nullptr;
    127                 ++* stats().map_lookups;
    128                 auto it = typeTable->find( id );
    129                 return it == typeTable->end() ? nullptr : it->second.decl;
    130         }
    131 
    132         const StructDecl * Indexer::lookupStruct( const std::string & id ) const {
    133                 ++* stats().lookup_calls;
    134                 if ( ! structTable ) return nullptr;
    135                 ++* stats().map_lookups;
    136                 auto it = structTable->find( id );
    137                 return it == structTable->end() ? nullptr : it->second.decl;
    138         }
    139 
    140         const EnumDecl * Indexer::lookupEnum( const std::string & id ) const {
    141                 ++* stats().lookup_calls;
    142                 if ( ! enumTable ) return nullptr;
    143                 ++* stats().map_lookups;
    144                 auto it = enumTable->find( id );
    145                 return it == enumTable->end() ? nullptr : it->second.decl;
    146         }
    147 
    148         const UnionDecl * Indexer::lookupUnion( const std::string & id ) const {
    149                 ++* stats().lookup_calls;
    150                 if ( ! unionTable ) return nullptr;
    151                 ++* stats().map_lookups;
    152                 auto it = unionTable->find( id );
    153                 return it == unionTable->end() ? nullptr : it->second.decl;
    154         }
    155 
    156         const TraitDecl * Indexer::lookupTrait( const std::string & id ) const {
    157                 ++* stats().lookup_calls;
    158                 if ( ! traitTable ) return nullptr;
    159                 ++* stats().map_lookups;
    160                 auto it = traitTable->find( id );
    161                 return it == traitTable->end() ? nullptr : it->second.decl;
    162         }
    163 
    164         const Indexer * Indexer::atScope( unsigned long target ) const {
    165                 // by lazy construction, final indexer in list has repScope 0, cannot be > target
    166                 // otherwise, will find first scope representing the target
    167                 const Indexer * indexer = this;
    168                 while ( indexer->repScope > target ) {
    169                         indexer = indexer->prevScope.get();
    170                 }
    171                 return indexer;
    172         }
    173 
    174         const NamedTypeDecl * Indexer::globalLookupType( const std::string & id ) const {
    175                 return atScope( 0 )->lookupType( id );
    176         }
    177 
    178         const StructDecl * Indexer::globalLookupStruct( const std::string & id ) const {
    179                 return atScope( 0 )->lookupStruct( id );
    180         }
    181 
    182         const UnionDecl * Indexer::globalLookupUnion( const std::string & id ) const {
    183                 return atScope( 0 )->lookupUnion( id );
    184         }
    185 
    186         const EnumDecl * Indexer::globalLookupEnum( const std::string & id ) const {
    187                 return atScope( 0 )->lookupEnum( id );
    188         }
    189 
    190         bool isFunction( const DeclarationWithType * decl ) {
     198                deleteRef( tables );
     199        }
     200
     201        Indexer& Indexer::operator= ( const Indexer &that ) {
     202                deleteRef( tables );
     203
     204                tables = newRef( that.tables );
     205                scope = that.scope;
     206                doDebug = that.doDebug;
     207
     208                return *this;
     209        }
     210
     211        Indexer& Indexer::operator= ( Indexer &&that ) {
     212                deleteRef( tables );
     213
     214                tables = that.tables;
     215                scope = that.scope;
     216                doDebug = that.doDebug;
     217
     218                that.tables = 0;
     219
     220                return *this;
     221        }
     222
     223        void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const {
     224                std::unordered_set< std::string > foundMangleNames;
     225
     226                Indexer::Impl *searchTables = tables;
     227                while ( searchTables ) {
     228
     229                        IdTable::const_iterator decls = searchTables->idTable.find( id );
     230                        if ( decls != searchTables->idTable.end() ) {
     231                                const MangleTable &mangleTable = decls->second;
     232                                for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
     233                                        // mark the mangled name as found, skipping this insertion if a declaration for that name has already been found
     234                                        if ( foundMangleNames.insert( decl->first ).second == false ) continue;
     235
     236                                        out.push_back( decl->second );
     237                                }
     238                        }
     239
     240                        // get declarations from base indexers
     241                        searchTables = searchTables->base.tables;
     242                }
     243
     244                // some special functions, e.g. constructors and destructors
     245                // remove autogenerated functions when they are defined so that
     246                // they can never be matched
     247                removeSpecialOverrides( id, out );
     248        }
     249
     250        NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
     251                if ( ! tables ) return 0;
     252
     253                TypeTable::const_iterator ret = tables->typeTable.find( id );
     254                return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id );
     255        }
     256
     257        StructDecl *Indexer::lookupStruct( const std::string &id ) const {
     258                if ( ! tables ) return 0;
     259
     260                StructTable::const_iterator ret = tables->structTable.find( id );
     261                return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id );
     262        }
     263
     264        EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
     265                if ( ! tables ) return 0;
     266
     267                EnumTable::const_iterator ret = tables->enumTable.find( id );
     268                return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id );
     269        }
     270
     271        UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
     272                if ( ! tables ) return 0;
     273
     274                UnionTable::const_iterator ret = tables->unionTable.find( id );
     275                return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id );
     276        }
     277
     278        TraitDecl *Indexer::lookupTrait( const std::string &id ) const {
     279                if ( ! tables ) return 0;
     280
     281                TraitTable::const_iterator ret = tables->traitTable.find( id );
     282                return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id );
     283        }
     284
     285        const Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
     286                if ( ! tables ) return nullptr;
     287                if ( tables->scope < scope ) return nullptr;
     288
     289                IdTable::const_iterator decls = tables->idTable.find( id );
     290                if ( decls != tables->idTable.end() ) {
     291                        const MangleTable &mangleTable = decls->second;
     292                        MangleTable::const_iterator decl = mangleTable.find( mangleName );
     293                        if ( decl != mangleTable.end() ) return &decl->second;
     294                }
     295
     296                return tables->base.lookupIdAtScope( id, mangleName, scope );
     297        }
     298
     299        Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) {
     300                return const_cast<IdData *>(const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope ));
     301        }
     302
     303        bool Indexer::hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
     304                if ( ! tables ) return false;
     305                if ( tables->scope < scope ) return false;
     306
     307                IdTable::const_iterator decls = tables->idTable.find( id );
     308                if ( decls != tables->idTable.end() ) {
     309                        const MangleTable &mangleTable = decls->second;
     310                        for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
     311                                // check for C decls with the same name, skipping those with a compatible type (by mangleName)
     312                                if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first != mangleName ) return true;
     313                        }
     314                }
     315
     316                return tables->base.hasIncompatibleCDecl( id, mangleName, scope );
     317        }
     318
     319        bool Indexer::hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
     320                if ( ! tables ) return false;
     321                if ( tables->scope < scope ) return false;
     322
     323                IdTable::const_iterator decls = tables->idTable.find( id );
     324                if ( decls != tables->idTable.end() ) {
     325                        const MangleTable &mangleTable = decls->second;
     326                        for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
     327                                // check for C decls with the same name, skipping
     328                                // those with an incompatible type (by mangleName)
     329                                if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first == mangleName ) return true;
     330                        }
     331                }
     332
     333                return tables->base.hasCompatibleCDecl( id, mangleName, scope );
     334        }
     335
     336        NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const {
     337                if ( ! tables ) return 0;
     338                if ( tables->scope < scope ) return 0;
     339
     340                TypeTable::const_iterator ret = tables->typeTable.find( id );
     341                return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope );
     342        }
     343
     344        StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const {
     345                if ( ! tables ) return 0;
     346                if ( tables->scope < scope ) return 0;
     347
     348                StructTable::const_iterator ret = tables->structTable.find( id );
     349                return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope );
     350        }
     351
     352        EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const {
     353                if ( ! tables ) return 0;
     354                if ( tables->scope < scope ) return 0;
     355
     356                EnumTable::const_iterator ret = tables->enumTable.find( id );
     357                return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope );
     358        }
     359
     360        UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const {
     361                if ( ! tables ) return 0;
     362                if ( tables->scope < scope ) return 0;
     363
     364                UnionTable::const_iterator ret = tables->unionTable.find( id );
     365                return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope );
     366        }
     367
     368        TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const {
     369                if ( ! tables ) return 0;
     370                if ( tables->scope < scope ) return 0;
     371
     372                TraitTable::const_iterator ret = tables->traitTable.find( id );
     373                return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope );
     374        }
     375
     376        bool isFunction( DeclarationWithType * decl ) {
    191377                return GenPoly::getFunctionType( decl->get_type() );
    192378        }
    193379
    194         bool isObject( const DeclarationWithType * decl ) {
     380        bool isObject( DeclarationWithType * decl ) {
    195381                return ! isFunction( decl );
    196382        }
    197383
    198         bool isDefinition( const DeclarationWithType * decl ) {
    199                 if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
     384        bool isDefinition( DeclarationWithType * decl ) {
     385                if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
    200386                        // a function is a definition if it has a body
    201387                        return func->statements;
     
    207393        }
    208394
    209 
    210         bool Indexer::addedIdConflicts(
    211                         const Indexer::IdData & existing, const DeclarationWithType * added,
    212                         Indexer::OnConflict handleConflicts, const Declaration * deleteStmt ) {
    213                 // if we're giving the same name mangling to things of different types then there is
    214                 // something wrong
     395        bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) {
     396                // if we're giving the same name mangling to things of different types then there is something wrong
    215397                assert( (isObject( added ) && isObject( existing.id ) )
    216398                        || ( isFunction( added ) && isFunction( existing.id ) ) );
    217399
    218                 if ( LinkageSpec::isOverridable( existing.id->linkage ) ) {
     400                if ( LinkageSpec::isOverridable( existing.id->get_linkage() ) ) {
    219401                        // new definition shadows the autogenerated one, even at the same scope
    220402                        return false;
    221                 } else if ( LinkageSpec::isMangled( added->linkage )
    222                                 || ResolvExpr::typesCompatible(
    223                                         added->get_type(), existing.id->get_type(), Indexer() ) ) {
     403                } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) {
    224404
    225405                        // it is a conflict if one declaration is deleted and the other is not
    226406                        if ( deleteStmt && ! existing.deleteStmt ) {
    227                                 if ( handleConflicts.mode == OnConflict::Error ) {
    228                                         SemanticError( added, "deletion of defined identifier " );
    229                                 }
    230                                 return true;
     407                                return handleConflicts( existing, "deletion of defined identifier " );
    231408                        } else if ( ! deleteStmt && existing.deleteStmt ) {
    232                                 if ( handleConflicts.mode == OnConflict::Error ) {
    233                                         SemanticError( added, "definition of deleted identifier " );
    234                                 }
    235                                 return true;
     409                                return handleConflicts( existing, "definition of deleted identifier " );
    236410                        }
    237411
    238412                        if ( isDefinition( added ) && isDefinition( existing.id ) ) {
    239                                 if ( handleConflicts.mode == OnConflict::Error ) {
    240                                         SemanticError( added,
    241                                                 isFunction( added ) ?
    242                                                         "duplicate function definition for " :
    243                                                         "duplicate object definition for " );
    244                                 }
    245                                 return true;
     413                                if ( isFunction( added ) ) {
     414                                        return handleConflicts( existing, "duplicate function definition for " );
     415                                } else {
     416                                        return handleConflicts( existing, "duplicate object definition for " );
     417                                } // if
    246418                        } // if
    247419                } else {
    248                         if ( handleConflicts.mode == OnConflict::Error ) {
    249                                 SemanticError( added, "duplicate definition for " );
    250                         }
    251                         return true;
     420                        return handleConflicts( existing, "duplicate definition for " );
    252421                } // if
    253422
     
    255424        }
    256425
    257         bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const {
    258                 if ( ! idTable ) return false;
    259 
    260                 ++* stats().map_lookups;
    261                 auto decls = idTable->find( id );
    262                 if ( decls == idTable->end() ) return false;
    263 
    264                 for ( auto decl : *(decls->second) ) {
    265                         // skip other scopes (hidden by this decl)
    266                         if ( decl.second.scope != scope ) continue;
    267                         // check for C decl with compatible type (by mangleName)
    268                         if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first == mangleName ) {
    269                                 return true;
    270                         }
    271                 }
    272 
    273                 return false;
    274         }
    275 
    276         bool Indexer::hasIncompatibleCDecl(const std::string & id, const std::string &mangleName ) const {
    277                 if ( ! idTable ) return false;
    278 
    279                 ++* stats().map_lookups;
    280                 auto decls = idTable->find( id );
    281                 if ( decls == idTable->end() ) return false;
    282 
    283                 for ( auto decl : *(decls->second) ) {
    284                         // skip other scopes (hidden by this decl)
    285                         if ( decl.second.scope != scope ) continue;
    286                         // check for C decl with incompatible type (by manglename)
    287                         if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first != mangleName ) {
    288                                 return true;
    289                         }
    290                 }
    291 
    292                 return false;
    293         }
    294 
    295         /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function
    296         std::string getOtypeKey( const FunctionDecl * function ) {
    297                 auto& params = function->type->parameters;
    298                 assert( ! params.empty() );
    299                 // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    300                 Type * base = InitTweak::getPointerBase( params.front()->get_type() );
    301                 assert( base );
    302                 return Mangler::mangle( base );
    303         }
    304 
    305         /// gets the declaration for the function acting on a type specified by otype key,
    306         /// nullptr if none such
    307         const FunctionDecl * getFunctionForOtype( const DeclarationWithType * decl, const std::string& otypeKey ) {
    308                 const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl );
    309                 if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr;
    310                 return func;
    311         }
    312 
    313         bool Indexer::removeSpecialOverrides(Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) {
    314                 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which
    315                 // determinethe set of ctor/dtor/assign that can be used  by the requester. In particular,
    316                 // if the user defines a default ctor, then the generated default ctor is unavailable,
    317                 // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated
    318                 // field ctors are available. If the user defines any ctor then the generated default ctor
    319                 // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines
    320                 // anything that looks like a copy constructor, then the generated copy constructor is
    321                 // unavailable, and likewise for the assignment operator.
    322 
    323                 // only relevant on function declarations
    324                 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( data.id );
    325                 if ( ! function ) return true;
    326                 // only need to perform this check for constructors, destructors, and assignment functions
    327                 if ( ! CodeGen::isCtorDtorAssign( data.id->name ) ) return true;
    328 
    329                 // set up information for this type
    330                 bool dataIsUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
    331                 bool dataIsCopyFunc = InitTweak::isCopyFunction( function, function->name );
    332                 std::string dataOtypeKey = getOtypeKey( function );
    333 
    334                 if ( dataIsUserDefinedFunc && dataIsCopyFunc ) {
    335                         // this is a user-defined copy function
    336                         // if this is the first such, delete/remove non-user-defined overloads as needed
    337                         std::vector< std::string > removed;
    338                         std::vector< MangleTable::value_type > deleted;
    339                         bool alreadyUserDefinedFunc = false;
    340 
    341                         for ( const auto& entry : * mangleTable ) {
    342                                 // skip decls that aren't functions or are for the wrong type
    343                                 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
    344                                 if ( ! decl ) continue;
    345 
    346                                 bool isCopyFunc = InitTweak::isCopyFunction( decl, decl->name );
    347                                 if ( ! LinkageSpec::isOverridable( decl->linkage ) ) {
    348                                         // matching user-defined function
    349                                         if ( isCopyFunc ) {
    350                                                 // mutation already performed, return early
    351                                                 return true;
    352                                         } else {
    353                                                 // note that non-copy deletions already performed
    354                                                 alreadyUserDefinedFunc = true;
    355                                         }
    356                                 } else {
    357                                         // non-user-defined function; mark for deletion/removal as appropriate
    358                                         if ( isCopyFunc ) {
    359                                                 removed.push_back( entry.first );
    360                                         } else if ( ! alreadyUserDefinedFunc ) {
    361                                                 deleted.push_back( entry );
    362                                         }
    363                                 }
    364                         }
    365 
    366                         // perform removals from mangle table, and deletions if necessary
    367                         for ( const auto& key : removed ) {
    368                                 ++* stats().map_mutations;
    369                                 mangleTable = mangleTable->erase( key );
    370                         }
    371                         if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) {
    372                                 ++* stats().map_mutations;
    373                                 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
    374                         }
    375                 } else if ( dataIsUserDefinedFunc ) {
    376                         // this is a user-defined non-copy function
    377                         // if this is the first user-defined function, delete non-user-defined overloads
    378                         std::vector< MangleTable::value_type > deleted;
    379 
    380                         for ( const auto& entry : * mangleTable ) {
    381                                 // skip decls that aren't functions or are for the wrong type
    382                                 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
    383                                 if ( ! decl ) continue;
    384 
    385                                 // exit early if already a matching user-defined function;
    386                                 // earlier function will have mutated table
    387                                 if ( ! LinkageSpec::isOverridable( decl->linkage ) ) return true;
    388 
    389                                 // skip mutating intrinsic functions
    390                                 if ( decl->linkage == LinkageSpec::Intrinsic ) continue;
    391 
    392                                 // user-defined non-copy functions do not override copy functions
    393                                 if ( InitTweak::isCopyFunction( decl, decl->name ) ) continue;
    394 
    395                                 // this function to be deleted after mangleTable iteration is complete
    396                                 deleted.push_back( entry );
    397                         }
    398 
    399                         // mark deletions to update mangle table
    400                         // this needs to be a separate loop because of iterator invalidation
    401                         for ( const auto& entry : deleted ) {
    402                                 ++* stats().map_mutations;
    403                                 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
    404                         }
    405                 } else if ( function->linkage != LinkageSpec::Intrinsic ) {
    406                         // this is an overridable generated function
    407                         // if there already exists a matching user-defined function, delete this appropriately
    408                         for ( const auto& entry : * mangleTable ) {
    409                                 // skip decls that aren't functions or are for the wrong type
    410                                 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
    411                                 if ( ! decl ) continue;
    412 
    413                                 // skip non-user-defined functions
    414                                 if ( LinkageSpec::isOverridable( decl->linkage ) ) continue;
    415 
    416                                 if ( dataIsCopyFunc ) {
    417                                         // remove current function if exists a user-defined copy function
    418                                         // since the signatures for copy functions don't need to match exactly, using
    419                                         // a delete statement is the wrong approach
    420                                         if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false;
    421                                 } else {
    422                                         // mark current function deleted by first user-defined function found
    423                                         data.deleteStmt = decl;
    424                                         return true;
    425                                 }
    426                         }
    427                 }
    428 
    429                 // nothing (more) to fix, return true
    430                 return true;
    431         }
    432 
    433         void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr,
    434                         const Declaration * deleteStmt ) {
    435                 ++* stats().add_calls;
     426        void Indexer::addId( DeclarationWithType *decl, ConflictFunction handleConflicts, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) {
     427                if ( decl->name == "" ) return;
     428                debugPrint( "Adding Id " << decl->name << std::endl );
     429                makeWritable();
     430
    436431                const std::string &name = decl->name;
    437                 if ( name == "" ) return;
    438 
    439432                std::string mangleName;
    440433                if ( LinkageSpec::isOverridable( decl->linkage ) ) {
    441                         // mangle the name without including the appropriate suffix, so overridable routines
    442                         // are placed into the same "bucket" as their user defined versions.
     434                        // mangle the name without including the appropriate suffix, so overridable routines are placed into the
     435                        // same "bucket" as their user defined versions.
    443436                        mangleName = Mangler::mangle( decl, false );
    444437                } else {
     
    446439                } // if
    447440
    448                 // this ensures that no two declarations with the same unmangled name at the same scope
    449                 // both have C linkage
    450                 if ( LinkageSpec::isMangled( decl->linkage ) ) {
     441                // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage
     442                if ( ! LinkageSpec::isMangled( decl->linkage ) ) {
     443                        // NOTE this is broken in Richard's original code in such a way that it never triggers (it
     444                        // doesn't check decls that have the same manglename, and all C-linkage decls are defined to
     445                        // have their name as their manglename, hence the error can never trigger).
     446                        // The code here is closer to correct, but name mangling would have to be completely
     447                        // isomorphic to C type-compatibility, which it may not be.
     448                        if ( hasIncompatibleCDecl( name, mangleName, scope ) ) {
     449                                SemanticError( decl, "conflicting overload of C function " );
     450                        }
     451                } else {
    451452                        // Check that a Cforall declaration doesn't override any C declaration
    452                         if ( hasCompatibleCDecl( name, mangleName ) ) {
     453                        if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
    453454                                SemanticError( decl, "Cforall declaration hides C function " );
    454455                        }
    455                 } else {
    456                         // NOTE: only correct if name mangling is completely isomorphic to C
    457                         // type-compatibility, which it may not be.
    458                         if ( hasIncompatibleCDecl( name, mangleName ) ) {
    459                                 SemanticError( decl, "conflicting overload of C function " );
    460                         }
    461                 }
    462 
    463                 // ensure tables exist and add identifier
    464                 MangleTable::Ptr mangleTable;
    465                 if ( ! idTable ) {
    466                         idTable = IdTable::new_ptr();
    467                         mangleTable = MangleTable::new_ptr();
    468                 } else {
    469                         ++* stats().map_lookups;
    470                         auto decls = idTable->find( name );
    471                         if ( decls == idTable->end() ) {
    472                                 mangleTable = MangleTable::new_ptr();
    473                         } else {
    474                                 mangleTable = decls->second;
    475                                 // skip in-scope repeat declarations of same identifier
    476                                 ++* stats().map_lookups;
    477                                 auto existing = mangleTable->find( mangleName );
    478                                 if ( existing != mangleTable->end()
    479                                                 && existing->second.scope == scope
    480                                                 && existing->second.id ) {
    481                                         if ( addedIdConflicts( existing->second, decl, handleConflicts, deleteStmt ) ) {
    482                                                 if ( handleConflicts.mode == OnConflict::Delete ) {
    483                                                         // set delete expression for conflicting identifier
    484                                                         lazyInitScope();
    485                                                         * stats().map_mutations += 2;
    486                                                         idTable = idTable->set(
    487                                                                 name,
    488                                                                 mangleTable->set(
    489                                                                         mangleName,
    490                                                                         IdData{ existing->second, handleConflicts.deleteStmt } ) );
    491                                                 }
    492                                                 return;
    493                                         }
    494                                 }
    495                         }
    496                 }
    497 
    498                 // add/overwrite with new identifier
    499                 lazyInitScope();
    500                 IdData data{ decl, baseExpr, deleteStmt, scope };
    501                 // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary
    502                 if ( ! removeSpecialOverrides( data, mangleTable ) ) return;
    503                 * stats().map_mutations += 2;
    504                 idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) );
    505         }
    506 
    507         void Indexer::addId( const DeclarationWithType * decl, const Expression * baseExpr ) {
     456                }
     457
     458                // Skip repeat declarations of the same identifier
     459                IdData * existing = lookupIdAtScope( name, mangleName, scope );
     460                if ( existing && existing->id && addedIdConflicts( *existing, decl, deleteStmt, handleConflicts ) ) return;
     461
     462                // add to indexer
     463                tables->idTable[ name ][ mangleName ] = IdData{ decl, baseExpr, deleteStmt };
     464                ++tables->size;
     465        }
     466
     467        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
    508468                // default handling of conflicts is to raise an error
    509                 addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
    510         }
    511 
    512         void Indexer::addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt ) {
     469                addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );
     470        }
     471
     472        void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
    513473                // default handling of conflicts is to raise an error
    514                 addId( decl, OnConflict::error(), nullptr, deleteStmt );
    515         }
    516 
    517         bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) {
    518                 if ( existing->base == nullptr ) {
     474                addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );
     475        }
     476
     477        bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
     478                if ( existing->get_base() == 0 ) {
    519479                        return false;
    520                 } else if ( added->base == nullptr ) {
     480                } else if ( added->get_base() == 0 ) {
    521481                        return true;
    522482                } else {
    523                         assert( existing->base && added->base );
    524                         // typedef redeclarations are errors only if types are different
    525                         if ( ! ResolvExpr::typesCompatible( existing->base, added->base, Indexer() ) ) {
    526                                 SemanticError( added->location, "redeclaration of " + added->name );
    527                         }
    528                 }
    529                 // does not need to be added to the table if both existing and added have a base that are
    530                 // the same
    531                 return true;
    532         }
    533 
    534         void Indexer::addType( const NamedTypeDecl * decl ) {
    535                 ++* stats().add_calls;
    536                 const std::string & id = decl->name;
    537 
    538                 if ( ! typeTable ) {
    539                         typeTable = TypeTable::new_ptr();
    540                 } else {
    541                         ++* stats().map_lookups;
    542                         auto existing = typeTable->find( id );
    543                         if ( existing != typeTable->end()
    544                                 && existing->second.scope == scope
    545                                 && addedTypeConflicts( existing->second.decl, decl ) ) return;
    546                 }
    547 
    548                 lazyInitScope();
    549                 ++* stats().map_mutations;
    550                 typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } );
    551         }
    552 
    553         bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) {
     483                        SemanticError( added, "redeclaration of " );
     484                }
     485        }
     486
     487        void Indexer::addType( NamedTypeDecl *decl ) {
     488                debugPrint( "Adding type " << decl->name << std::endl );
     489                makeWritable();
     490
     491                const std::string &id = decl->get_name();
     492                TypeTable::iterator existing = tables->typeTable.find( id );
     493                if ( existing == tables->typeTable.end() ) {
     494                        NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope );
     495                        if ( ! parent || ! addedTypeConflicts( parent, decl ) ) {
     496                                tables->typeTable.insert( existing, std::make_pair( id, decl ) );
     497                                ++tables->size;
     498                        }
     499                } else {
     500                        if ( ! addedTypeConflicts( existing->second, decl ) ) {
     501                                existing->second = decl;
     502                        }
     503                }
     504        }
     505
     506        bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) {
    554507                if ( ! existing->body ) {
    555508                        return false;
     
    560513        }
    561514
    562         void Indexer::addStruct( const std::string & id ) {
     515        void Indexer::addStruct( const std::string &id ) {
     516                debugPrint( "Adding fwd decl for struct " << id << std::endl );
    563517                addStruct( new StructDecl( id ) );
    564518        }
    565519
    566         void Indexer::addStruct( const StructDecl * decl ) {
    567                 ++* stats().add_calls;
    568                 const std::string & id = decl->name;
    569 
    570                 if ( ! structTable ) {
    571                         structTable = StructTable::new_ptr();
    572                 } else {
    573                         ++* stats().map_lookups;
    574                         auto existing = structTable->find( id );
    575                         if ( existing != structTable->end()
    576                                 && existing->second.scope == scope
    577                                 && addedDeclConflicts( existing->second.decl, decl ) ) return;
    578                 }
    579 
    580                 lazyInitScope();
    581                 ++* stats().map_mutations;
    582                 structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } );
    583         }
    584 
    585         void Indexer::addEnum( const EnumDecl * decl ) {
    586                 ++* stats().add_calls;
    587                 const std::string & id = decl->name;
    588 
    589                 if ( ! enumTable ) {
    590                         enumTable = EnumTable::new_ptr();
    591                 } else {
    592                         ++* stats().map_lookups;
    593                         auto existing = enumTable->find( id );
    594                         if ( existing != enumTable->end()
    595                                 && existing->second.scope == scope
    596                                 && addedDeclConflicts( existing->second.decl, decl ) ) return;
    597                 }
    598 
    599                 lazyInitScope();
    600                 ++* stats().map_mutations;
    601                 enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } );
    602         }
    603 
    604         void Indexer::addUnion( const std::string & id ) {
     520        void Indexer::addStruct( StructDecl *decl ) {
     521                debugPrint( "Adding struct " << decl->name << std::endl );
     522                makeWritable();
     523
     524                const std::string &id = decl->get_name();
     525                StructTable::iterator existing = tables->structTable.find( id );
     526                if ( existing == tables->structTable.end() ) {
     527                        StructDecl *parent = tables->base.lookupStructAtScope( id, scope );
     528                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     529                                tables->structTable.insert( existing, std::make_pair( id, decl ) );
     530                                ++tables->size;
     531                        }
     532                } else {
     533                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     534                                existing->second = decl;
     535                        }
     536                }
     537        }
     538
     539        void Indexer::addEnum( EnumDecl *decl ) {
     540                debugPrint( "Adding enum " << decl->name << std::endl );
     541                makeWritable();
     542
     543                const std::string &id = decl->get_name();
     544                EnumTable::iterator existing = tables->enumTable.find( id );
     545                if ( existing == tables->enumTable.end() ) {
     546                        EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope );
     547                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     548                                tables->enumTable.insert( existing, std::make_pair( id, decl ) );
     549                                ++tables->size;
     550                        }
     551                } else {
     552                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     553                                existing->second = decl;
     554                        }
     555                }
     556        }
     557
     558        void Indexer::addUnion( const std::string &id ) {
     559                debugPrint( "Adding fwd decl for union " << id << std::endl );
    605560                addUnion( new UnionDecl( id ) );
    606561        }
    607562
    608         void Indexer::addUnion( const UnionDecl * decl ) {
    609                 ++* stats().add_calls;
    610                 const std::string & id = decl->name;
    611 
    612                 if ( ! unionTable ) {
    613                         unionTable = UnionTable::new_ptr();
    614                 } else {
    615                         ++* stats().map_lookups;
    616                         auto existing = unionTable->find( id );
    617                         if ( existing != unionTable->end()
    618                                 && existing->second.scope == scope
    619                                 && addedDeclConflicts( existing->second.decl, decl ) ) return;
    620                 }
    621 
    622                 lazyInitScope();
    623                 ++* stats().map_mutations;
    624                 unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } );
    625         }
    626 
    627         void Indexer::addTrait( const TraitDecl * decl ) {
    628                 ++* stats().add_calls;
    629                 const std::string & id = decl->name;
    630 
    631                 if ( ! traitTable ) {
    632                         traitTable = TraitTable::new_ptr();
    633                 } else {
    634                         ++* stats().map_lookups;
    635                         auto existing = traitTable->find( id );
    636                         if ( existing != traitTable->end()
    637                                 && existing->second.scope == scope
    638                                 && addedDeclConflicts( existing->second.decl, decl ) ) return;
    639                 }
    640 
    641                 lazyInitScope();
    642                 ++* stats().map_mutations;
    643                 traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } );
    644         }
    645 
    646         void Indexer::addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ) {
     563        void Indexer::addUnion( UnionDecl *decl ) {
     564                debugPrint( "Adding union " << decl->name << std::endl );
     565                makeWritable();
     566
     567                const std::string &id = decl->get_name();
     568                UnionTable::iterator existing = tables->unionTable.find( id );
     569                if ( existing == tables->unionTable.end() ) {
     570                        UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );
     571                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     572                                tables->unionTable.insert( existing, std::make_pair( id, decl ) );
     573                                ++tables->size;
     574                        }
     575                } else {
     576                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     577                                existing->second = decl;
     578                        }
     579                }
     580        }
     581
     582        void Indexer::addTrait( TraitDecl *decl ) {
     583                debugPrint( "Adding trait " << decl->name << std::endl );
     584                makeWritable();
     585
     586                const std::string &id = decl->get_name();
     587                TraitTable::iterator existing = tables->traitTable.find( id );
     588                if ( existing == tables->traitTable.end() ) {
     589                        TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );
     590                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     591                                tables->traitTable.insert( existing, std::make_pair( id, decl ) );
     592                                ++tables->size;
     593                        }
     594                } else {
     595                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     596                                existing->second = decl;
     597                        }
     598                }
     599        }
     600
     601        void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction handleConflicts ) {
    647602                for ( Declaration * decl : aggr->members ) {
    648603                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    649604                                addId( dwt, handleConflicts, expr );
    650605                                if ( dwt->name == "" ) {
    651                                         const Type * t = dwt->get_type()->stripReferences();
    652                                         if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) {
     606                                        Type * t = dwt->get_type()->stripReferences();
     607                                        if ( dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ) ) {
    653608                                                Expression * base = expr->clone();
    654609                                                ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost?
     
    661616        }
    662617
    663         void Indexer::addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt ) {
    664                 for ( const Expression * expr : withExprs ) {
     618        void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ) {
     619                for ( Expression * expr : withExprs ) {
    665620                        if ( expr->result ) {
    666621                                AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
    667622                                assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
    668623
    669                                 addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) );
     624                                addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) {
     625                                        // on conflict, delete the identifier
     626                                        existing.deleteStmt = withStmt;
     627                                        return true;
     628                                });
    670629                        }
    671630                }
     
    685644        }
    686645
    687         void Indexer::addFunctionType( const FunctionType * ftype ) {
     646        void Indexer::addFunctionType( FunctionType * ftype ) {
    688647                addTypes( ftype->forall );
    689648                addIds( ftype->returnVals );
    690649                addIds( ftype->parameters );
     650        }
     651
     652        void Indexer::enterScope() {
     653                ++scope;
     654
     655                if ( doDebug ) {
     656                        std::cerr << "--- Entering scope " << scope << std::endl;
     657                }
     658        }
     659
     660        void Indexer::leaveScope() {
     661                using std::cerr;
     662
     663                assert( scope > 0 && "cannot leave initial scope" );
     664                if ( doDebug ) {
     665                        cerr << "--- Leaving scope " << scope << " containing" << std::endl;
     666                }
     667                --scope;
     668
     669                while ( tables && tables->scope > scope ) {
     670                        if ( doDebug ) {
     671                                dump( tables->idTable, cerr );
     672                                dump( tables->typeTable, cerr );
     673                                dump( tables->structTable, cerr );
     674                                dump( tables->enumTable, cerr );
     675                                dump( tables->unionTable, cerr );
     676                                dump( tables->traitTable, cerr );
     677                        }
     678
     679                        // swap tables for base table until we find one at an appropriate scope
     680                        Indexer::Impl *base = newRef( tables->base.tables );
     681                        deleteRef( tables );
     682                        tables = base;
     683                }
     684        }
     685
     686        void Indexer::print( std::ostream &os, int indent ) const {
     687                using std::cerr;
     688
     689                if ( tables ) {
     690                        os << "--- scope " << tables->scope << " ---" << std::endl;
     691
     692                        os << "===idTable===" << std::endl;
     693                        dump( tables->idTable, os );
     694                        os << "===typeTable===" << std::endl;
     695                        dump( tables->typeTable, os );
     696                        os << "===structTable===" << std::endl;
     697                        dump( tables->structTable, os );
     698                        os << "===enumTable===" << std::endl;
     699                        dump( tables->enumTable, os );
     700                        os << "===unionTable===" << std::endl;
     701                        dump( tables->unionTable, os );
     702                        os << "===contextTable===" << std::endl;
     703                        dump( tables->traitTable, os );
     704
     705                        tables->base.print( os, indent );
     706                } else {
     707                        os << "--- end ---" << std::endl;
     708                }
     709
    691710        }
    692711
     
    696715                        Expression * base = baseExpr->clone();
    697716                        ResolvExpr::referenceToRvalueConversion( base, cost );
    698                         ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base );
     717                        ret = new MemberExpr( id, base );
    699718                        // xxx - this introduces hidden environments, for now remove them.
    700719                        // std::swap( base->env, ret->env );
     
    702721                        base->env = nullptr;
    703722                } else {
    704                         ret = new VariableExpr( const_cast<DeclarationWithType *>(id) );
    705                 }
    706                 if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<Declaration *>(deleteStmt) );
     723                        ret = new VariableExpr( id );
     724                }
     725                if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt );
    707726                return ret;
    708727        }
  • src/SymTab/Indexer.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:38:55 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Mar  8 13:55:00 2019
    13 // Update Count     : 9
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Aug 17 16:09:12 2017
     13// Update Count     : 8
    1414//
    1515
    1616#pragma once
    1717
    18 #include <functional>              // for function
    19 #include <list>                    // for list
    20 #include <memory>                  // for shared_ptr, enable_shared_from_this
    21 #include <string>                  // for string
     18#include <iosfwd>             // for ostream
     19#include <list>               // for list
     20#include <string>             // for string
     21#include <functional>         // for function
    2222
    23 #include "Common/PersistentMap.h"  // for PersistentMap
    24 #include "SynTree/SynTree.h"       // for AST nodes
     23#include "SynTree/Visitor.h"  // for Visitor
     24#include "SynTree/SynTree.h"  // for AST nodes
    2525
    2626namespace ResolvExpr {
    27         class Cost;
     27class Cost;
    2828}
    2929
    3030namespace SymTab {
    31         class Indexer : public std::enable_shared_from_this<SymTab::Indexer> {
    32         public:
     31        class Indexer {
     32          public:
    3333                explicit Indexer();
     34
     35                Indexer( const Indexer &that );
     36                Indexer( Indexer &&that );
    3437                virtual ~Indexer();
     38                Indexer& operator= ( const Indexer &that );
     39                Indexer& operator= ( Indexer &&that );
    3540
    36                 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to
    37                 // tell the indexer explicitly when scopes begin and end
     41                // when using an indexer manually (e.g., within a mutator traversal), it is necessary to tell the indexer
     42                // explicitly when scopes begin and end
    3843                void enterScope();
    3944                void leaveScope();
    4045
    4146                struct IdData {
    42                         const DeclarationWithType * id = nullptr;
    43                         const Expression * baseExpr = nullptr; // WithExpr
     47                        DeclarationWithType * id = nullptr;
     48                        Expression * baseExpr = nullptr; // WithExpr
    4449
    4550                        /// non-null if this declaration is deleted
    46                         const Declaration * deleteStmt = nullptr;
    47                         /// scope of identifier
    48                         unsigned long scope = 0;
     51                        BaseSyntaxNode * deleteStmt = nullptr;
    4952
    5053                        // NOTE: shouldn't need either of these constructors, but gcc-4 does not properly support initializer lists with default members.
    5154                        IdData() = default;
    52                         IdData(
    53                                 const DeclarationWithType * id, const Expression * baseExpr, const Declaration * deleteStmt,
    54                                 unsigned long scope )
    55                                 : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {}
    56                         IdData( const IdData& o, const Declaration * deleteStmt )
    57                                 : id( o.id ), baseExpr( o.baseExpr ), deleteStmt( deleteStmt ), scope( o.scope ) {}
     55                        IdData( DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ) {}
    5856
    5957                        Expression * combine( ResolvExpr::Cost & cost ) const;
     
    6159
    6260                /// Gets all declarations with the given ID
    63                 void lookupId( const std::string & id, std::list< IdData > &out ) const;
     61                void lookupId( const std::string &id, std::list< IdData > &out ) const;
    6462                /// Gets the top-most type declaration with the given ID
    65                 const NamedTypeDecl * lookupType( const std::string & id ) const;
     63                NamedTypeDecl *lookupType( const std::string &id ) const;
    6664                /// Gets the top-most struct declaration with the given ID
    67                 const StructDecl * lookupStruct( const std::string & id ) const;
     65                StructDecl *lookupStruct( const std::string &id ) const;
    6866                /// Gets the top-most enum declaration with the given ID
    69                 const EnumDecl * lookupEnum( const std::string & id ) const;
     67                EnumDecl *lookupEnum( const std::string &id ) const;
    7068                /// Gets the top-most union declaration with the given ID
    71                 const UnionDecl * lookupUnion( const std::string & id ) const;
     69                UnionDecl *lookupUnion( const std::string &id ) const;
    7270                /// Gets the top-most trait declaration with the given ID
    73                 const TraitDecl * lookupTrait( const std::string & id ) const;
     71                TraitDecl *lookupTrait( const std::string &id ) const;
    7472
    75                 /// Gets the type declaration with the given ID at global scope
    76                 const NamedTypeDecl * globalLookupType( const std::string & id ) const;
    77                 /// Gets the struct declaration with the given ID at global scope
    78                 const StructDecl * globalLookupStruct( const std::string & id ) const;
    79                 /// Gets the union declaration with the given ID at global scope
    80                 const UnionDecl * globalLookupUnion( const std::string & id ) const;
    81                 /// Gets the enum declaration with the given ID at global scope
    82                 const EnumDecl * globalLookupEnum( const std::string & id ) const;
     73                void print( std::ostream &os, int indent = 0 ) const;
    8374
    84                 void addId( const DeclarationWithType * decl, const Expression * baseExpr = nullptr );
    85                 void addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt );
     75                /// looks up a specific mangled ID at the given scope
     76                IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope );
     77                const IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     78                /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
     79                bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     80                /// returns true if there exists a declaration with C linkage and the given name with the same mangled name
     81                bool hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     82                // equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope)
     83                NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const;
     84                StructDecl *lookupStructAtScope( const std::string &id, unsigned long scope ) const;
     85                EnumDecl *lookupEnumAtScope( const std::string &id, unsigned long scope ) const;
     86                UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const;
     87                TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
    8688
    87                 void addType( const NamedTypeDecl * decl );
    88                 void addStruct( const std::string & id );
    89                 void addStruct( const StructDecl * decl );
    90                 void addEnum( const EnumDecl * decl );
    91                 void addUnion( const std::string & id );
    92                 void addUnion( const UnionDecl * decl );
    93                 void addTrait( const TraitDecl * decl );
     89                typedef std::function<bool(IdData &, const std::string &)> ConflictFunction;
     90
     91                void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr );
     92                void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt );
     93
     94                void addType( NamedTypeDecl *decl );
     95                void addStruct( const std::string &id );
     96                void addStruct( StructDecl *decl );
     97                void addEnum( EnumDecl *decl );
     98                void addUnion( const std::string &id );
     99                void addUnion( UnionDecl *decl );
     100                void addTrait( TraitDecl *decl );
    94101
    95102                /// adds all of the IDs from WithStmt exprs
    96                 void addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt );
     103                void addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt );
     104
     105                /// adds all of the members of the Aggregate (addWith helper)
     106                void addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction );
    97107
    98108                /// convenience function for adding a list of Ids to the indexer
     
    103113
    104114                /// convenience function for adding all of the declarations in a function type to the indexer
    105                 void addFunctionType( const FunctionType * ftype );
     115                void addFunctionType( FunctionType * ftype );
    106116
     117                bool doDebug = false; ///< Display debugging trace?
    107118          private:
    108                 /// Wraps a Decl * with a scope
    109                 template<typename Decl>
    110                 struct Scoped {
    111                         const Decl * decl;           ///< declaration
    112                         unsigned long scope;  ///< scope of this declaration
     119                struct Impl;
    113120
    114                         Scoped(const Decl * d, unsigned long s) : decl(d), scope(s) {}
    115                 };
     121                Impl *tables;         ///< Copy-on-write instance of table data structure
     122                unsigned long scope;  ///< Scope index of this pointer
    116123
    117                 using Ptr = std::shared_ptr<const Indexer>;
     124                /// Takes a new ref to a table (returns null if null)
     125                static Impl *newRef( Impl *toClone );
     126                /// Clears a ref to a table (does nothing if null)
     127                static void deleteRef( Impl *toFree );
    118128
    119                 using MangleTable = PersistentMap< std::string, IdData >;
    120                 using IdTable = PersistentMap< std::string, MangleTable::Ptr >;
    121                 using TypeTable = PersistentMap< std::string, Scoped<NamedTypeDecl> >;
    122                 using StructTable = PersistentMap< std::string, Scoped<StructDecl> >;
    123                 using EnumTable = PersistentMap< std::string, Scoped<EnumDecl> >;
    124                 using UnionTable = PersistentMap< std::string, Scoped<UnionDecl> >;
    125                 using TraitTable = PersistentMap< std::string, Scoped<TraitDecl> >;
     129                // Removes matching autogenerated constructors and destructors
     130                // so that they will not be selected
     131                // void removeSpecialOverrides( FunctionDecl *decl );
     132                void removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const;
    126133
    127                 IdTable::Ptr idTable;          ///< identifier namespace
    128                 TypeTable::Ptr typeTable;      ///< type namespace
    129                 StructTable::Ptr structTable;  ///< struct namespace
    130                 EnumTable::Ptr enumTable;      ///< enum namespace
    131                 UnionTable::Ptr unionTable;    ///< union namespace
    132                 TraitTable::Ptr traitTable;    ///< trait namespace
    133 
    134                 Ptr prevScope;                 ///< reference to indexer for parent scope
    135                 unsigned long scope;           ///< Scope index of this indexer
    136                 unsigned long repScope;        ///< Scope index of currently represented scope
    137 
    138                 /// Ensures that a proper backtracking scope exists before a mutation
    139                 void lazyInitScope();
    140 
    141                 /// Gets the indexer at the given scope
    142                 const Indexer * atScope( unsigned long scope ) const;
    143 
    144                 /// Removes matching autogenerated constructors and destructors so that they will not be
    145                 /// selected. If returns false, passed decl should not be added.
    146                 bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable );
    147 
    148                 /// Options for handling identifier conflicts
    149                 struct OnConflict {
    150                         enum {
    151                                 Error,  ///< Throw a semantic error
    152                                 Delete  ///< Delete the earlier version with the delete statement
    153                         } mode;
    154                         const Declaration * deleteStmt;  ///< Statement that deletes this expression
    155 
    156                 private:
    157                         OnConflict() : mode(Error), deleteStmt(nullptr) {}
    158                         OnConflict( const Declaration * d ) : mode(Delete), deleteStmt(d) {}
    159                 public:
    160                         OnConflict( const OnConflict& ) = default;
    161 
    162                         static OnConflict error() { return {}; }
    163                         static OnConflict deleteWith( const Declaration * d ) { return { d }; }
    164                 };
    165 
    166                 /// true if the existing identifier conflicts with the added identifier
    167                 bool addedIdConflicts(
    168                         const IdData & existing, const DeclarationWithType * added, OnConflict handleConflicts,
    169                         const Declaration * deleteStmt );
     134                /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
     135                void makeWritable();
    170136
    171137                /// common code for addId, addDeletedId, etc.
    172                 void addId(const DeclarationWithType * decl, OnConflict handleConflicts,
    173                         const Expression * baseExpr = nullptr, const Declaration * deleteStmt = nullptr );
    174 
    175                 /// adds all of the members of the Aggregate (addWith helper)
    176                 void addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts );
    177 
    178                 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name
    179                 bool hasCompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
    180                 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
    181                 bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
     138                void addId( DeclarationWithType * decl, ConflictFunction, Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr );
    182139        };
    183140} // namespace SymTab
  • src/SymTab/Mangler.cc

    rb067d9b r7951100  
    1010// Created On       : Sun May 17 21:40:29 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul 30 13:46:10 2019
    13 // Update Count     : 26
     12// Last Modified On : Mon Sep 25 15:49:26 2017
     13// Update Count     : 23
    1414//
    1515#include "Mangler.h"
    1616
    17 #include <algorithm>                     // for copy, transform
    18 #include <cassert>                       // for assert, assertf
    19 #include <functional>                    // for const_mem_fun_t, mem_fun
    20 #include <iterator>                      // for ostream_iterator, back_insert_ite...
    21 #include <list>                          // for _List_iterator, list, _List_const...
    22 #include <string>                        // for string, char_traits, operator<<
    23 
    24 #include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
     17#include <algorithm>                // for copy, transform
     18#include <cassert>                  // for assert, assertf
     19#include <functional>               // for const_mem_fun_t, mem_fun
     20#include <iterator>                 // for ostream_iterator, back_insert_ite...
     21#include <list>                     // for _List_iterator, list, _List_const...
     22#include <string>                   // for string, char_traits, operator<<
     23
     24#include "CodeGen/OperatorTable.h"  // for OperatorInfo, operatorLookup
    2525#include "Common/PassVisitor.h"
    26 #include "Common/SemanticError.h"        // for SemanticError
    27 #include "Common/utility.h"              // for toString
    28 #include "Parser/LinkageSpec.h"          // for Spec, isOverridable, AutoGen, Int...
    29 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    30 #include "SynTree/Declaration.h"         // for TypeDecl, DeclarationWithType
    31 #include "SynTree/Expression.h"          // for TypeExpr, Expression, operator<<
    32 #include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
    33 
    34 #include "AST/Pass.hpp"
     26#include "Common/SemanticError.h"   // for SemanticError
     27#include "Common/utility.h"         // for toString
     28#include "Parser/LinkageSpec.h"     // for Spec, isOverridable, AutoGen, Int...
     29#include "SynTree/Declaration.h"    // for TypeDecl, DeclarationWithType
     30#include "SynTree/Expression.h"     // for TypeExpr, Expression, operator<<
     31#include "SynTree/Type.h"           // for Type, ReferenceToType, Type::Fora...
    3532
    3633namespace SymTab {
     
    3835                namespace {
    3936                        /// Mangles names to a unique C identifier
    40                         struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards {
    41                                 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
    42                                 Mangler_old( const Mangler_old & ) = delete;
    43 
    44                                 void previsit( const BaseSyntaxNode * ) { visit_children = false; }
    45 
    46                                 void postvisit( const ObjectDecl * declaration );
    47                                 void postvisit( const FunctionDecl * declaration );
    48                                 void postvisit( const TypeDecl * declaration );
    49 
    50                                 void postvisit( const VoidType * voidType );
    51                                 void postvisit( const BasicType * basicType );
    52                                 void postvisit( const PointerType * pointerType );
    53                                 void postvisit( const ArrayType * arrayType );
    54                                 void postvisit( const ReferenceType * refType );
    55                                 void postvisit( const FunctionType * functionType );
    56                                 void postvisit( const StructInstType * aggregateUseType );
    57                                 void postvisit( const UnionInstType * aggregateUseType );
    58                                 void postvisit( const EnumInstType * aggregateUseType );
    59                                 void postvisit( const TypeInstType * aggregateUseType );
    60                                 void postvisit( const TraitInstType * inst );
    61                                 void postvisit( const TupleType * tupleType );
    62                                 void postvisit( const VarArgsType * varArgsType );
    63                                 void postvisit( const ZeroType * zeroType );
    64                                 void postvisit( const OneType * oneType );
    65                                 void postvisit( const QualifiedType * qualType );
     37                        struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
     38                                Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
     39                                Mangler( const Mangler & ) = delete;
     40
     41                                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     42
     43                                void postvisit( ObjectDecl * declaration );
     44                                void postvisit( FunctionDecl * declaration );
     45                                void postvisit( TypeDecl * declaration );
     46
     47                                void postvisit( VoidType * voidType );
     48                                void postvisit( BasicType * basicType );
     49                                void postvisit( PointerType * pointerType );
     50                                void postvisit( ArrayType * arrayType );
     51                                void postvisit( ReferenceType * refType );
     52                                void postvisit( FunctionType * functionType );
     53                                void postvisit( StructInstType * aggregateUseType );
     54                                void postvisit( UnionInstType * aggregateUseType );
     55                                void postvisit( EnumInstType * aggregateUseType );
     56                                void postvisit( TypeInstType * aggregateUseType );
     57                                void postvisit( TraitInstType * inst );
     58                                void postvisit( TupleType * tupleType );
     59                                void postvisit( VarArgsType * varArgsType );
     60                                void postvisit( ZeroType * zeroType );
     61                                void postvisit( OneType * oneType );
    6662
    6763                                std::string get_mangleName() { return mangleName.str(); }
     
    7672                                bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
    7773                                bool inFunctionType = false;    ///< Include type qualifiers if false.
    78                                 bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
    79 
    80                           public:
    81                                 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    82                                         int nextVarNum, const VarMapType& varNums );
    83 
    84                           private:
    85                                 void mangleDecl( const DeclarationWithType * declaration );
    86                                 void mangleRef( const ReferenceToType * refType, std::string prefix );
    87 
    88                                 void printQualifiers( const Type *type );
    89                         }; // Mangler_old
     74
     75                                void mangleDecl( DeclarationWithType *declaration );
     76                                void mangleRef( ReferenceToType *refType, std::string prefix );
     77
     78                                void printQualifiers( Type *type );
     79                        }; // Mangler
    9080                } // namespace
    9181
    92                 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
    93                         PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
     82                std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
     83                        PassVisitor<Mangler> mangler( mangleOverridable, typeMode, mangleGenericParams );
    9484                        maybeAccept( decl, mangler );
    9585                        return mangler.pass.get_mangleName();
    9686                }
    9787
    98                 std::string mangleType( const Type * ty ) {
    99                         PassVisitor<Mangler_old> mangler( false, true, true );
     88                std::string mangleType( Type * ty ) {
     89                        PassVisitor<Mangler> mangler( false, true, true );
    10090                        maybeAccept( ty, mangler );
    10191                        return mangler.pass.get_mangleName();
    10292                }
    10393
    104                 std::string mangleConcrete( const Type * ty ) {
    105                         PassVisitor<Mangler_old> mangler( false, false, false );
     94                std::string mangleConcrete( Type * ty ) {
     95                        PassVisitor<Mangler> mangler( false, false, false );
    10696                        maybeAccept( ty, mangler );
    10797                        return mangler.pass.get_mangleName();
     
    10999
    110100                namespace {
    111                         Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
    112                                 : nextVarNum( 0 ), isTopLevel( true ),
    113                                 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
    114                                 mangleGenericParams( mangleGenericParams ) {}
    115 
    116                         Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    117                                 int nextVarNum, const VarMapType& varNums )
    118                                 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
    119                                 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
    120                                 mangleGenericParams( mangleGenericParams ) {}
    121 
    122                         void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) {
     101                        Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
     102                                : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {}
     103
     104                        void Mangler::mangleDecl( DeclarationWithType * declaration ) {
    123105                                bool wasTopLevel = isTopLevel;
    124106                                if ( isTopLevel ) {
     
    127109                                        isTopLevel = false;
    128110                                } // if
    129                                 mangleName << Encoding::manglePrefix;
     111                                mangleName << "__";
    130112                                CodeGen::OperatorInfo opInfo;
    131113                                if ( operatorLookup( declaration->get_name(), opInfo ) ) {
    132                                         mangleName << opInfo.outputName.size() << opInfo.outputName;
     114                                        mangleName << opInfo.outputName;
    133115                                } else {
    134                                         mangleName << declaration->name.size() << declaration->name;
     116                                        mangleName << declaration->get_name();
    135117                                } // if
     118                                mangleName << "__";
    136119                                maybeAccept( declaration->get_type(), *visitor );
    137120                                if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) {
     
    139122                                        // so they need a different name mangling
    140123                                        if ( declaration->get_linkage() == LinkageSpec::AutoGen ) {
    141                                                 mangleName << Encoding::autogen;
     124                                                mangleName << "autogen__";
    142125                                        } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
    143                                                 mangleName << Encoding::intrinsic;
     126                                                mangleName << "intrinsic__";
    144127                                        } else {
    145128                                                // if we add another kind of overridable function, this has to change
     
    150133                        }
    151134
    152                         void Mangler_old::postvisit( const ObjectDecl * declaration ) {
     135                        void Mangler::postvisit( ObjectDecl * declaration ) {
    153136                                mangleDecl( declaration );
    154137                        }
    155138
    156                         void Mangler_old::postvisit( const FunctionDecl * declaration ) {
     139                        void Mangler::postvisit( FunctionDecl * declaration ) {
    157140                                mangleDecl( declaration );
    158141                        }
    159142
    160                         void Mangler_old::postvisit( const VoidType * voidType ) {
     143                        void Mangler::postvisit( VoidType * voidType ) {
    161144                                printQualifiers( voidType );
    162                                 mangleName << Encoding::void_t;
    163                         }
    164 
    165                         void Mangler_old::postvisit( const BasicType * basicType ) {
     145                                mangleName << "v";
     146                        }
     147
     148                        void Mangler::postvisit( BasicType * basicType ) {
     149                                static const char *btLetter[] = {
     150                                        "b",    // Bool
     151                                        "c",    // Char
     152                                        "Sc",   // SignedChar
     153                                        "Uc",   // UnsignedChar
     154                                        "s",    // ShortSignedInt
     155                                        "Us",   // ShortUnsignedInt
     156                                        "i",    // SignedInt
     157                                        "Ui",   // UnsignedInt
     158                                        "l",    // LongSignedInt
     159                                        "Ul",   // LongUnsignedInt
     160                                        "q",    // LongLongSignedInt
     161                                        "Uq",   // LongLongUnsignedInt
     162                                        "f",    // Float
     163                                        "d",    // Double
     164                                        "r",    // LongDouble
     165                                        "Xf",   // FloatComplex
     166                                        "Xd",   // DoubleComplex
     167                                        "Xr",   // LongDoubleComplex
     168                                        "If",   // FloatImaginary
     169                                        "Id",   // DoubleImaginary
     170                                        "Ir",   // LongDoubleImaginary
     171                                        "w",    // SignedInt128
     172                                        "Uw",   // UnsignedInt128
     173                                        "x",   // Float80
     174                                        "y",   // Float128
     175                                };
     176                                static_assert(
     177                                        sizeof(btLetter)/sizeof(btLetter[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
     178                                        "Each basic type kind should have a corresponding mangler letter"
     179                                );
     180
    166181                                printQualifiers( basicType );
    167                                 assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
    168                                 mangleName << Encoding::basicTypes[ basicType->kind ];
    169                         }
    170 
    171                         void Mangler_old::postvisit( const PointerType * pointerType ) {
     182                                assert( basicType->get_kind() < sizeof(btLetter)/sizeof(btLetter[0]) );
     183                                mangleName << btLetter[ basicType->get_kind() ];
     184                        }
     185
     186                        void Mangler::postvisit( PointerType * pointerType ) {
    172187                                printQualifiers( pointerType );
    173188                                // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
    174                                 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << Encoding::pointer;
     189                                if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << "P";
    175190                                maybeAccept( pointerType->base, *visitor );
    176191                        }
    177192
    178                         void Mangler_old::postvisit( const ArrayType * arrayType ) {
     193                        void Mangler::postvisit( ArrayType * arrayType ) {
    179194                                // TODO: encode dimension
    180195                                printQualifiers( arrayType );
    181                                 mangleName << Encoding::array << "0";
     196                                mangleName << "A0";
    182197                                maybeAccept( arrayType->base, *visitor );
    183198                        }
    184199
    185                         void Mangler_old::postvisit( const ReferenceType * refType ) {
     200                        void Mangler::postvisit( ReferenceType * refType ) {
    186201                                // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
    187202                                // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
     
    202217                        }
    203218
    204                         void Mangler_old::postvisit( const FunctionType * functionType ) {
     219                        void Mangler::postvisit( FunctionType * functionType ) {
    205220                                printQualifiers( functionType );
    206                                 mangleName << Encoding::function;
     221                                mangleName << "F";
    207222                                // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
    208223                                // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
     
    211226                                inFunctionType = true;
    212227                                std::list< Type* > returnTypes = getTypes( functionType->returnVals );
    213                                 if (returnTypes.empty()) mangleName << Encoding::void_t;
    214                                 else acceptAll( returnTypes, *visitor );
     228                                acceptAll( returnTypes, *visitor );
    215229                                mangleName << "_";
    216230                                std::list< Type* > paramTypes = getTypes( functionType->parameters );
     
    219233                        }
    220234
    221                         void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
     235                        void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
    222236                                printQualifiers( refType );
    223237
    224                                 mangleName << prefix << refType->name.length() << refType->name;
     238                                mangleName << ( refType->name.length() + prefix.length() ) << prefix << refType->name;
    225239
    226240                                if ( mangleGenericParams ) {
    227                                         const std::list< Expression* > & params = refType->parameters;
     241                                        std::list< Expression* >& params = refType->parameters;
    228242                                        if ( ! params.empty() ) {
    229243                                                mangleName << "_";
    230                                                 for ( const Expression * param : params ) {
    231                                                         const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param );
    232                                                         assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
     244                                                for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
     245                                                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     246                                                        assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
    233247                                                        maybeAccept( paramType->type, *visitor );
    234248                                                }
     
    238252                        }
    239253
    240                         void Mangler_old::postvisit( const StructInstType * aggregateUseType ) {
    241                                 mangleRef( aggregateUseType, Encoding::struct_t );
    242                         }
    243 
    244                         void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) {
    245                                 mangleRef( aggregateUseType, Encoding::union_t );
    246                         }
    247 
    248                         void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) {
    249                                 mangleRef( aggregateUseType, Encoding::enum_t );
    250                         }
    251 
    252                         void Mangler_old::postvisit( const TypeInstType * typeInst ) {
     254                        void Mangler::postvisit( StructInstType * aggregateUseType ) {
     255                                mangleRef( aggregateUseType, "s" );
     256                        }
     257
     258                        void Mangler::postvisit( UnionInstType * aggregateUseType ) {
     259                                mangleRef( aggregateUseType, "u" );
     260                        }
     261
     262                        void Mangler::postvisit( EnumInstType * aggregateUseType ) {
     263                                mangleRef( aggregateUseType, "e" );
     264                        }
     265
     266                        void Mangler::postvisit( TypeInstType * typeInst ) {
    253267                                VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
    254268                                if ( varNum == varNums.end() ) {
    255                                         mangleRef( typeInst, Encoding::type );
     269                                        mangleRef( typeInst, "t" );
    256270                                } else {
    257271                                        printQualifiers( typeInst );
    258                                         // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
    259                                         //   forall(dtype T) void f(T);
    260                                         //   forall(dtype S) void f(S);
    261                                         // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
    262                                         // are first found and prefixing with the appropriate encoding for the type class.
    263                                         assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
    264                                         mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
     272                                        std::ostringstream numStream;
     273                                        numStream << varNum->second.first;
     274                                        switch ( (TypeDecl::Kind )varNum->second.second ) {
     275                                          case TypeDecl::Dtype:
     276                                                mangleName << "d";
     277                                                break;
     278                                          case TypeDecl::Ftype:
     279                                                mangleName << "f";
     280                                                break;
     281                                                case TypeDecl::Ttype:
     282                                                mangleName << "tVARGS";
     283                                                break;
     284                                                default:
     285                                                assert( false );
     286                                        } // switch
     287                                        mangleName << numStream.str();
    265288                                } // if
    266289                        }
    267290
    268                         void Mangler_old::postvisit( const TraitInstType * inst ) {
     291                        void Mangler::postvisit( TraitInstType * inst ) {
    269292                                printQualifiers( inst );
    270                                 mangleName << inst->name.size() << inst->name;
    271                         }
    272 
    273                         void Mangler_old::postvisit( const TupleType * tupleType ) {
     293                                mangleName << "_Y" << inst->name << "_";
     294                        }
     295
     296                        void Mangler::postvisit( TupleType * tupleType ) {
    274297                                printQualifiers( tupleType );
    275                                 mangleName << Encoding::tuple << tupleType->types.size();
     298                                mangleName << "T";
    276299                                acceptAll( tupleType->types, *visitor );
    277                         }
    278 
    279                         void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
     300                                mangleName << "_";
     301                        }
     302
     303                        void Mangler::postvisit( VarArgsType * varArgsType ) {
    280304                                printQualifiers( varArgsType );
    281                                 static const std::string vargs = "__builtin_va_list";
    282                                 mangleName << Encoding::type << vargs.size() << vargs;
    283                         }
    284 
    285                         void Mangler_old::postvisit( const ZeroType * ) {
    286                                 mangleName << Encoding::zero;
    287                         }
    288 
    289                         void Mangler_old::postvisit( const OneType * ) {
    290                                 mangleName << Encoding::one;
    291                         }
    292 
    293                         void Mangler_old::postvisit( const QualifiedType * qualType ) {
    294                                 bool inqual = inQualifiedType;
    295                                 if (! inqual ) {
    296                                         // N marks the start of a qualified type
    297                                         inQualifiedType = true;
    298                                         mangleName << Encoding::qualifiedTypeStart;
    299                                 }
    300                                 maybeAccept( qualType->parent, *visitor );
    301                                 maybeAccept( qualType->child, *visitor );
    302                                 if ( ! inqual ) {
    303                                         // E marks the end of a qualified type
    304                                         inQualifiedType = false;
    305                                         mangleName << Encoding::qualifiedTypeEnd;
    306                                 }
    307                         }
    308 
    309                         void Mangler_old::postvisit( const TypeDecl * decl ) {
    310                                 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
    311                                 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
    312                                 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
    313                                 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
    314                                 // aside from the assert false.
    315                                 assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl));
    316                                 assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
    317                                 mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name;
     305                                mangleName << "VARGS";
     306                        }
     307
     308                        void Mangler::postvisit( ZeroType * ) {
     309                                mangleName << "Z";
     310                        }
     311
     312                        void Mangler::postvisit( OneType * ) {
     313                                mangleName << "O";
     314                        }
     315
     316                        void Mangler::postvisit( TypeDecl * decl ) {
     317                                static const char *typePrefix[] = { "BT", "BD", "BF" };
     318                                mangleName << typePrefix[ decl->get_kind() ] << ( decl->name.length() + 1 ) << decl->name;
    318319                        }
    319320
     
    324325                        }
    325326
    326                         void Mangler_old::printQualifiers( const Type * type ) {
     327                        void Mangler::printQualifiers( Type * type ) {
    327328                                // skip if not including qualifiers
    328329                                if ( typeMode ) return;
    329                                 if ( ! type->forall.empty() ) {
     330                                if ( ! type->get_forall().empty() ) {
    330331                                        std::list< std::string > assertionNames;
    331                                         int dcount = 0, fcount = 0, vcount = 0, acount = 0;
    332                                         mangleName << Encoding::forall;
    333                                         for ( const TypeDecl * i : type->forall ) {
    334                                                 switch ( i->kind ) {
     332                                        int tcount = 0, dcount = 0, fcount = 0, vcount = 0;
     333                                        mangleName << "A";
     334                                        for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
     335                                                switch ( (*i)->get_kind() ) {
    335336                                                  case TypeDecl::Dtype:
    336337                                                        dcount++;
     
    345346                                                        assert( false );
    346347                                                } // switch
    347                                                 varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind );
    348                                                 for ( const DeclarationWithType * assert : i->assertions ) {
    349                                                         PassVisitor<Mangler_old> sub_mangler(
    350                                                                 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    351                                                         assert->accept( sub_mangler );
    352                                                         assertionNames.push_back( sub_mangler.pass.get_mangleName() );
    353                                                         acount++;
     348                                                varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() );
     349                                                for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
     350                                                        PassVisitor<Mangler> sub_mangler( mangleOverridable, typeMode, mangleGenericParams );
     351                                                        sub_mangler.pass.nextVarNum = nextVarNum;
     352                                                        sub_mangler.pass.isTopLevel = false;
     353                                                        sub_mangler.pass.varNums = varNums;
     354                                                        (*assert)->accept( sub_mangler );
     355                                                        assertionNames.push_back( sub_mangler.pass.mangleName.str() );
    354356                                                } // for
    355357                                        } // for
    356                                         mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
     358                                        mangleName << tcount << "_" << dcount << "_" << fcount << "_" << vcount << "_";
    357359                                        std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
    358360                                        mangleName << "_";
     
    361363                                        // these qualifiers do not distinguish the outermost type of a function parameter
    362364                                        if ( type->get_const() ) {
    363                                                 mangleName << Encoding::qualifiers.at(Type::Const);
     365                                                mangleName << "C";
    364366                                        } // if
    365367                                        if ( type->get_volatile() ) {
    366                                                 mangleName << Encoding::qualifiers.at(Type::Volatile);
     368                                                mangleName << "V";
    367369                                        } // if
    368370                                        // Removed due to restrict not affecting function compatibility in GCC
     
    371373                                        // } // if
    372374                                        if ( type->get_atomic() ) {
    373                                                 mangleName << Encoding::qualifiers.at(Type::Atomic);
     375                                                mangleName << "A";
    374376                                        } // if
    375377                                }
    376378                                if ( type->get_mutex() ) {
    377                                         mangleName << Encoding::qualifiers.at(Type::Mutex);
     379                                        mangleName << "M";
    378380                                } // if
     381                                if ( type->get_lvalue() ) {
     382                                        // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
     383                                        mangleName << "L";
     384                                }
     385
    379386                                if ( inFunctionType ) {
    380387                                        // turn off inFunctionType so that types can be differentiated for nested qualifiers
     
    386393        } // namespace Mangler
    387394} // namespace SymTab
    388 
    389 namespace Mangle {
    390         namespace {
    391                 /// Mangles names to a unique C identifier
    392                 struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards {
    393                         Mangler_new( Mangle::Mode mode );
    394                         Mangler_new( const Mangler_new & ) = delete;
    395 
    396                         void previsit( const ast::Node * ) { visit_children = false; }
    397 
    398                         void postvisit( const ast::ObjectDecl * declaration );
    399                         void postvisit( const ast::FunctionDecl * declaration );
    400                         void postvisit( const ast::TypeDecl * declaration );
    401 
    402                         void postvisit( const ast::VoidType * voidType );
    403                         void postvisit( const ast::BasicType * basicType );
    404                         void postvisit( const ast::PointerType * pointerType );
    405                         void postvisit( const ast::ArrayType * arrayType );
    406                         void postvisit( const ast::ReferenceType * refType );
    407                         void postvisit( const ast::FunctionType * functionType );
    408                         void postvisit( const ast::StructInstType * aggregateUseType );
    409                         void postvisit( const ast::UnionInstType * aggregateUseType );
    410                         void postvisit( const ast::EnumInstType * aggregateUseType );
    411                         void postvisit( const ast::TypeInstType * aggregateUseType );
    412                         void postvisit( const ast::TraitInstType * inst );
    413                         void postvisit( const ast::TupleType * tupleType );
    414                         void postvisit( const ast::VarArgsType * varArgsType );
    415                         void postvisit( const ast::ZeroType * zeroType );
    416                         void postvisit( const ast::OneType * oneType );
    417                         void postvisit( const ast::QualifiedType * qualType );
    418 
    419                         std::string get_mangleName() { return mangleName.str(); }
    420                   private:
    421                         std::ostringstream mangleName;  ///< Mangled name being constructed
    422                         typedef std::map< std::string, std::pair< int, int > > VarMapType;
    423                         VarMapType varNums;             ///< Map of type variables to indices
    424                         int nextVarNum;                 ///< Next type variable index
    425                         bool isTopLevel;                ///< Is the Mangler at the top level
    426                         bool mangleOverridable;         ///< Specially mangle overridable built-in methods
    427                         bool typeMode;                  ///< Produce a unique mangled name for a type
    428                         bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
    429                         bool inFunctionType = false;    ///< Include type qualifiers if false.
    430                         bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
    431 
    432                   private:
    433                         Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    434                                 int nextVarNum, const VarMapType& varNums );
    435                         friend class ast::Pass<Mangler_new>;
    436 
    437                   private:
    438                         void mangleDecl( const ast::DeclWithType *declaration );
    439                         void mangleRef( const ast::ReferenceToType *refType, std::string prefix );
    440 
    441                         void printQualifiers( const ast::Type *type );
    442                 }; // Mangler_new
    443         } // namespace
    444 
    445 
    446         std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
    447                 ast::Pass<Mangler_new> mangler( mode );
    448                 maybeAccept( decl, mangler );
    449                 return mangler.pass.get_mangleName();
    450         }
    451 
    452         namespace {
    453                 Mangler_new::Mangler_new( Mangle::Mode mode )
    454                         : nextVarNum( 0 ), isTopLevel( true ),
    455                         mangleOverridable  ( ! mode.no_overrideable   ),
    456                         typeMode           (   mode.type              ),
    457                         mangleGenericParams( ! mode.no_generic_params ) {}
    458 
    459                 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    460                         int nextVarNum, const VarMapType& varNums )
    461                         : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
    462                         mangleOverridable( mangleOverridable ), typeMode( typeMode ),
    463                         mangleGenericParams( mangleGenericParams ) {}
    464 
    465                 void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) {
    466                         bool wasTopLevel = isTopLevel;
    467                         if ( isTopLevel ) {
    468                                 varNums.clear();
    469                                 nextVarNum = 0;
    470                                 isTopLevel = false;
    471                         } // if
    472                         mangleName << Encoding::manglePrefix;
    473                         CodeGen::OperatorInfo opInfo;
    474                         if ( operatorLookup( decl->name, opInfo ) ) {
    475                                 mangleName << opInfo.outputName.size() << opInfo.outputName;
    476                         } else {
    477                                 mangleName << decl->name.size() << decl->name;
    478                         } // if
    479                         maybeAccept( decl->get_type(), *visitor );
    480                         if ( mangleOverridable && decl->linkage.is_overrideable ) {
    481                                 // want to be able to override autogenerated and intrinsic routines,
    482                                 // so they need a different name mangling
    483                                 if ( decl->linkage == ast::Linkage::AutoGen ) {
    484                                         mangleName << Encoding::autogen;
    485                                 } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
    486                                         mangleName << Encoding::intrinsic;
    487                                 } else {
    488                                         // if we add another kind of overridable function, this has to change
    489                                         assert( false && "unknown overrideable linkage" );
    490                                 } // if
    491                         }
    492                         isTopLevel = wasTopLevel;
    493                 }
    494 
    495                 void Mangler_new::postvisit( const ast::ObjectDecl * decl ) {
    496                         mangleDecl( decl );
    497                 }
    498 
    499                 void Mangler_new::postvisit( const ast::FunctionDecl * decl ) {
    500                         mangleDecl( decl );
    501                 }
    502 
    503                 void Mangler_new::postvisit( const ast::VoidType * voidType ) {
    504                         printQualifiers( voidType );
    505                         mangleName << Encoding::void_t;
    506                 }
    507 
    508                 void Mangler_new::postvisit( const ast::BasicType * basicType ) {
    509                         printQualifiers( basicType );
    510                         assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
    511                         mangleName << Encoding::basicTypes[ basicType->kind ];
    512                 }
    513 
    514                 void Mangler_new::postvisit( const ast::PointerType * pointerType ) {
    515                         printQualifiers( pointerType );
    516                         // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
    517                         if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName << Encoding::pointer;
    518                         maybe_accept( pointerType->base.get(), *visitor );
    519                 }
    520 
    521                 void Mangler_new::postvisit( const ast::ArrayType * arrayType ) {
    522                         // TODO: encode dimension
    523                         printQualifiers( arrayType );
    524                         mangleName << Encoding::array << "0";
    525                         maybeAccept( arrayType->base.get(), *visitor );
    526                 }
    527 
    528                 void Mangler_new::postvisit( const ast::ReferenceType * refType ) {
    529                         // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
    530                         // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
    531                         // by pretending every reference type is a function parameter.
    532                         GuardValue( inFunctionType );
    533                         inFunctionType = true;
    534                         printQualifiers( refType );
    535                         maybeAccept( refType->base.get(), *visitor );
    536                 }
    537 
    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 
    545                 void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
    546                         printQualifiers( functionType );
    547                         mangleName << Encoding::function;
    548                         // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
    549                         // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
    550                         // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
    551                         GuardValue( inFunctionType );
    552                         inFunctionType = true;
    553                         std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns );
    554                         if (returnTypes.empty()) mangleName << Encoding::void_t;
    555                         else accept_each( returnTypes, *visitor );
    556                         mangleName << "_";
    557                         std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
    558                         accept_each( paramTypes, *visitor );
    559                         mangleName << "_";
    560                 }
    561 
    562                 void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) {
    563                         printQualifiers( refType );
    564 
    565                         mangleName << prefix << refType->name.length() << refType->name;
    566 
    567                         if ( mangleGenericParams ) {
    568                                 if ( ! refType->params.empty() ) {
    569                                         mangleName << "_";
    570                                         for ( const ast::Expr * param : refType->params ) {
    571                                                 auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
    572                                                 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
    573                                                 maybeAccept( paramType->type.get(), *visitor );
    574                                         }
    575                                         mangleName << "_";
    576                                 }
    577                         }
    578                 }
    579 
    580                 void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) {
    581                         mangleRef( aggregateUseType, Encoding::struct_t );
    582                 }
    583 
    584                 void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) {
    585                         mangleRef( aggregateUseType, Encoding::union_t );
    586                 }
    587 
    588                 void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) {
    589                         mangleRef( aggregateUseType, Encoding::enum_t );
    590                 }
    591 
    592                 void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) {
    593                         VarMapType::iterator varNum = varNums.find( typeInst->name );
    594                         if ( varNum == varNums.end() ) {
    595                                 mangleRef( typeInst, Encoding::type );
    596                         } else {
    597                                 printQualifiers( typeInst );
    598                                 // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
    599                                 //   forall(dtype T) void f(T);
    600                                 //   forall(dtype S) void f(S);
    601                                 // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
    602                                 // are first found and prefixing with the appropriate encoding for the type class.
    603                                 assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
    604                                 mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
    605                         } // if
    606                 }
    607 
    608                 void Mangler_new::postvisit( const ast::TraitInstType * inst ) {
    609                         printQualifiers( inst );
    610                         mangleName << inst->name.size() << inst->name;
    611                 }
    612 
    613                 void Mangler_new::postvisit( const ast::TupleType * tupleType ) {
    614                         printQualifiers( tupleType );
    615                         mangleName << Encoding::tuple << tupleType->types.size();
    616                         accept_each( tupleType->types, *visitor );
    617                 }
    618 
    619                 void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) {
    620                         printQualifiers( varArgsType );
    621                         static const std::string vargs = "__builtin_va_list";
    622                         mangleName << Encoding::type << vargs.size() << vargs;
    623                 }
    624 
    625                 void Mangler_new::postvisit( const ast::ZeroType * ) {
    626                         mangleName << Encoding::zero;
    627                 }
    628 
    629                 void Mangler_new::postvisit( const ast::OneType * ) {
    630                         mangleName << Encoding::one;
    631                 }
    632 
    633                 void Mangler_new::postvisit( const ast::QualifiedType * qualType ) {
    634                         bool inqual = inQualifiedType;
    635                         if (! inqual ) {
    636                                 // N marks the start of a qualified type
    637                                 inQualifiedType = true;
    638                                 mangleName << Encoding::qualifiedTypeStart;
    639                         }
    640                         maybeAccept( qualType->parent.get(), *visitor );
    641                         maybeAccept( qualType->child.get(), *visitor );
    642                         if ( ! inqual ) {
    643                                 // E marks the end of a qualified type
    644                                 inQualifiedType = false;
    645                                 mangleName << Encoding::qualifiedTypeEnd;
    646                         }
    647                 }
    648 
    649                 void Mangler_new::postvisit( const ast::TypeDecl * decl ) {
    650                         // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
    651                         // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
    652                         // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
    653                         // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
    654                         // aside from the assert false.
    655                         assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl));
    656                         assertf( decl->kind < ast::TypeVar::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
    657                         mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name;
    658                 }
    659 
    660                 __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
    661                         for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
    662                                 os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
    663                         } // for
    664                 }
    665 
    666                 void Mangler_new::printQualifiers( const ast::Type * type ) {
    667                         // skip if not including qualifiers
    668                         if ( typeMode ) return;
    669                         if ( auto ptype = dynamic_cast< const ast::ParameterizedType * >(type) ) {
    670                                 if ( ! ptype->forall.empty() ) {
    671                                         std::list< std::string > assertionNames;
    672                                         int dcount = 0, fcount = 0, vcount = 0, acount = 0;
    673                                         mangleName << Encoding::forall;
    674                                         for ( const ast::TypeDecl * decl : ptype->forall ) {
    675                                                 switch ( decl->kind ) {
    676                                                 case ast::TypeVar::Kind::Dtype:
    677                                                         dcount++;
    678                                                         break;
    679                                                 case ast::TypeVar::Kind::Ftype:
    680                                                         fcount++;
    681                                                         break;
    682                                                 case ast::TypeVar::Kind::Ttype:
    683                                                         vcount++;
    684                                                         break;
    685                                                 default:
    686                                                         assert( false );
    687                                                 } // switch
    688                                                 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
    689                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    690                                                         ast::Pass<Mangler_new> sub_mangler(
    691                                                                 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    692                                                         assert->accept( sub_mangler );
    693                                                         assertionNames.push_back( sub_mangler.pass.get_mangleName() );
    694                                                         acount++;
    695                                                 } // for
    696                                         } // for
    697                                         mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
    698                                         std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
    699                                         mangleName << "_";
    700                                 } // if
    701                         } // if
    702                         if ( ! inFunctionType ) {
    703                                 // these qualifiers do not distinguish the outermost type of a function parameter
    704                                 if ( type->is_const() ) {
    705                                         mangleName << Encoding::qualifiers.at(Type::Const);
    706                                 } // if
    707                                 if ( type->is_volatile() ) {
    708                                         mangleName << Encoding::qualifiers.at(Type::Volatile);
    709                                 } // if
    710                                 // Removed due to restrict not affecting function compatibility in GCC
    711                                 // if ( type->get_isRestrict() ) {
    712                                 //      mangleName << "E";
    713                                 // } // if
    714                                 if ( type->is_atomic() ) {
    715                                         mangleName << Encoding::qualifiers.at(Type::Atomic);
    716                                 } // if
    717                         }
    718                         if ( type->is_mutex() ) {
    719                                 mangleName << Encoding::qualifiers.at(Type::Mutex);
    720                         } // if
    721                         if ( inFunctionType ) {
    722                                 // turn off inFunctionType so that types can be differentiated for nested qualifiers
    723                                 GuardValue( inFunctionType );
    724                                 inFunctionType = false;
    725                         }
    726                 }
    727         }       // namespace
    728 } // namespace Mangle
    729395
    730396// Local Variables: //
  • src/SymTab/Mangler.h

    rb067d9b r7951100  
    2121#include <utility>            // for pair
    2222
    23 #include "AST/Bitfield.hpp"
    24 #include "AST/Fwd.hpp"
    2523#include "SynTree/SynTree.h"  // for Types
    2624#include "SynTree/Visitor.h"  // for Visitor, maybeAccept
    27 
    28 // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
    29 // The CFA name mangling scheme is based closely on the itanium C++ name mangling scheme, with the following key differences:
    30 // * Variable names are also mangled to include type information, not just functions
    31 // * CFA does not have template expansion, so the rules for function specialization do not apply.
    32 // * CFA instead has to handle type parameters and assertion parameters.
    33 // * Currently name compression is not implemented.
    34 
    35 namespace ResolvExpr {
    36         class TypeEnvironment;
    37 }
    3825
    3926namespace SymTab {
    4027        namespace Mangler {
    4128                /// Mangle syntax tree object; primary interface to clients
    42                 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
     29                std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
    4330
    4431                /// Mangle a type name; secondary interface
    45                 std::string mangleType( const Type * ty );
     32                std::string mangleType( Type* ty );
    4633                /// Mangle ignoring generic type parameters
    47                 std::string mangleConcrete( const Type * ty );
    48 
    49                 namespace Encoding {
    50                         extern const std::string manglePrefix;
    51                         extern const std::string basicTypes[];
    52                         extern const std::map<int, std::string> qualifiers;
    53 
    54                         extern const std::string void_t;
    55                         extern const std::string zero;
    56                         extern const std::string one;
    57 
    58                         extern const std::string function;
    59                         extern const std::string tuple;
    60                         extern const std::string pointer;
    61                         extern const std::string array;
    62                         extern const std::string qualifiedTypeStart;
    63                         extern const std::string qualifiedTypeEnd;
    64 
    65                         extern const std::string forall;
    66                         extern const std::string typeVariables[];
    67 
    68                         extern const std::string struct_t;
    69                         extern const std::string union_t;
    70                         extern const std::string enum_t;
    71                         extern const std::string type;
    72 
    73                         extern const std::string autogen;
    74                         extern const std::string intrinsic;
    75                 };
     34                std::string mangleConcrete( Type* ty );
    7635        } // Mangler
    7736} // SymTab
    78 
    79 namespace Mangle {
    80         /// Bitflags for mangle modes
    81         enum {
    82                 NoOverrideable  = 1 << 0,
    83                 Type            = 1 << 1,
    84                 NoGenericParams = 1 << 2
    85         };
    86 
    87         /// Bitflag type for mangler modes
    88         struct mangle_flags {
    89                 union {
    90                         unsigned int val;
    91                         struct {
    92                                 bool no_overrideable   : 1;
    93                                 bool type              : 1;
    94                                 bool no_generic_params : 1;
    95                         };
    96                 };
    97 
    98                 constexpr mangle_flags( unsigned int val ) : val(val) {}
    99         };
    100 
    101         using Mode = bitfield<mangle_flags>;
    102 
    103         static inline Mode typeMode() { return NoOverrideable | Type; }
    104 
    105         /// Mangle declaration name
    106         std::string mangle( const ast::Node * decl, Mode mode = {} );
    107 
    108         namespace Encoding {
    109                 using namespace SymTab::Mangler::Encoding;
    110         };
    111 }
    112 
    113 extern "C" {
    114         char * cforall_demangle(const char *, int);
    115 }
    11637
    11738// Local Variables: //
  • src/SymTab/Validate.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Aug  7 6:42:00 2019
    13 // Update Count     : 360
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Aug 28 13:47:23 2017
     13// Update Count     : 359
    1414//
    1515
     
    4444#include <list>                        // for list
    4545#include <string>                      // for string
    46 #include <unordered_map>               // for unordered_map
    4746#include <utility>                     // for pair
    4847
    49 #include "AST/Chain.hpp"
    50 #include "AST/Decl.hpp"
    51 #include "AST/Node.hpp"
    52 #include "AST/Pass.hpp"
    53 #include "AST/SymbolTable.hpp"
    54 #include "AST/Type.hpp"
    55 #include "AST/TypeSubstitution.hpp"
    5648#include "CodeGen/CodeGenerator.h"     // for genName
    5749#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5850#include "ControlStruct/Mutate.h"      // for ForExprMutator
    59 #include "Common/CodeLocation.h"       // for CodeLocation
    60 #include "Common/Stats.h"              // for Stats::Heap
    6151#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
    6252#include "Common/ScopedMap.h"          // for ScopedMap
     
    7161#include "Parser/LinkageSpec.h"        // for C
    7262#include "ResolvExpr/typeops.h"        // for typesCompatible
    73 #include "ResolvExpr/Resolver.h"       // for findSingleExpression
    74 #include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
    7563#include "SymTab/Autogen.h"            // for SizeType
    7664#include "SynTree/Attribute.h"         // for noAttributes, Attribute
     
    8472#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    8573#include "SynTree/Visitor.h"           // for Visitor
    86 #include "Validate/HandleAttributes.h" // for handleAttributes
    87 #include "Validate/FindSpecialDecls.h" // for FindSpecialDecls
    8874
    8975class CompoundStmt;
     
    9177class SwitchStmt;
    9278
    93 #define debugPrint( x ) if ( doDebug ) x
     79#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
    9480
    9581namespace SymTab {
    96         /// hoists declarations that are difficult to hoist while parsing
    97         struct HoistTypeDecls final : public WithDeclsToAdd {
    98                 void previsit( SizeofExpr * );
    99                 void previsit( AlignofExpr * );
    100                 void previsit( UntypedOffsetofExpr * );
    101                 void previsit( CompoundLiteralExpr * );
    102                 void handleType( Type * );
    103         };
    104 
    105         struct FixQualifiedTypes final : public WithIndexer {
    106                 Type * postmutate( QualifiedType * );
    107         };
    108 
    10982        struct HoistStruct final : public WithDeclsToAdd, public WithGuards {
    11083                /// Flattens nested struct types
    11184                static void hoistStruct( std::list< Declaration * > &translationUnit );
    11285
     86                void previsit( EnumInstType * enumInstType );
     87                void previsit( StructInstType * structInstType );
     88                void previsit( UnionInstType * unionInstType );
    11389                void previsit( StructDecl * aggregateDecl );
    11490                void previsit( UnionDecl * aggregateDecl );
    11591                void previsit( StaticAssertDecl * assertDecl );
    116                 void previsit( StructInstType * type );
    117                 void previsit( UnionInstType * type );
    118                 void previsit( EnumInstType * type );
    11992
    12093          private:
    121                 template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl );
     94                template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
    12295
    12396                AggregateDecl * parentAggr = nullptr;
     
    133106
    134107        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
    135         struct EnumAndPointerDecay_old {
    136                 void previsit( EnumDecl * aggregateDecl );
    137                 void previsit( FunctionType * func );
     108        struct EnumAndPointerDecay {
     109                void previsit( EnumDecl *aggregateDecl );
     110                void previsit( FunctionType *func );
    138111        };
    139112
    140113        /// Associates forward declarations of aggregates with their definitions
    141         struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting {
    142                 LinkReferenceToTypes_old( const Indexer * indexer );
    143                 void postvisit( TypeInstType * typeInst );
    144 
    145                 void postvisit( EnumInstType * enumInst );
    146                 void postvisit( StructInstType * structInst );
    147                 void postvisit( UnionInstType * unionInst );
    148                 void postvisit( TraitInstType * traitInst );
    149                 void previsit( QualifiedType * qualType );
    150                 void postvisit( QualifiedType * qualType );
    151 
    152                 void postvisit( EnumDecl * enumDecl );
    153                 void postvisit( StructDecl * structDecl );
    154                 void postvisit( UnionDecl * unionDecl );
     114        struct LinkReferenceToTypes final : public WithIndexer, public WithGuards {
     115                LinkReferenceToTypes( const Indexer *indexer );
     116                void postvisit( TypeInstType *typeInst );
     117
     118                void postvisit( EnumInstType *enumInst );
     119                void postvisit( StructInstType *structInst );
     120                void postvisit( UnionInstType *unionInst );
     121                void postvisit( TraitInstType *traitInst );
     122
     123                void postvisit( EnumDecl *enumDecl );
     124                void postvisit( StructDecl *structDecl );
     125                void postvisit( UnionDecl *unionDecl );
    155126                void postvisit( TraitDecl * traitDecl );
    156127
    157                 void previsit( StructDecl * structDecl );
    158                 void previsit( UnionDecl * unionDecl );
     128                void previsit( StructDecl *structDecl );
     129                void previsit( UnionDecl *unionDecl );
    159130
    160131                void renameGenericParams( std::list< TypeDecl * > & params );
    161132
    162133          private:
    163                 const Indexer * local_indexer;
     134                const Indexer *local_indexer;
    164135
    165136                typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType;
     
    174145
    175146        /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
    176         struct ForallPointerDecay_old final {
     147        struct ForallPointerDecay final {
    177148                void previsit( ObjectDecl * object );
    178149                void previsit( FunctionDecl * func );
     
    194165        };
    195166
    196         struct ReplaceTypedef final : public WithVisitorRef<ReplaceTypedef>, public WithGuards, public WithShortCircuiting, public WithDeclsToAdd {
    197                 ReplaceTypedef() : scopeLevel( 0 ) {}
     167        struct EliminateTypedef final : public WithVisitorRef<EliminateTypedef>, public WithGuards {
     168                EliminateTypedef() : scopeLevel( 0 ) {}
    198169                /// Replaces typedefs by forward declarations
    199                 static void replaceTypedef( std::list< Declaration * > &translationUnit );
    200 
    201                 void premutate( QualifiedType * );
    202                 Type * postmutate( QualifiedType * qualType );
     170                static void eliminateTypedef( std::list< Declaration * > &translationUnit );
     171
    203172                Type * postmutate( TypeInstType * aggregateUseType );
    204173                Declaration * postmutate( TypedefDecl * typeDecl );
     
    211180
    212181                void premutate( CompoundStmt * compoundStmt );
     182                CompoundStmt * postmutate( CompoundStmt * compoundStmt );
    213183
    214184                void premutate( StructDecl * structDecl );
     185                Declaration * postmutate( StructDecl * structDecl );
    215186                void premutate( UnionDecl * unionDecl );
     187                Declaration * postmutate( UnionDecl * unionDecl );
    216188                void premutate( EnumDecl * enumDecl );
    217                 void premutate( TraitDecl * );
     189                Declaration * postmutate( EnumDecl * enumDecl );
     190                Declaration * postmutate( TraitDecl * contextDecl );
    218191
    219192                void premutate( FunctionType * ftype );
     
    221194          private:
    222195                template<typename AggDecl>
     196                AggDecl *handleAggregate( AggDecl * aggDecl );
     197
     198                template<typename AggDecl>
    223199                void addImplicitTypedef( AggDecl * aggDecl );
    224                 template< typename AggDecl >
    225                 void handleAggregate( AggDecl * aggr );
    226200
    227201                typedef std::unique_ptr<TypedefDecl> TypedefDeclPtr;
    228202                typedef ScopedMap< std::string, std::pair< TypedefDeclPtr, int > > TypedefMap;
    229                 typedef ScopedMap< std::string, TypeDecl * > TypeDeclMap;
     203                typedef std::map< std::string, TypeDecl * > TypeDeclMap;
    230204                TypedefMap typedefNames;
    231205                TypeDeclMap typedeclNames;
    232206                int scopeLevel;
    233207                bool inFunctionType = false;
    234         };
    235 
    236         struct EliminateTypedef {
    237                 /// removes TypedefDecls from the AST
    238                 static void eliminateTypedef( std::list< Declaration * > &translationUnit );
    239 
    240                 template<typename AggDecl>
    241                 void handleAggregate( AggDecl * aggregateDecl );
    242 
    243                 void previsit( StructDecl * aggregateDecl );
    244                 void previsit( UnionDecl * aggregateDecl );
    245                 void previsit( CompoundStmt * compoundStmt );
    246208        };
    247209
     
    252214                static void verify( std::list< Declaration * > &translationUnit );
    253215
    254                 void previsit( FunctionDecl * funcDecl );
     216                void previsit( FunctionDecl *funcDecl );
    255217        };
    256218
     
    261223        };
    262224
    263         struct FixObjectType : public WithIndexer {
    264                 /// resolves typeof type in object, function, and type declarations
    265                 static void fix( std::list< Declaration * > & translationUnit );
    266 
    267                 void previsit( ObjectDecl * );
    268                 void previsit( FunctionDecl * );
    269                 void previsit( TypeDecl * );
    270         };
    271 
    272         struct ArrayLength : public WithIndexer {
     225        struct ArrayLength {
    273226                /// for array types without an explicit length, compute the length and store it so that it
    274227                /// is known to the rest of the phases. For example,
     
    281234
    282235                void previsit( ObjectDecl * objDecl );
    283                 void previsit( ArrayType * arrayType );
    284236        };
    285237
     
    287239                Type::StorageClasses storageClasses;
    288240
    289                 void premutate( ObjectDecl * objectDecl );
    290                 Expression * postmutate( CompoundLiteralExpr * compLitExpr );
     241                void premutate( ObjectDecl *objectDecl );
     242                Expression * postmutate( CompoundLiteralExpr *compLitExpr );
    291243        };
    292244
     
    298250        };
    299251
     252        FunctionDecl * dereferenceOperator = nullptr;
     253        struct FindSpecialDeclarations final {
     254                void previsit( FunctionDecl * funcDecl );
     255        };
     256
    300257        void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
    301                 PassVisitor<EnumAndPointerDecay_old> epc;
    302                 PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
    303                 PassVisitor<ForallPointerDecay_old> fpd;
     258                PassVisitor<EnumAndPointerDecay> epc;
     259                PassVisitor<LinkReferenceToTypes> lrt( nullptr );
     260                PassVisitor<ForallPointerDecay> fpd;
    304261                PassVisitor<CompoundLiteral> compoundliteral;
    305262                PassVisitor<ValidateGenericParameters> genericParams;
     263                PassVisitor<FindSpecialDeclarations> finder;
    306264                PassVisitor<LabelAddressFixer> labelAddrFixer;
    307                 PassVisitor<HoistTypeDecls> hoistDecls;
    308                 PassVisitor<FixQualifiedTypes> fixQual;
    309 
    310                 {
    311                         Stats::Heap::newPass("validate-A");
    312                         Stats::Time::BlockGuard guard("validate-A");
    313                         acceptAll( translationUnit, hoistDecls );
    314                         ReplaceTypedef::replaceTypedef( translationUnit );
    315                         ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    316                         acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling
    317                 }
    318                 {
    319                         Stats::Heap::newPass("validate-B");
    320                         Stats::Time::BlockGuard guard("validate-B");
    321                         Stats::Time::TimeBlock("Link Reference To Types", [&]() {
    322                                 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
    323                         });
    324                         Stats::Time::TimeBlock("Fix Qualified Types", [&]() {
    325                                 mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed
    326                         });
    327                         Stats::Time::TimeBlock("Hoist Structs", [&]() {
    328                                 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order
    329                         });
    330                         Stats::Time::TimeBlock("Eliminate Typedefs", [&]() {
    331                                 EliminateTypedef::eliminateTypedef( translationUnit ); //
    332                         });
    333                 }
    334                 {
    335                         Stats::Heap::newPass("validate-C");
    336                         Stats::Time::BlockGuard guard("validate-C");
    337                         acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes_old
    338                         VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
    339                         ReturnChecker::checkFunctionReturns( translationUnit );
    340                         InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen
    341                 }
    342                 {
    343                         Stats::Heap::newPass("validate-D");
    344                         Stats::Time::BlockGuard guard("validate-D");
    345                         Stats::Time::TimeBlock("Apply Concurrent Keywords", [&]() {
    346                                 Concurrency::applyKeywords( translationUnit );
    347                         });
    348                         Stats::Time::TimeBlock("Forall Pointer Decay", [&]() {
    349                                 acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
    350                         });
    351                         Stats::Time::TimeBlock("Hoist Control Declarations", [&]() {
    352                                 ControlStruct::hoistControlDecls( translationUnit );  // hoist initialization out of for statements; must happen before autogenerateRoutines
    353                         });
    354                         Stats::Time::TimeBlock("Generate Autogen routines", [&]() {
    355                                 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay_old
    356                         });
    357                 }
    358                 {
    359                         Stats::Heap::newPass("validate-E");
    360                         Stats::Time::BlockGuard guard("validate-E");
    361                         Stats::Time::TimeBlock("Implement Mutex Func", [&]() {
    362                                 Concurrency::implementMutexFuncs( translationUnit );
    363                         });
    364                         Stats::Time::TimeBlock("Implement Thread Start", [&]() {
    365                                 Concurrency::implementThreadStarter( translationUnit );
    366                         });
    367                         Stats::Time::TimeBlock("Compound Literal", [&]() {
    368                                 mutateAll( translationUnit, compoundliteral );
    369                         });
    370                         Stats::Time::TimeBlock("Resolve With Expressions", [&]() {
    371                                 ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables
    372                         });
    373                 }
    374                 {
    375                         Stats::Heap::newPass("validate-F");
    376                         Stats::Time::BlockGuard guard("validate-F");
    377                         Stats::Time::TimeBlock("Fix Object Type", [&]() {
    378                                 FixObjectType::fix( translationUnit );
    379                         });
    380                         Stats::Time::TimeBlock("Array Length", [&]() {
    381                                 ArrayLength::computeLength( translationUnit );
    382                         });
    383                         Stats::Time::TimeBlock("Find Special Declarations", [&]() {
    384                                 Validate::findSpecialDecls( translationUnit );
    385                         });
    386                         Stats::Time::TimeBlock("Fix Label Address", [&]() {
    387                                 mutateAll( translationUnit, labelAddrFixer );
    388                         });
    389                         Stats::Time::TimeBlock("Handle Attributes", [&]() {
    390                                 Validate::handleAttributes( translationUnit );
    391                         });
    392                 }
    393         }
    394 
    395         void validateType( Type * type, const Indexer * indexer ) {
    396                 PassVisitor<EnumAndPointerDecay_old> epc;
    397                 PassVisitor<LinkReferenceToTypes_old> lrt( indexer );
    398                 PassVisitor<ForallPointerDecay_old> fpd;
     265
     266                EliminateTypedef::eliminateTypedef( translationUnit );
     267                HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order
     268                ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
     269                acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling
     270                acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
     271                acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes
     272                VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
     273                ReturnChecker::checkFunctionReturns( translationUnit );
     274                InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen
     275                Concurrency::applyKeywords( translationUnit );
     276                acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
     277                ControlStruct::hoistControlDecls( translationUnit );  // hoist initialization out of for statements; must happen before autogenerateRoutines
     278                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay
     279                Concurrency::implementMutexFuncs( translationUnit );
     280                Concurrency::implementThreadStarter( translationUnit );
     281                mutateAll( translationUnit, compoundliteral );
     282                ArrayLength::computeLength( translationUnit );
     283                acceptAll( translationUnit, finder ); // xxx - remove this pass soon
     284                mutateAll( translationUnit, labelAddrFixer );
     285        }
     286
     287        void validateType( Type *type, const Indexer *indexer ) {
     288                PassVisitor<EnumAndPointerDecay> epc;
     289                PassVisitor<LinkReferenceToTypes> lrt( indexer );
     290                PassVisitor<ForallPointerDecay> fpd;
    399291                type->accept( epc );
    400292                type->accept( lrt );
     
    402294        }
    403295
    404 
    405         void HoistTypeDecls::handleType( Type * type ) {
    406                 // some type declarations are buried in expressions and not easy to hoist during parsing; hoist them here
    407                 AggregateDecl * aggr = nullptr;
    408                 if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
    409                         aggr = inst->baseStruct;
    410                 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
    411                         aggr = inst->baseUnion;
    412                 } else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( type ) ) {
    413                         aggr = inst->baseEnum;
    414                 }
    415                 if ( aggr && aggr->body ) {
    416                         declsToAddBefore.push_front( aggr );
    417                 }
    418         }
    419 
    420         void HoistTypeDecls::previsit( SizeofExpr * expr ) {
    421                 handleType( expr->type );
    422         }
    423 
    424         void HoistTypeDecls::previsit( AlignofExpr * expr ) {
    425                 handleType( expr->type );
    426         }
    427 
    428         void HoistTypeDecls::previsit( UntypedOffsetofExpr * expr ) {
    429                 handleType( expr->type );
    430         }
    431 
    432         void HoistTypeDecls::previsit( CompoundLiteralExpr * expr ) {
    433                 handleType( expr->result );
    434         }
    435 
    436 
    437         Type * FixQualifiedTypes::postmutate( QualifiedType * qualType ) {
    438                 Type * parent = qualType->parent;
    439                 Type * child = qualType->child;
    440                 if ( dynamic_cast< GlobalScopeType * >( qualType->parent ) ) {
    441                         // .T => lookup T at global scope
    442                         if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
    443                                 auto td = indexer.globalLookupType( inst->name );
    444                                 if ( ! td ) {
    445                                         SemanticError( qualType->location, toString("Use of undefined global type ", inst->name) );
    446                                 }
    447                                 auto base = td->base;
    448                                 assert( base );
    449                                 Type * ret = base->clone();
    450                                 ret->get_qualifiers() = qualType->get_qualifiers();
    451                                 return ret;
    452                         } else {
    453                                 // .T => T is not a type name
    454                                 assertf( false, "unhandled global qualified child type: %s", toCString(child) );
    455                         }
    456                 } else {
    457                         // S.T => S must be an aggregate type, find the declaration for T in S.
    458                         AggregateDecl * aggr = nullptr;
    459                         if ( StructInstType * inst = dynamic_cast< StructInstType * >( parent ) ) {
    460                                 aggr = inst->baseStruct;
    461                         } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * > ( parent ) ) {
    462                                 aggr = inst->baseUnion;
    463                         } else {
    464                                 SemanticError( qualType->location, toString("Qualified type requires an aggregate on the left, but has: ", parent) );
    465                         }
    466                         assert( aggr ); // TODO: need to handle forward declarations
    467                         for ( Declaration * member : aggr->members ) {
    468                                 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
    469                                         // name on the right is a typedef
    470                                         if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) {
    471                                                 if ( aggr->name == inst->name ) {
    472                                                         assert( aggr->base );
    473                                                         Type * ret = aggr->base->clone();
    474                                                         ret->get_qualifiers() = qualType->get_qualifiers();
    475                                                         TypeSubstitution sub = parent->genericSubstitution();
    476                                                         sub.apply(ret);
    477                                                         return ret;
    478                                                 }
    479                                         }
    480                                 } else {
    481                                         // S.T - S is not an aggregate => error
    482                                         assertf( false, "unhandled qualified child type: %s", toCString(qualType) );
    483                                 }
    484                         }
    485                         // failed to find a satisfying definition of type
    486                         SemanticError( qualType->location, toString("Undefined type in qualified type: ", qualType) );
    487                 }
    488 
    489                 // ... may want to link canonical SUE definition to each forward decl so that it becomes easier to lookup?
    490         }
    491 
    492 
    493296        void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
    494297                PassVisitor<HoistStruct> hoister;
     
    496299        }
    497300
    498         bool shouldHoist( Declaration * decl ) {
     301        bool shouldHoist( Declaration *decl ) {
    499302                return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl );
    500303        }
    501304
    502         namespace {
    503                 void qualifiedName( AggregateDecl * aggr, std::ostringstream & ss ) {
    504                         if ( aggr->parent ) qualifiedName( aggr->parent, ss );
    505                         ss << "__" << aggr->name;
    506                 }
    507 
    508                 // mangle nested type names using entire parent chain
    509                 std::string qualifiedName( AggregateDecl * aggr ) {
    510                         std::ostringstream ss;
    511                         qualifiedName( aggr, ss );
    512                         return ss.str();
    513                 }
    514         }
    515 
    516305        template< typename AggDecl >
    517         void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) {
     306        void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
    518307                if ( parentAggr ) {
    519                         aggregateDecl->parent = parentAggr;
    520                         aggregateDecl->name = qualifiedName( aggregateDecl );
    521308                        // Add elements in stack order corresponding to nesting structure.
    522309                        declsToAddBefore.push_front( aggregateDecl );
     
    529316        }
    530317
     318        void HoistStruct::previsit( EnumInstType * inst ) {
     319                if ( inst->baseEnum && inst->baseEnum->body ) {
     320                        declsToAddBefore.push_front( inst->baseEnum );
     321                }
     322        }
     323
     324        void HoistStruct::previsit( StructInstType * inst ) {
     325                if ( inst->baseStruct && inst->baseStruct->body ) {
     326                        declsToAddBefore.push_front( inst->baseStruct );
     327                }
     328        }
     329
     330        void HoistStruct::previsit( UnionInstType * inst ) {
     331                if ( inst->baseUnion && inst->baseUnion->body ) {
     332                        declsToAddBefore.push_front( inst->baseUnion );
     333                }
     334        }
     335
    531336        void HoistStruct::previsit( StaticAssertDecl * assertDecl ) {
    532337                if ( parentAggr ) {
     
    543348        }
    544349
    545         void HoistStruct::previsit( StructInstType * type ) {
    546                 // need to reset type name after expanding to qualified name
    547                 assert( type->baseStruct );
    548                 type->name = type->baseStruct->name;
    549         }
    550 
    551         void HoistStruct::previsit( UnionInstType * type ) {
    552                 assert( type->baseUnion );
    553                 type->name = type->baseUnion->name;
    554         }
    555 
    556         void HoistStruct::previsit( EnumInstType * type ) {
    557                 assert( type->baseEnum );
    558                 type->name = type->baseEnum->name;
    559         }
    560 
    561 
    562         bool isTypedef( Declaration * decl ) {
    563                 return dynamic_cast< TypedefDecl * >( decl );
    564         }
    565 
    566         void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
    567                 PassVisitor<EliminateTypedef> eliminator;
    568                 acceptAll( translationUnit, eliminator );
    569                 filter( translationUnit, isTypedef, true );
    570         }
    571 
    572         template< typename AggDecl >
    573         void EliminateTypedef::handleAggregate( AggDecl * aggregateDecl ) {
    574                 filter( aggregateDecl->members, isTypedef, true );
    575         }
    576 
    577         void EliminateTypedef::previsit( StructDecl * aggregateDecl ) {
    578                 handleAggregate( aggregateDecl );
    579         }
    580 
    581         void EliminateTypedef::previsit( UnionDecl * aggregateDecl ) {
    582                 handleAggregate( aggregateDecl );
    583         }
    584 
    585         void EliminateTypedef::previsit( CompoundStmt * compoundStmt ) {
    586                 // remove and delete decl stmts
    587                 filter( compoundStmt->kids, [](Statement * stmt) {
    588                         if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
    589                                 if ( dynamic_cast< TypedefDecl * >( declStmt->decl ) ) {
    590                                         return true;
    591                                 } // if
    592                         } // if
    593                         return false;
    594                 }, true);
    595         }
    596 
    597         void EnumAndPointerDecay_old::previsit( EnumDecl * enumDecl ) {
     350        void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) {
    598351                // Set the type of each member of the enumeration to be EnumConstant
    599                 for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) {
    600                         ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i );
     352                for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
     353                        ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
    601354                        assert( obj );
    602                         obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) );
     355                        obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->get_name() ) );
    603356                } // for
    604357        }
     
    627380        }
    628381
    629         void EnumAndPointerDecay_old::previsit( FunctionType * func ) {
     382        void EnumAndPointerDecay::previsit( FunctionType *func ) {
    630383                // Fix up parameters and return types
    631384                fixFunctionList( func->parameters, func->isVarArgs, func );
     
    633386        }
    634387
    635         LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) {
     388        LinkReferenceToTypes::LinkReferenceToTypes( const Indexer *other_indexer ) {
    636389                if ( other_indexer ) {
    637390                        local_indexer = other_indexer;
     
    641394        }
    642395
    643         void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) {
    644                 const EnumDecl * st = local_indexer->lookupEnum( enumInst->name );
     396        void LinkReferenceToTypes::postvisit( EnumInstType *enumInst ) {
     397                EnumDecl *st = local_indexer->lookupEnum( enumInst->get_name() );
    645398                // it's not a semantic error if the enum is not found, just an implicit forward declaration
    646399                if ( st ) {
    647                         enumInst->baseEnum = const_cast<EnumDecl *>(st); // Just linking in the node
    648                 } // if
    649                 if ( ! st || ! st->body ) {
     400                        //assert( ! enumInst->get_baseEnum() || enumInst->get_baseEnum()->get_members().empty() || ! st->get_members().empty() );
     401                        enumInst->set_baseEnum( st );
     402                } // if
     403                if ( ! st || st->get_members().empty() ) {
    650404                        // use of forward declaration
    651                         forwardEnums[ enumInst->name ].push_back( enumInst );
     405                        forwardEnums[ enumInst->get_name() ].push_back( enumInst );
    652406                } // if
    653407        }
     
    661415        }
    662416
    663         void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {
    664                 const StructDecl * st = local_indexer->lookupStruct( structInst->name );
     417        void LinkReferenceToTypes::postvisit( StructInstType *structInst ) {
     418                StructDecl *st = local_indexer->lookupStruct( structInst->get_name() );
    665419                // it's not a semantic error if the struct is not found, just an implicit forward declaration
    666420                if ( st ) {
    667                         structInst->baseStruct = const_cast<StructDecl *>(st); // Just linking in the node
    668                 } // if
    669                 if ( ! st || ! st->body ) {
     421                        //assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
     422                        structInst->set_baseStruct( st );
     423                } // if
     424                if ( ! st || st->get_members().empty() ) {
    670425                        // use of forward declaration
    671                         forwardStructs[ structInst->name ].push_back( structInst );
     426                        forwardStructs[ structInst->get_name() ].push_back( structInst );
    672427                } // if
    673428                checkGenericParameters( structInst );
    674429        }
    675430
    676         void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) {
    677                 const UnionDecl * un = local_indexer->lookupUnion( unionInst->name );
     431        void LinkReferenceToTypes::postvisit( UnionInstType *unionInst ) {
     432                UnionDecl *un = local_indexer->lookupUnion( unionInst->get_name() );
    678433                // it's not a semantic error if the union is not found, just an implicit forward declaration
    679434                if ( un ) {
    680                         unionInst->baseUnion = const_cast<UnionDecl *>(un); // Just linking in the node
    681                 } // if
    682                 if ( ! un || ! un->body ) {
     435                        unionInst->set_baseUnion( un );
     436                } // if
     437                if ( ! un || un->get_members().empty() ) {
    683438                        // use of forward declaration
    684                         forwardUnions[ unionInst->name ].push_back( unionInst );
     439                        forwardUnions[ unionInst->get_name() ].push_back( unionInst );
    685440                } // if
    686441                checkGenericParameters( unionInst );
    687         }
    688 
    689         void LinkReferenceToTypes_old::previsit( QualifiedType * ) {
    690                 visit_children = false;
    691         }
    692 
    693         void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) {
    694                 // linking only makes sense for the 'oldest ancestor' of the qualified type
    695                 qualType->parent->accept( * visitor );
    696442        }
    697443
     
    704450                        DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
    705451                        if ( dwt1 && dwt2 ) {
    706                                 if ( dwt1->name == dwt2->name && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
     452                                if ( dwt1->get_name() == dwt2->get_name() && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
    707453                                        // std::cerr << "=========== equal:" << std::endl;
    708454                                        // std::cerr << "d1: " << d1 << std::endl;
     
    729475        template< typename Iterator >
    730476        void expandAssertions( TraitInstType * inst, Iterator out ) {
    731                 assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) );
     477                assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toString( inst ).c_str() );
    732478                std::list< DeclarationWithType * > asserts;
    733479                for ( Declaration * decl : inst->baseTrait->members ) {
     
    738484        }
    739485
    740         void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) {
     486        void LinkReferenceToTypes::postvisit( TraitDecl * traitDecl ) {
    741487                if ( traitDecl->name == "sized" ) {
    742488                        // "sized" is a special trait - flick the sized status on for the type variable
     
    760506        }
    761507
    762         void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) {
     508        void LinkReferenceToTypes::postvisit( TraitInstType * traitInst ) {
    763509                // handle other traits
    764                 const TraitDecl * traitDecl = local_indexer->lookupTrait( traitInst->name );
     510                TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
    765511                if ( ! traitDecl ) {
    766512                        SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
    767513                } // if
    768                 if ( traitDecl->parameters.size() != traitInst->parameters.size() ) {
     514                if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
    769515                        SemanticError( traitInst, "incorrect number of trait parameters: " );
    770516                } // if
    771                 traitInst->baseTrait = const_cast<TraitDecl *>(traitDecl); // Just linking in the node
     517                traitInst->baseTrait = traitDecl;
    772518
    773519                // need to carry over the 'sized' status of each decl in the instance
    774                 for ( auto p : group_iterate( traitDecl->parameters, traitInst->parameters ) ) {
     520                for ( auto p : group_iterate( traitDecl->get_parameters(), traitInst->get_parameters() ) ) {
    775521                        TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
    776522                        if ( ! expr ) {
     
    779525                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
    780526                                TypeDecl * formalDecl = std::get<0>(p);
    781                                 TypeDecl * instDecl = inst->baseType;
     527                                TypeDecl * instDecl = inst->get_baseType();
    782528                                if ( formalDecl->get_sized() ) instDecl->set_sized( true );
    783529                        }
     
    786532        }
    787533
    788         void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) {
     534        void LinkReferenceToTypes::postvisit( EnumDecl *enumDecl ) {
    789535                // visit enum members first so that the types of self-referencing members are updated properly
    790                 if ( enumDecl->body ) {
    791                         ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->name );
     536                if ( ! enumDecl->get_members().empty() ) {
     537                        ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->get_name() );
    792538                        if ( fwds != forwardEnums.end() ) {
    793539                                for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    794                                         (* inst)->baseEnum = enumDecl;
     540                                        (*inst )->set_baseEnum( enumDecl );
    795541                                } // for
    796542                                forwardEnums.erase( fwds );
    797543                        } // if
    798 
    799                         for ( Declaration * member : enumDecl->members ) {
    800                                 ObjectDecl * field = strict_dynamic_cast<ObjectDecl *>( member );
    801                                 if ( field->init ) {
    802                                         // need to resolve enumerator initializers early so that other passes that determine if an expression is constexpr have the appropriate information.
    803                                         SingleInit * init = strict_dynamic_cast<SingleInit *>( field->init );
    804                                         ResolvExpr::findSingleExpression( init->value, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), indexer );
    805                                 }
    806                         }
    807                 } // if
    808         }
    809 
    810         void LinkReferenceToTypes_old::renameGenericParams( std::list< TypeDecl * > & params ) {
     544                } // if
     545        }
     546
     547        void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) {
    811548                // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
    812549                //   forall(otype T)
     
    826563        }
    827564
    828         void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) {
     565        void LinkReferenceToTypes::previsit( StructDecl * structDecl ) {
    829566                renameGenericParams( structDecl->parameters );
    830567        }
    831568
    832         void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) {
     569        void LinkReferenceToTypes::previsit( UnionDecl * unionDecl ) {
    833570                renameGenericParams( unionDecl->parameters );
    834571        }
    835572
    836         void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) {
     573        void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) {
    837574                // visit struct members first so that the types of self-referencing members are updated properly
    838575                // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults)
    839                 if ( structDecl->body ) {
    840                         ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->name );
     576                if ( ! structDecl->get_members().empty() ) {
     577                        ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
    841578                        if ( fwds != forwardStructs.end() ) {
    842579                                for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    843                                         (* inst)->baseStruct = structDecl;
     580                                        (*inst )->set_baseStruct( structDecl );
    844581                                } // for
    845582                                forwardStructs.erase( fwds );
     
    848585        }
    849586
    850         void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) {
    851                 if ( unionDecl->body ) {
    852                         ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name );
     587        void LinkReferenceToTypes::postvisit( UnionDecl *unionDecl ) {
     588                if ( ! unionDecl->get_members().empty() ) {
     589                        ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
    853590                        if ( fwds != forwardUnions.end() ) {
    854591                                for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    855                                         (* inst)->baseUnion = unionDecl;
     592                                        (*inst )->set_baseUnion( unionDecl );
    856593                                } // for
    857594                                forwardUnions.erase( fwds );
     
    860597        }
    861598
    862         void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) {
     599        void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) {
    863600                // ensure generic parameter instances are renamed like the base type
    864601                if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
    865                 if ( const NamedTypeDecl * namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) {
    866                         if ( const TypeDecl * typeDecl = dynamic_cast< const TypeDecl * >( namedTypeDecl ) ) {
    867                                 typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype );
     602                if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name() ) ) {
     603                        if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
     604                                typeInst->set_isFtype( typeDecl->get_kind() == TypeDecl::Ftype );
    868605                        } // if
    869606                } // if
     
    877614                        // expand trait instances into their members
    878615                        for ( DeclarationWithType * assertion : asserts ) {
    879                                 if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     616                                if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
    880617                                        // expand trait instance into all of its members
    881618                                        expandAssertions( traitInst, back_inserter( type->assertions ) );
     
    897634        }
    898635
    899         void ForallPointerDecay_old::previsit( ObjectDecl * object ) {
     636        void ForallPointerDecay::previsit( ObjectDecl *object ) {
    900637                // ensure that operator names only apply to functions or function pointers
    901638                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     
    905642        }
    906643
    907         void ForallPointerDecay_old::previsit( FunctionDecl * func ) {
     644        void ForallPointerDecay::previsit( FunctionDecl *func ) {
    908645                func->fixUniqueId();
    909646        }
    910647
    911         void ForallPointerDecay_old::previsit( FunctionType * ftype ) {
     648        void ForallPointerDecay::previsit( FunctionType * ftype ) {
    912649                forallFixer( ftype->forall, ftype );
    913650        }
    914651
    915         void ForallPointerDecay_old::previsit( StructDecl * aggrDecl ) {
     652        void ForallPointerDecay::previsit( StructDecl * aggrDecl ) {
    916653                forallFixer( aggrDecl->parameters, aggrDecl );
    917654        }
    918655
    919         void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
     656        void ForallPointerDecay::previsit( UnionDecl * aggrDecl ) {
    920657                forallFixer( aggrDecl->parameters, aggrDecl );
    921658        }
     
    942679
    943680
    944         void ReplaceTypedef::replaceTypedef( std::list< Declaration * > &translationUnit ) {
    945                 PassVisitor<ReplaceTypedef> eliminator;
     681        bool isTypedef( Declaration *decl ) {
     682                return dynamic_cast< TypedefDecl * >( decl );
     683        }
     684
     685        void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
     686                PassVisitor<EliminateTypedef> eliminator;
    946687                mutateAll( translationUnit, eliminator );
    947688                if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
    948689                        // grab and remember declaration of size_t
    949                         Validate::SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone();
     690                        SizeType = eliminator.pass.typedefNames["size_t"].first->get_base()->clone();
    950691                } else {
    951692                        // xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
    952693                        // eventually should have a warning for this case.
    953                         Validate::SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    954                 }
    955         }
    956 
    957         void ReplaceTypedef::premutate( QualifiedType * ) {
    958                 visit_children = false;
    959         }
    960 
    961         Type * ReplaceTypedef::postmutate( QualifiedType * qualType ) {
    962                 // replacing typedefs only makes sense for the 'oldest ancestor' of the qualified type
    963                 qualType->parent = qualType->parent->acceptMutator( * visitor );
    964                 return qualType;
    965         }
    966 
    967         Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) {
     694                        SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     695                }
     696                filter( translationUnit, isTypedef, true );
     697        }
     698
     699        Type * EliminateTypedef::postmutate( TypeInstType * typeInst ) {
    968700                // instances of typedef types will come here. If it is an instance
    969701                // of a typdef type, link the instance to its actual type.
    970                 TypedefMap::const_iterator def = typedefNames.find( typeInst->name );
     702                TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
    971703                if ( def != typedefNames.end() ) {
    972                         Type * ret = def->second.first->base->clone();
    973                         ret->location = typeInst->location;
     704                        Type *ret = def->second.first->base->clone();
    974705                        ret->get_qualifiers() |= typeInst->get_qualifiers();
    975706                        // attributes are not carried over from typedef to function parameters/return values
     
    982713                        // place instance parameters on the typedef'd type
    983714                        if ( ! typeInst->parameters.empty() ) {
    984                                 ReferenceToType * rtt = dynamic_cast<ReferenceToType *>(ret);
     715                                ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret);
    985716                                if ( ! rtt ) {
    986717                                        SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
    987718                                }
    988                                 rtt->parameters.clear();
     719                                rtt->get_parameters().clear();
    989720                                cloneAll( typeInst->parameters, rtt->parameters );
    990                                 mutateAll( rtt->parameters, * visitor );  // recursively fix typedefs on parameters
     721                                mutateAll( rtt->parameters, *visitor );  // recursively fix typedefs on parameters
    991722                        } // if
    992723                        delete typeInst;
    993724                        return ret;
    994725                } else {
    995                         TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->name );
    996                         if ( base == typedeclNames.end() ) {
    997                                 SemanticError( typeInst->location, toString("Use of undefined type ", typeInst->name) );
    998                         }
     726                        TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->get_name() );
     727                        assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst->name.c_str() );
    999728                        typeInst->set_baseType( base->second );
    1000                         return typeInst;
    1001                 } // if
    1002                 assert( false );
     729                } // if
     730                return typeInst;
    1003731        }
    1004732
     
    1017745        }
    1018746
    1019         Declaration * ReplaceTypedef::postmutate( TypedefDecl * tyDecl ) {
    1020                 if ( typedefNames.count( tyDecl->name ) == 1 && typedefNames[ tyDecl->name ].second == scopeLevel ) {
     747        Declaration *EliminateTypedef::postmutate( TypedefDecl * tyDecl ) {
     748                if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
    1021749                        // typedef to the same name from the same scope
    1022750                        // must be from the same type
    1023751
    1024                         Type * t1 = tyDecl->base;
    1025                         Type * t2 = typedefNames[ tyDecl->name ].first->base;
     752                        Type * t1 = tyDecl->get_base();
     753                        Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
    1026754                        if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
    1027755                                SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
     
    1035763                        }
    1036764                } else {
    1037                         typedefNames[ tyDecl->name ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
     765                        typedefNames[ tyDecl->get_name() ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
    1038766                } // if
    1039767
     
    1043771                //    struct screen;
    1044772                // because the expansion of the typedef is:
    1045                 //    void rtn( SCREEN * p ) => void rtn( struct screen * p )
     773                //    void rtn( SCREEN *p ) => void rtn( struct screen *p )
    1046774                // hence the type-name "screen" must be defined.
    1047775                // Note, qualifiers on the typedef are superfluous for the forward declaration.
    1048776
    1049                 Type * designatorType = tyDecl->base->stripDeclarator();
    1050                 if ( StructInstType * aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
    1051                         declsToAddBefore.push_back( new StructDecl( aggDecl->name, DeclarationNode::Struct, noAttributes, tyDecl->linkage ) );
    1052                 } else if ( UnionInstType * aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
    1053                         declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) );
    1054                 } else if ( EnumInstType * enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
    1055                         declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage ) );
    1056                 } // if
    1057                 return tyDecl->clone();
    1058         }
    1059 
    1060         void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
    1061                 TypedefMap::iterator i = typedefNames.find( typeDecl->name );
     777                Type *designatorType = tyDecl->get_base()->stripDeclarator();
     778                if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
     779                        return new StructDecl( aggDecl->get_name(), DeclarationNode::Struct, noAttributes, tyDecl->get_linkage() );
     780                } else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
     781                        return new UnionDecl( aggDecl->get_name(), noAttributes, tyDecl->get_linkage() );
     782                } else if ( EnumInstType *enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
     783                        return new EnumDecl( enumDecl->get_name(), noAttributes, tyDecl->get_linkage() );
     784                } else {
     785                        return tyDecl->clone();
     786                } // if
     787        }
     788
     789        void EliminateTypedef::premutate( TypeDecl * typeDecl ) {
     790                TypedefMap::iterator i = typedefNames.find( typeDecl->get_name() );
    1062791                if ( i != typedefNames.end() ) {
    1063792                        typedefNames.erase( i ) ;
    1064793                } // if
    1065794
    1066                 typedeclNames.insert( typeDecl->name, typeDecl );
    1067         }
    1068 
    1069         void ReplaceTypedef::premutate( FunctionDecl * ) {
     795                typedeclNames[ typeDecl->get_name() ] = typeDecl;
     796        }
     797
     798        void EliminateTypedef::premutate( FunctionDecl * ) {
    1070799                GuardScope( typedefNames );
    1071                 GuardScope( typedeclNames );
    1072         }
    1073 
    1074         void ReplaceTypedef::premutate( ObjectDecl * ) {
     800        }
     801
     802        void EliminateTypedef::premutate( ObjectDecl * ) {
    1075803                GuardScope( typedefNames );
    1076                 GuardScope( typedeclNames );
    1077         }
    1078 
    1079         DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) {
    1080                 if ( FunctionType * funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type?
     804        }
     805
     806        DeclarationWithType *EliminateTypedef::postmutate( ObjectDecl * objDecl ) {
     807                if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->get_type() ) ) { // function type?
    1081808                        // replace the current object declaration with a function declaration
    1082                         FunctionDecl * newDecl = new FunctionDecl( objDecl->name, objDecl->get_storageClasses(), objDecl->linkage, funtype, 0, objDecl->attributes, objDecl->get_funcSpec() );
    1083                         objDecl->attributes.clear();
     809                        FunctionDecl * newDecl = new FunctionDecl( objDecl->get_name(), objDecl->get_storageClasses(), objDecl->get_linkage(), funtype, 0, objDecl->get_attributes(), objDecl->get_funcSpec() );
     810                        objDecl->get_attributes().clear();
    1084811                        objDecl->set_type( nullptr );
    1085812                        delete objDecl;
     
    1089816        }
    1090817
    1091         void ReplaceTypedef::premutate( CastExpr * ) {
     818        void EliminateTypedef::premutate( CastExpr * ) {
    1092819                GuardScope( typedefNames );
    1093                 GuardScope( typedeclNames );
    1094         }
    1095 
    1096         void ReplaceTypedef::premutate( CompoundStmt * ) {
     820        }
     821
     822        void EliminateTypedef::premutate( CompoundStmt * ) {
    1097823                GuardScope( typedefNames );
    1098                 GuardScope( typedeclNames );
    1099824                scopeLevel += 1;
    1100825                GuardAction( [this](){ scopeLevel -= 1; } );
    1101826        }
    1102827
     828        CompoundStmt *EliminateTypedef::postmutate( CompoundStmt * compoundStmt ) {
     829                // remove and delete decl stmts
     830                filter( compoundStmt->kids, [](Statement * stmt) {
     831                        if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
     832                                if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {
     833                                        return true;
     834                                } // if
     835                        } // if
     836                        return false;
     837                }, true);
     838                return compoundStmt;
     839        }
     840
     841        // there may be typedefs nested within aggregates. in order for everything to work properly, these should be removed
     842        // as well
    1103843        template<typename AggDecl>
    1104         void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
     844        AggDecl *EliminateTypedef::handleAggregate( AggDecl * aggDecl ) {
     845                filter( aggDecl->members, isTypedef, true );
     846                return aggDecl;
     847        }
     848
     849        template<typename AggDecl>
     850        void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
    1105851                if ( typedefNames.count( aggDecl->get_name() ) == 0 ) {
    1106                         Type * type = nullptr;
     852                        Type *type = nullptr;
    1107853                        if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) {
    1108854                                type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() );
     
    1114860                        TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) );
    1115861                        typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel );
    1116                         // add the implicit typedef to the AST
    1117                         declsToAddBefore.push_back( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type->clone(), aggDecl->get_linkage() ) );
    1118                 } // if
    1119         }
    1120 
    1121         template< typename AggDecl >
    1122         void ReplaceTypedef::handleAggregate( AggDecl * aggr ) {
    1123                 SemanticErrorException errors;
    1124 
    1125                 ValueGuard< std::list<Declaration * > > oldBeforeDecls( declsToAddBefore );
    1126                 ValueGuard< std::list<Declaration * > > oldAfterDecls ( declsToAddAfter  );
    1127                 declsToAddBefore.clear();
    1128                 declsToAddAfter.clear();
    1129 
    1130                 GuardScope( typedefNames );
    1131                 GuardScope( typedeclNames );
    1132                 mutateAll( aggr->parameters, * visitor );
    1133 
    1134                 // unroll mutateAll for aggr->members so that implicit typedefs for nested types are added to the aggregate body.
    1135                 for ( std::list< Declaration * >::iterator i = aggr->members.begin(); i != aggr->members.end(); ++i ) {
    1136                         if ( !declsToAddAfter.empty() ) { aggr->members.splice( i, declsToAddAfter ); }
    1137 
    1138                         try {
    1139                                 * i = maybeMutate( * i, * visitor );
    1140                         } catch ( SemanticErrorException &e ) {
    1141                                 errors.append( e );
    1142                         }
    1143 
    1144                         if ( !declsToAddBefore.empty() ) { aggr->members.splice( i, declsToAddBefore ); }
    1145                 }
    1146 
    1147                 if ( !declsToAddAfter.empty() ) { aggr->members.splice( aggr->members.end(), declsToAddAfter ); }
    1148                 if ( !errors.isEmpty() ) { throw errors; }
    1149         }
    1150 
    1151         void ReplaceTypedef::premutate( StructDecl * structDecl ) {
    1152                 visit_children = false;
     862                } // if
     863        }
     864
     865        void EliminateTypedef::premutate( StructDecl * structDecl ) {
    1153866                addImplicitTypedef( structDecl );
    1154                 handleAggregate( structDecl );
    1155         }
    1156 
    1157         void ReplaceTypedef::premutate( UnionDecl * unionDecl ) {
    1158                 visit_children = false;
     867        }
     868
     869
     870        Declaration *EliminateTypedef::postmutate( StructDecl * structDecl ) {
     871                return handleAggregate( structDecl );
     872        }
     873
     874        void EliminateTypedef::premutate( UnionDecl * unionDecl ) {
    1159875                addImplicitTypedef( unionDecl );
    1160                 handleAggregate( unionDecl );
    1161         }
    1162 
    1163         void ReplaceTypedef::premutate( EnumDecl * enumDecl ) {
     876        }
     877
     878        Declaration *EliminateTypedef::postmutate( UnionDecl * unionDecl ) {
     879                return handleAggregate( unionDecl );
     880        }
     881
     882        void EliminateTypedef::premutate( EnumDecl * enumDecl ) {
    1164883                addImplicitTypedef( enumDecl );
    1165884        }
    1166885
    1167         void ReplaceTypedef::premutate( FunctionType * ) {
     886        Declaration *EliminateTypedef::postmutate( EnumDecl * enumDecl ) {
     887                return handleAggregate( enumDecl );
     888        }
     889
     890        Declaration *EliminateTypedef::postmutate( TraitDecl * traitDecl ) {
     891                return handleAggregate( traitDecl );
     892        }
     893
     894        void EliminateTypedef::premutate( FunctionType * ) {
    1168895                GuardValue( inFunctionType );
    1169896                inFunctionType = true;
    1170         }
    1171 
    1172         void ReplaceTypedef::premutate( TraitDecl * ) {
    1173                 GuardScope( typedefNames );
    1174                 GuardScope( typedeclNames);
    1175897        }
    1176898
     
    1217939                        for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) {
    1218940                                if ( i < args.size() ) {
    1219                                         TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) );
    1220                                         sub.add( (* paramIter)->get_name(), expr->get_type()->clone() );
     941                                        TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( *std::next( args.begin(), i ) );
     942                                        sub.add( (*paramIter)->get_name(), expr->get_type()->clone() );
    1221943                                } else if ( i == args.size() ) {
    1222                                         Type * defaultType = (* paramIter)->get_init();
     944                                        Type * defaultType = (*paramIter)->get_init();
    1223945                                        if ( defaultType ) {
    1224946                                                args.push_back( new TypeExpr( defaultType->clone() ) );
    1225                                                 sub.add( (* paramIter)->get_name(), defaultType->clone() );
     947                                                sub.add( (*paramIter)->get_name(), defaultType->clone() );
    1226948                                        }
    1227949                                }
     
    1242964        }
    1243965
    1244         void CompoundLiteral::premutate( ObjectDecl * objectDecl ) {
     966        void CompoundLiteral::premutate( ObjectDecl *objectDecl ) {
    1245967                storageClasses = objectDecl->get_storageClasses();
    1246968        }
    1247969
    1248         Expression * CompoundLiteral::postmutate( CompoundLiteralExpr * compLitExpr ) {
     970        Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {
    1249971                // transform [storage_class] ... (struct S){ 3, ... };
    1250972                // into [storage_class] struct S temp =  { 3, ... };
    1251973                static UniqueName indexName( "_compLit" );
    1252974
    1253                 ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
     975                ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
    1254976                compLitExpr->set_result( nullptr );
    1255977                compLitExpr->set_initializer( nullptr );
     
    12891011                        TupleType * tupleType = strict_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
    12901012                        // ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false.
    1291                         ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) );
     1013                        ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
    12921014                        deleteAll( retVals );
    12931015                        retVals.clear();
     
    12961018        }
    12971019
    1298         void FixObjectType::fix( std::list< Declaration * > & translationUnit ) {
    1299                 PassVisitor<FixObjectType> fixer;
    1300                 acceptAll( translationUnit, fixer );
    1301         }
    1302 
    1303         void FixObjectType::previsit( ObjectDecl * objDecl ) {
    1304                 Type * new_type = ResolvExpr::resolveTypeof( objDecl->get_type(), indexer );
    1305                 objDecl->set_type( new_type );
    1306         }
    1307 
    1308         void FixObjectType::previsit( FunctionDecl * funcDecl ) {
    1309                 Type * new_type = ResolvExpr::resolveTypeof( funcDecl->type, indexer );
    1310                 funcDecl->set_type( new_type );
    1311         }
    1312 
    1313         void FixObjectType::previsit( TypeDecl * typeDecl ) {
    1314                 if ( typeDecl->get_base() ) {
    1315                         Type * new_type = ResolvExpr::resolveTypeof( typeDecl->get_base(), indexer );
    1316                         typeDecl->set_base( new_type );
    1317                 } // if
    1318         }
    1319 
    13201020        void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
    13211021                PassVisitor<ArrayLength> len;
     
    13241024
    13251025        void ArrayLength::previsit( ObjectDecl * objDecl ) {
    1326                 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->type ) ) {
    1327                         if ( at->dimension ) return;
    1328                         if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->init ) ) {
    1329                                 at->dimension = new ConstantExpr( Constant::from_ulong( init->initializers.size() ) );
    1330                         }
    1331                 }
    1332         }
    1333 
    1334         void ArrayLength::previsit( ArrayType * type ) {
    1335                 if ( type->dimension ) {
    1336                         // need to resolve array dimensions early so that constructor code can correctly determine
    1337                         // if a type is a VLA (and hence whether its elements need to be constructed)
    1338                         ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
    1339 
    1340                         // must re-evaluate whether a type is a VLA, now that more information is available
    1341                         // (e.g. the dimension may have been an enumerator, which was unknown prior to this step)
    1342                         type->isVarLen = ! InitTweak::isConstExpr( type->dimension );
     1026                if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
     1027                        if ( at->get_dimension() ) return;
     1028                        if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->get_init() ) ) {
     1029                                at->set_dimension( new ConstantExpr( Constant::from_ulong( init->get_initializers().size() ) ) );
     1030                        }
    13431031                }
    13441032        }
     
    13741062        }
    13751063
    1376 namespace {
    1377         /// Replaces enum types by int, and function/array types in function parameter and return
    1378         /// lists by appropriate pointers
    1379         struct EnumAndPointerDecay_new {
    1380                 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
    1381                         // set the type of each member of the enumeration to be EnumConstant
    1382                         for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
    1383                                 // build new version of object with EnumConstant
    1384                                 ast::ptr< ast::ObjectDecl > obj =
    1385                                         enumDecl->members[i].strict_as< ast::ObjectDecl >();
    1386                                 obj.get_and_mutate()->type =
    1387                                         new ast::EnumInstType{ enumDecl->name, ast::CV::Const };
    1388 
    1389                                 // set into decl
    1390                                 ast::EnumDecl * mut = mutate( enumDecl );
    1391                                 mut->members[i] = obj.get();
    1392                                 enumDecl = mut;
    1393                         }
    1394                         return enumDecl;
    1395                 }
    1396 
    1397                 static const ast::FunctionType * fixFunctionList(
    1398                         const ast::FunctionType * func,
    1399                         std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field,
    1400                         ast::ArgumentFlag isVarArgs = ast::FixedArgs
    1401                 ) {
    1402                         const auto & dwts = func->* field;
    1403                         unsigned nvals = dwts.size();
    1404                         bool hasVoid = false;
    1405                         for ( unsigned i = 0; i < nvals; ++i ) {
    1406                                 func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) );
    1407                         }
    1408 
    1409                         // the only case in which "void" is valid is where it is the only one in the list
    1410                         if ( hasVoid && ( nvals > 1 || isVarArgs ) ) {
    1411                                 SemanticError(
    1412                                         dwts.front()->location, func, "invalid type void in function type" );
    1413                         }
    1414 
    1415                         // one void is the only thing in the list, remove it
    1416                         if ( hasVoid ) {
    1417                                 func = ast::mutate_field(
    1418                                         func, field, std::vector< ast::ptr< ast::DeclWithType > >{} );
    1419                         }
    1420 
    1421                         return func;
    1422                 }
    1423 
    1424                 const ast::FunctionType * previsit( const ast::FunctionType * func ) {
    1425                         func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs );
    1426                         return fixFunctionList( func, &ast::FunctionType::returns );
    1427                 }
    1428         };
    1429 
    1430         /// expand assertions from a trait instance, performing appropriate type variable substitutions
    1431         void expandAssertions(
    1432                 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out
    1433         ) {
    1434                 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) );
    1435 
    1436                 // build list of trait members, substituting trait decl parameters for instance parameters
    1437                 ast::TypeSubstitution sub{
    1438                         inst->base->params.begin(), inst->base->params.end(), inst->params.begin() };
    1439                 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base
    1440                 for ( ast::ptr< ast::Decl > decl : inst->base->members ) {
    1441                         auto member = decl.strict_as< ast::DeclWithType >();
    1442                         sub.apply( member );
    1443                         out.emplace_back( member );
    1444                 }
    1445         }
    1446 
    1447         /// Associates forward declarations of aggregates with their definitions
    1448         class LinkReferenceToTypes_new final
    1449         : public ast::WithSymbolTable, public ast::WithGuards, public
    1450           ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
    1451 
    1452                 // these maps of uses of forward declarations of types need to have the actual type
    1453                 // declaration switched in * after * they have been traversed. To enable this in the
    1454                 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it
    1455                 // before it is placed in the map, properly updating its parents in the usual traversal,
    1456                 // then can have the actual mutation applied later
    1457                 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >;
    1458                 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >;
    1459                 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >;
    1460 
    1461                 const CodeLocation & location;
    1462                 const ast::SymbolTable * localSymtab;
    1463 
    1464                 ForwardEnumsType forwardEnums;
    1465                 ForwardStructsType forwardStructs;
    1466                 ForwardUnionsType forwardUnions;
    1467 
    1468                 /// true if currently in a generic type body, so that type parameter instances can be
    1469                 /// renamed appropriately
    1470                 bool inGeneric = false;
    1471 
    1472         public:
    1473                 /// contstruct using running symbol table
    1474                 LinkReferenceToTypes_new( const CodeLocation & loc )
    1475                 : location( loc ), localSymtab( &symtab ) {}
    1476 
    1477                 /// construct using provided symbol table
    1478                 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms )
    1479                 : location( loc ), localSymtab( &syms ) {}
    1480 
    1481                 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    1482                         // ensure generic parameter instances are renamed like the base type
    1483                         if ( inGeneric && typeInst->base ) {
    1484                                 typeInst = ast::mutate_field(
    1485                                         typeInst, &ast::TypeInstType::name, typeInst->base->name );
    1486                         }
    1487 
    1488                         if (
    1489                                 auto typeDecl = dynamic_cast< const ast::TypeDecl * >(
    1490                                         localSymtab->lookupType( typeInst->name ) )
    1491                         ) {
    1492                                 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind );
    1493                         }
    1494 
    1495                         return typeInst;
    1496                 }
    1497 
    1498                 const ast::Type * postvisit( const ast::EnumInstType * inst ) {
    1499                         const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name );
    1500                         // not a semantic error if the enum is not found, just an implicit forward declaration
    1501                         if ( decl ) {
    1502                                 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl );
    1503                         }
    1504                         if ( ! decl || ! decl->body ) {
    1505                                 // forward declaration
    1506                                 auto mut = mutate( inst );
    1507                                 forwardEnums.emplace( inst->name, mut );
    1508                                 inst = mut;
    1509                         }
    1510                         return inst;
    1511                 }
    1512 
    1513                 void checkGenericParameters( const ast::ReferenceToType * inst ) {
    1514                         for ( const ast::Expr * param : inst->params ) {
    1515                                 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
    1516                                         SemanticError(
    1517                                                 location, inst, "Expression parameters for generic types are currently "
    1518                                                 "unsupported: " );
     1064        void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) {
     1065                if ( ! dereferenceOperator ) {
     1066                        if ( funcDecl->get_name() == "*?" && funcDecl->get_linkage() == LinkageSpec::Intrinsic ) {
     1067                                FunctionType * ftype = funcDecl->get_functionType();
     1068                                if ( ftype->get_parameters().size() == 1 && ftype->get_parameters().front()->get_type()->get_qualifiers() == Type::Qualifiers() ) {
     1069                                        dereferenceOperator = funcDecl;
    15191070                                }
    15201071                        }
    15211072                }
    1522 
    1523                 const ast::StructInstType * postvisit( const ast::StructInstType * inst ) {
    1524                         const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name );
    1525                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1526                         if ( decl ) {
    1527                                 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl );
    1528                         }
    1529                         if ( ! decl || ! decl->body ) {
    1530                                 // forward declaration
    1531                                 auto mut = mutate( inst );
    1532                                 forwardStructs.emplace( inst->name, mut );
    1533                                 inst = mut;
    1534                         }
    1535                         checkGenericParameters( inst );
    1536                         return inst;
    1537                 }
    1538 
    1539                 const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) {
    1540                         const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name );
    1541                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1542                         if ( decl ) {
    1543                                 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl );
    1544                         }
    1545                         if ( ! decl || ! decl->body ) {
    1546                                 // forward declaration
    1547                                 auto mut = mutate( inst );
    1548                                 forwardUnions.emplace( inst->name, mut );
    1549                                 inst = mut;
    1550                         }
    1551                         checkGenericParameters( inst );
    1552                         return inst;
    1553                 }
    1554 
    1555                 const ast::Type * postvisit( const ast::TraitInstType * traitInst ) {
    1556                         // handle other traits
    1557                         const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name );
    1558                         if ( ! traitDecl )       {
    1559                                 SemanticError( location, "use of undeclared trait " + traitInst->name );
    1560                         }
    1561                         if ( traitDecl->params.size() != traitInst->params.size() ) {
    1562                                 SemanticError( location, traitInst, "incorrect number of trait parameters: " );
    1563                         }
    1564                         traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl );
    1565 
    1566                         // need to carry over the "sized" status of each decl in the instance
    1567                         for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) {
    1568                                 auto expr = traitInst->params[i].as< ast::TypeExpr >();
    1569                                 if ( ! expr ) {
    1570                                         SemanticError(
    1571                                                 traitInst->params[i].get(), "Expression parameters for trait instances "
    1572                                                 "are currently unsupported: " );
    1573                                 }
    1574 
    1575                                 if ( auto inst = expr->type.as< ast::TypeInstType >() ) {
    1576                                         if ( traitDecl->params[i]->sized && ! inst->base->sized ) {
    1577                                                 // traitInst = ast::mutate_field_index(
    1578                                                 //      traitInst, &ast::TraitInstType::params, i,
    1579                                                 //      ...
    1580                                                 // );
    1581                                                 ast::TraitInstType * mut = ast::mutate( traitInst );
    1582                                                 ast::chain_mutate( mut->params[i] )
    1583                                                         ( &ast::TypeExpr::type )
    1584                                                                 ( &ast::TypeInstType::base )->sized = true;
    1585                                                 traitInst = mut;
    1586                                         }
    1587                                 }
    1588                         }
    1589 
    1590                         return traitInst;
    1591                 }
    1592 
    1593                 void previsit( const ast::QualifiedType * ) { visit_children = false; }
    1594 
    1595                 const ast::Type * postvisit( const ast::QualifiedType * qualType ) {
    1596                         // linking only makes sense for the "oldest ancestor" of the qualified type
    1597                         return ast::mutate_field(
    1598                                 qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) );
    1599                 }
    1600 
    1601                 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) {
    1602                         // visit enum members first so that the types of self-referencing members are updated
    1603                         // properly
    1604                         if ( ! enumDecl->body ) return enumDecl;
    1605 
    1606                         // update forward declarations to point here
    1607                         auto fwds = forwardEnums.equal_range( enumDecl->name );
    1608                         if ( fwds.first != fwds.second ) {
    1609                                 auto inst = fwds.first;
    1610                                 do {
    1611                                         // forward decl is stored * mutably * in map, can thus be updated
    1612                                         inst->second->base = enumDecl;
    1613                                 } while ( ++inst != fwds.second );
    1614                                 forwardEnums.erase( fwds.first, fwds.second );
    1615                         }
    1616 
    1617                         // ensure that enumerator initializers are properly set
    1618                         for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
    1619                                 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >();
    1620                                 if ( field->init ) {
    1621                                         // need to resolve enumerator initializers early so that other passes that
    1622                                         // determine if an expression is constexpr have appropriate information
    1623                                         auto init = field->init.strict_as< ast::SingleInit >();
    1624 
    1625                                         enumDecl = ast::mutate_field_index(
    1626                                                 enumDecl, &ast::EnumDecl::members, i,
    1627                                                 ast::mutate_field( field, &ast::ObjectDecl::init,
    1628                                                         ast::mutate_field( init, &ast::SingleInit::value,
    1629                                                                 ResolvExpr::findSingleExpression(
    1630                                                                         init->value, new ast::BasicType{ ast::BasicType::SignedInt },
    1631                                                                         symtab ) ) ) );
    1632                                 }
    1633                         }
    1634 
    1635                         return enumDecl;
    1636                 }
    1637 
    1638                 /// rename generic type parameters uniquely so that they do not conflict with user defined
    1639                 /// function forall parameters, e.g. the T in Box and the T in f, below
    1640                 ///   forall(otype T)
    1641                 ///   struct Box {
    1642                 ///     T x;
    1643                 ///   };
    1644                 ///   forall(otype T)
    1645                 ///   void f(Box(T) b) {
    1646                 ///     ...
    1647                 ///   }
    1648                 template< typename AggrDecl >
    1649                 const AggrDecl * renameGenericParams( const AggrDecl * aggr ) {
    1650                         GuardValue( inGeneric );
    1651                         inGeneric = ! aggr->params.empty();
    1652 
    1653                         for ( unsigned i = 0; i < aggr->params.size(); ++i ) {
    1654                                 const ast::TypeDecl * td = aggr->params[i];
    1655 
    1656                                 aggr = ast::mutate_field_index(
    1657                                         aggr, &AggrDecl::params, i,
    1658                                         ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) );
    1659                         }
    1660                         return aggr;
    1661                 }
    1662 
    1663                 const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) {
    1664                         return renameGenericParams( structDecl );
    1665                 }
    1666 
    1667                 void postvisit( const ast::StructDecl * structDecl ) {
    1668                         // visit struct members first so that the types of self-referencing members are
    1669                         // updated properly
    1670                         if ( ! structDecl->body ) return;
    1671 
    1672                         // update forward declarations to point here
    1673                         auto fwds = forwardStructs.equal_range( structDecl->name );
    1674                         if ( fwds.first != fwds.second ) {
    1675                                 auto inst = fwds.first;
    1676                                 do {
    1677                                         // forward decl is stored * mutably * in map, can thus be updated
    1678                                         inst->second->base = structDecl;
    1679                                 } while ( ++inst != fwds.second );
    1680                                 forwardStructs.erase( fwds.first, fwds.second );
    1681                         }
    1682                 }
    1683 
    1684                 const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) {
    1685                         return renameGenericParams( unionDecl );
    1686                 }
    1687 
    1688                 void postvisit( const ast::UnionDecl * unionDecl ) {
    1689                         // visit union members first so that the types of self-referencing members are updated
    1690                         // properly
    1691                         if ( ! unionDecl->body ) return;
    1692 
    1693                         // update forward declarations to point here
    1694                         auto fwds = forwardUnions.equal_range( unionDecl->name );
    1695                         if ( fwds.first != fwds.second ) {
    1696                                 auto inst = fwds.first;
    1697                                 do {
    1698                                         // forward decl is stored * mutably * in map, can thus be updated
    1699                                         inst->second->base = unionDecl;
    1700                                 } while ( ++inst != fwds.second );
    1701                                 forwardUnions.erase( fwds.first, fwds.second );
    1702                         }
    1703                 }
    1704 
    1705                 const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) {
    1706                         // set the "sized" status for the special "sized" trait
    1707                         if ( traitDecl->name == "sized" ) {
    1708                                 assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect "
    1709                                         "number of parameters: %zd", traitDecl->params.size() );
    1710 
    1711                                 traitDecl = ast::mutate_field_index(
    1712                                         traitDecl, &ast::TraitDecl::params, 0,
    1713                                         ast::mutate_field(
    1714                                                 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) );
    1715                         }
    1716 
    1717                         // move assertions from type parameters into the body of the trait
    1718                         std::vector< ast::ptr< ast::DeclWithType > > added;
    1719                         for ( const ast::TypeDecl * td : traitDecl->params ) {
    1720                                 for ( const ast::DeclWithType * assn : td->assertions ) {
    1721                                         auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1722                                         if ( inst ) {
    1723                                                 expandAssertions( inst, added );
    1724                                         } else {
    1725                                                 added.emplace_back( assn );
    1726                                         }
    1727                                 }
    1728                         }
    1729                         if ( ! added.empty() ) {
    1730                                 auto mut = mutate( traitDecl );
    1731                                 for ( const ast::DeclWithType * decl : added ) {
    1732                                         mut->members.emplace_back( decl );
    1733                                 }
    1734                                 traitDecl = mut;
    1735                         }
    1736 
    1737                         return traitDecl;
    1738                 }
    1739         };
    1740 
    1741         /// Replaces array and function types in forall lists by appropriate pointer type and assigns
    1742         /// each object and function declaration a unique ID
    1743         class ForallPointerDecay_new {
    1744                 const CodeLocation & location;
    1745         public:
    1746                 ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {}
    1747 
    1748                 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) {
    1749                         // ensure that operator names only apply to functions or function pointers
    1750                         if (
    1751                                 CodeGen::isOperator( obj->name )
    1752                                 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() )
    1753                         ) {
    1754                                 SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not "
    1755                                         "a function or function pointer." )  );
    1756                         }
    1757 
    1758                         // ensure object has unique ID
    1759                         if ( obj->uniqueId ) return obj;
    1760                         auto mut = mutate( obj );
    1761                         mut->fixUniqueId();
    1762                         return mut;
    1763                 }
    1764 
    1765                 const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) {
    1766                         // ensure function has unique ID
    1767                         if ( func->uniqueId ) return func;
    1768                         auto mut = mutate( func );
    1769                         mut->fixUniqueId();
    1770                         return mut;
    1771                 }
    1772 
    1773                 /// Fix up assertions -- flattens assertion lists, removing all trait instances
    1774                 template< typename node_t, typename parent_t >
    1775                 static const node_t * forallFixer(
    1776                         const CodeLocation & loc, const node_t * node,
    1777                         ast::ParameterizedType::ForallList parent_t::* forallField
    1778                 ) {
    1779                         for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) {
    1780                                 const ast::TypeDecl * type = (node->* forallField)[i];
    1781                                 if ( type->assertions.empty() ) continue;
    1782 
    1783                                 std::vector< ast::ptr< ast::DeclWithType > > asserts;
    1784                                 asserts.reserve( type->assertions.size() );
    1785 
    1786                                 // expand trait instances into their members
    1787                                 for ( const ast::DeclWithType * assn : type->assertions ) {
    1788                                         auto traitInst =
    1789                                                 dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1790                                         if ( traitInst ) {
    1791                                                 // expand trait instance to all its members
    1792                                                 expandAssertions( traitInst, asserts );
    1793                                         } else {
    1794                                                 // pass other assertions through
    1795                                                 asserts.emplace_back( assn );
    1796                                         }
    1797                                 }
    1798 
    1799                                 // apply FixFunction to every assertion to check for invalid void type
    1800                                 for ( ast::ptr< ast::DeclWithType > & assn : asserts ) {
    1801                                         bool isVoid = false;
    1802                                         assn = fixFunction( assn, isVoid );
    1803                                         if ( isVoid ) {
    1804                                                 SemanticError( loc, node, "invalid type void in assertion of function " );
    1805                                         }
    1806                                 }
    1807 
    1808                                 // place mutated assertion list in node
    1809                                 auto mut = mutate( type );
    1810                                 mut->assertions = move( asserts );
    1811                                 node = ast::mutate_field_index( node, forallField, i, mut );
    1812                         }
    1813                         return node;
    1814                 }
    1815 
    1816                 const ast::FunctionType * previsit( const ast::FunctionType * ftype ) {
    1817                         return forallFixer( location, ftype, &ast::FunctionType::forall );
    1818                 }
    1819 
    1820                 const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) {
    1821                         return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params );
    1822                 }
    1823 
    1824                 const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) {
    1825                         return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params );
    1826                 }
    1827         };
    1828 } // anonymous namespace
    1829 
    1830 const ast::Type * validateType(
    1831                 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1832         ast::Pass< EnumAndPointerDecay_new > epc;
    1833         ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    1834         ast::Pass< ForallPointerDecay_new > fpd{ loc };
    1835 
    1836         return type->accept( epc )->accept( lrt )->accept( fpd );
    1837 }
    1838 
     1073        }
    18391074} // namespace SymTab
    18401075
  • src/SymTab/Validate.h

    rb067d9b r7951100  
    1919#include <list>  // for list
    2020
    21 struct CodeLocation;
    22 class  Declaration;
    23 class  Type;
    24 
    25 namespace ast {
    26         class Type;
    27         class SymbolTable;
    28 }
     21class Declaration;
     22class Type;
    2923
    3024namespace SymTab {
     
    3428        void validate( std::list< Declaration * > &translationUnit, bool doDebug = false );
    3529        void validateType( Type *type, const Indexer *indexer );
    36 
    37         const ast::Type * validateType(
    38                 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab );
    3930} // namespace SymTab
    4031
  • src/SymTab/module.mk

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 SRC_SYMTAB = \
    18       SymTab/Autogen.cc \
    19       SymTab/FixFunction.cc \
    20       SymTab/Indexer.cc \
    21       SymTab/Mangler.cc \
    22       SymTab/ManglerCommon.cc \
    23       SymTab/Validate.cc
    24 
    25 SRC += $(SRC_SYMTAB)
    26 SRCDEMANGLE += $(SRC_SYMTAB) SymTab/Demangle.cc
     17SRC += SymTab/Indexer.cc \
     18       SymTab/Mangler.cc \
     19       SymTab/Validate.cc \
     20       SymTab/FixFunction.cc \
     21       SymTab/Autogen.cc
  • src/SynTree/AddressExpr.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 23:54:44 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 28 13:13:38 2019
    13 // Update Count     : 10
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Tue Apr 26 12:35:13 2016
     13// Update Count     : 6
    1414//
    1515
     
    4242AddressExpr::AddressExpr( Expression *arg ) : Expression(), arg( arg ) {
    4343        if ( arg->result ) {
    44                 if ( arg->get_lvalue() ) {
     44                if ( arg->result->get_lvalue() ) {
    4545                        // lvalue, retains all layers of reference and gains a pointer inside the references
    4646                        set_result( addrType( arg->result ) );
    4747                } else {
    4848                        // taking address of non-lvalue -- must be a reference, loses one layer of reference
    49                         if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( arg->result ) ) {
    50                                 set_result( addrType( refType->base ) );
    51                         } else {
    52                                 SemanticError( arg->result, "Attempt to take address of non-lvalue expression: " );
    53                         } // if
     49                        ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( arg->result );
     50                        set_result( addrType( refType->base ) );
    5451                }
     52                // result of & is never an lvalue
     53                get_result()->set_lvalue( false );
    5554        }
    5655}
  • src/SynTree/AggregateDecl.cc

    rb067d9b r7951100  
    8686std::string TraitDecl::typeString() const { return "trait"; }
    8787
     88namespace {
     89        long long int getConstValue( Expression * expr ) {
     90                if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) {
     91                        return getConstValue( castExpr->arg );
     92                } else if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
     93                        return constExpr->intValue();
     94                // can be -1, +1, etc.
     95                // } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) {
     96                //      if ( untypedExpr-> )
     97                } else {
     98                        assertf( false, "Unhandled expression type in getConstValue for enumerators: %s", toString( expr ).c_str() );
     99                }
     100        }
     101}
     102
    88103bool EnumDecl::valueOf( Declaration * enumerator, long long int & value ) {
    89104        if ( enumValues.empty() ) {
     
    93108                        if ( field->init ) {
    94109                                SingleInit * init = strict_dynamic_cast< SingleInit * >( field->init );
    95                                 auto result = eval( init->value );
    96                                 if ( ! result.second ) SemanticError( init->location, toString( "Non-constexpr in initialization of enumerator: ", field ) );
    97                                 currentValue = result.first;
     110                                currentValue = getConstValue( init->value );
    98111                        }
    99112                        assertf( enumValues.count( field->name ) == 0, "Enum %s has multiple members with the name %s", name.c_str(), field->name.c_str() );
  • src/SynTree/ApplicationExpr.cc

    rb067d9b r7951100  
    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 Aug 12 14:28:00 2019
    13 // Update Count     : 5
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Tue Apr 26 12:41:06 2016
     13// Update Count     : 4
    1414//
    1515
     
    2525#include "Declaration.h"         // for Declaration
    2626#include "Expression.h"          // for ParamEntry, ApplicationExpr, Expression
    27 #include "InitTweak/InitTweak.h" // for getFunction
    2827#include "ResolvExpr/typeops.h"  // for extractResultType
    2928#include "Type.h"                // for Type, PointerType, FunctionType
    3029
    31 ParamEntry::ParamEntry( UniqueId decl, Declaration * declptr, Type * actualType, Type * formalType, Expression* expr )
    32                 : decl( decl ), declptr( declptr ), actualType( actualType ), formalType( formalType ), expr( expr ) {
    33         }
     30ParamEntry::ParamEntry( const ParamEntry &other ) :
     31                decl( other.decl ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ), inferParams( new InferredParams( *other.inferParams ) ) {
     32}
    3433
    35 ParamEntry::ParamEntry( const ParamEntry &other ) :
    36                 decl( other.decl ), declptr( maybeClone( other.declptr ) ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) {
     34ParamEntry &ParamEntry::operator=( const ParamEntry &other ) {
     35        if ( &other == this ) return *this;
     36        decl = other.decl;
     37        // xxx - this looks like a memory leak
     38        actualType = maybeClone( other.actualType );
     39        formalType = maybeClone( other.formalType );
     40        expr = maybeClone( other.expr );
     41        *inferParams = *other.inferParams;
     42        return *this;
    3743}
    3844
    3945ParamEntry::~ParamEntry() {
    40         delete declptr;
    4146        delete actualType;
    4247        delete formalType;
     
    4550
    4651ParamEntry::ParamEntry( ParamEntry && other ) :
    47                 decl( other.decl ), declptr( other.declptr ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr ) {
    48         new (&other) ParamEntry();
     52                decl( other.decl ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr ), inferParams( std::move( other.inferParams ) ) {
     53        other.actualType = nullptr;
     54        other.formalType = nullptr;
     55        other.expr = nullptr;
    4956}
    5057
    5158ParamEntry & ParamEntry::operator=( ParamEntry && other ) {
    5259        if ( &other == this ) return *this;
    53         this->~ParamEntry();
    54         new (this) ParamEntry(other.decl, other.declptr, other.actualType, other.formalType, other.expr);
    55         new (&other) ParamEntry();
    56 
     60        delete actualType;
     61        delete formalType;
     62        delete expr;
     63        decl = other.decl;
     64        actualType = other.actualType;
     65        formalType = other.formalType;
     66        expr = other.expr;
     67        other.actualType = nullptr;
     68        other.formalType = nullptr;
     69        other.expr = nullptr;
     70        inferParams = std::move( other.inferParams );
    5771        return *this;
    5872}
     
    7791}
    7892
    79 bool ApplicationExpr::get_lvalue() const {
    80         // from src/GenPoly/Lvalue.cc: isIntrinsicReference
    81         static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    82         if ( const DeclarationWithType * func = InitTweak::getFunction( this ) ) {
    83                 return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
    84         }
    85         return false;
    86 }
    87 
    8893void ApplicationExpr::print( std::ostream &os, Indenter indent ) const {
    8994        os << "Application of" << std::endl << indent+1;
  • src/SynTree/ArrayType.cc

    rb067d9b r7951100  
    2626ArrayType::ArrayType( const Type::Qualifiers &tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes )
    2727        : Type( tq, attributes ), base( base ), dimension( dimension ), isVarLen( isVarLen ), isStatic( isStatic ) {
     28        base->set_lvalue( false );
    2829}
    2930
  • src/SynTree/Attribute.cc

    rb067d9b r7951100  
    2121#include "Expression.h"      // for Expression
    2222
    23 Attribute::Attribute( const Attribute &other ) : BaseSyntaxNode( other ), name( other.name ) {
     23Attribute::Attribute( const Attribute &other ) : name( other.name ) {
    2424        cloneAll( other.parameters, parameters );
    2525}
  • src/SynTree/Attribute.h

    rb067d9b r7951100  
    5050        Attribute * clone() const override { return new Attribute( *this ); }
    5151        virtual void accept( Visitor & v ) override { v.visit( this ); }
    52         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    5352        virtual Attribute * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    5453        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
  • src/SynTree/BaseSyntaxNode.h

    rb067d9b r7951100  
    99// Author           : Thierry Delisle
    1010// Created On       : Tue Feb 14 07:44:20 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 10 16:13:49 2019
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Aug 17 13:44:00
     13// Update Count     : 1
    1414//
    1515
     
    1818#include "Common/CodeLocation.h"
    1919#include "Common/Indenter.h"
    20 #include "Common/Stats.h"
    21 
    2220class Visitor;
    2321class Mutator;
     
    2523class BaseSyntaxNode {
    2624  public:
    27         static Stats::Counters::SimpleCounter* new_nodes;
    28 
    2925        CodeLocation location;
    30 
    31         BaseSyntaxNode() { ++*new_nodes; }
    32         BaseSyntaxNode( const BaseSyntaxNode & o ) : location(o.location) { ++*new_nodes; }
    33         BaseSyntaxNode & operator=( const BaseSyntaxNode & ) = default;
    3426
    3527        virtual ~BaseSyntaxNode() {}
     
    3729        virtual BaseSyntaxNode * clone() const = 0;
    3830        virtual void accept( Visitor & v ) = 0;
    39         virtual void accept( Visitor & v ) const = 0;
    4031        virtual BaseSyntaxNode * acceptMutator( Mutator & m ) = 0;
    41         /// Notes:
    42         /// * each node is responsible for indenting its children.
    43         /// * Expressions should not finish with a newline, since the expression's parent has better information.
     32  /// Notes:
     33  /// * each node is responsible for indenting its children.
     34  /// * Expressions should not finish with a newline, since the expression's parent has better information.
    4435        virtual void print( std::ostream & os, Indenter indent = {} ) const = 0;
     36  void print( std::ostream & os, unsigned int indent ) {
     37    print( os, Indenter{ Indenter::tabsize, indent });
     38  }
    4539};
    4640
  • src/SynTree/BasicType.cc

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  4 21:07:44 2019
    13 // Update Count     : 13
     12// Last Modified On : Mon Sep 25 14:14:03 2017
     13// Update Count     : 11
    1414//
    1515
     
    3030
    3131bool BasicType::isInteger() const {
    32         return kind <= UnsignedInt128;
     32        switch ( kind ) {
     33          case Bool:
     34          case Char:
     35          case SignedChar:
     36          case UnsignedChar:
     37          case ShortSignedInt:
     38          case ShortUnsignedInt:
     39          case SignedInt:
     40          case UnsignedInt:
     41          case LongSignedInt:
     42          case LongUnsignedInt:
     43          case LongLongSignedInt:
     44          case LongLongUnsignedInt:
     45          case SignedInt128:
     46          case UnsignedInt128:
     47                return true;
     48          case Float:
     49          case Double:
     50          case LongDouble:
     51          case FloatComplex:
     52          case DoubleComplex:
     53          case LongDoubleComplex:
     54          case FloatImaginary:
     55          case DoubleImaginary:
     56          case LongDoubleImaginary:
     57          case Float80:
     58          case Float128:
     59                return false;
     60          case NUMBER_OF_BASIC_TYPES:
     61                assert( false );
     62        } // switch
     63        assert( false );
     64        return false;
    3365}
    3466
  • src/SynTree/CommaExpr.cc

    rb067d9b r7951100  
    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 Arg 12 16:11:00 2016
    13 // Update Count     : 2
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Mon May 02 15:19:44 2016
     13// Update Count     : 1
    1414//
    1515
     
    2323CommaExpr::CommaExpr( Expression *arg1, Expression *arg2 )
    2424                : Expression(), arg1( arg1 ), arg2( arg2 ) {
     25        // xxx - result of a comma expression is never an lvalue, so should set lvalue
     26        // to false on all result types. Actually doing this causes some strange things
     27        // to happen in later passes (particularly, Specialize, Lvalue, and Box). This needs to be looked into.
    2528        set_result( maybeClone( arg2->get_result() ) );
     29        // get_type->set_isLvalue( false );
    2630}
    2731
     
    3337        delete arg1;
    3438        delete arg2;
    35 }
    36 
    37 bool CommaExpr::get_lvalue() const {
    38         // This is wrong by C, but the current implementation uses it.
    39         // (ex: Specialize, Lvalue and Box)
    40         return arg2->get_lvalue();
    4139}
    4240
  • src/SynTree/Constant.cc

    rb067d9b r7951100  
    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 : Wed Feb 13 18:11:22 2019
    13 // Update Count     : 32
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jul 14 14:50:00 2017
     13// Update Count     : 29
    1414//
    1515
     
    1919
    2020#include "Constant.h"
    21 #include "Expression.h" // for ConstantExpr
    2221#include "Type.h"    // for BasicType, Type, Type::Qualifiers, PointerType
    2322
    24 Constant::Constant( Type * type, std::string rep, std::optional<unsigned long long> ival ) : type( type ), rep( rep ), ival( ival ) {}
     23Constant::Constant( Type * type, std::string rep, unsigned long long val ) : type( type ), rep( rep ), val( val ) {}
     24Constant::Constant( Type * type, std::string rep, double val ) : type( type ), rep( rep ), val( val ) {}
    2525
    26 Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), ival( other.ival ) {
     26Constant::Constant( const Constant &other ) : rep( other.rep ), val( other.val ) {
    2727        type = other.type->clone();
    2828}
     
    3434}
    3535
     36Constant Constant::from_char( char c ) {
     37        return Constant( new BasicType( Type::Qualifiers(), BasicType::Char ), std::to_string( c ), (unsigned long long int)c );
     38}
     39
    3640Constant Constant::from_int( int i ) {
    3741        return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ), (unsigned long long int)i );
     
    4044Constant Constant::from_ulong( unsigned long i ) {
    4145        return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ), (unsigned long long int)i );
     46}
     47
     48Constant Constant::from_double( double d ) {
     49        return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ), d );
    4250}
    4351
     
    5563unsigned long long Constant::get_ival() const {
    5664        assertf( strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." );
    57         return ival.value();
     65        return val.ival;
     66}
     67
     68double Constant::get_dval() const {
     69        assertf( ! strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve dval from integer constant." );
     70        return val.dval;
    5871}
    5972
    6073void Constant::print( std::ostream &os, Indenter ) const {
    61         os << "(" << rep << " " << (ival ? toString(ival.value()) : "") ;
     74        os << "(" << rep << " " << val.ival;
    6275        if ( type ) {
    6376                os << ": ";
  • src/SynTree/Constant.h

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 10 15:57:38 2019
    13 // Update Count     : 19
     12// Last Modified On : Sat Jul 22 09:54:46 2017
     13// Update Count     : 17
    1414//
    1515
     
    1818#include <iosfwd>     // for ostream
    1919#include <string>     // for string
    20 #include <optional>   // for optional
    2120
    2221#include "BaseSyntaxNode.h"
     
    2827class Constant : public BaseSyntaxNode {
    2928  public:
    30         Constant( Type * type, std::string rep, std::optional<unsigned long long> i );
     29        Constant( Type * type, std::string rep, unsigned long long val );
     30        Constant( Type * type, std::string rep, double val );
    3131        Constant( const Constant & other );
    32         Constant & operator=( const Constant & ) = default;
    3332        virtual ~Constant();
    3433
    35         virtual Constant * clone() const override { return new Constant( *this ); }
     34        virtual Constant * clone() const { return new Constant( *this ); }
    3635
    3736        Type * get_type() { return type; }
     
    4039        void set_value( std::string newValue ) { rep = newValue; }
    4140        unsigned long long get_ival() const;
     41        double get_dval() const;
    4242
    4343        /// generates a boolean constant of the given bool
    4444        static Constant from_bool( bool b );
     45        /// generates a char constant of the given char
     46        static Constant from_char( char c );
    4547        /// generates an integer constant of the given int
    4648        static Constant from_int( int i );
    4749        /// generates an integer constant of the given unsigned long int
    4850        static Constant from_ulong( unsigned long i );
     51        /// generates a floating point constant of the given double
     52        static Constant from_double( double d );
    4953
    5054        /// generates a null pointer value for the given type. void * if omitted.
    5155        static Constant null( Type * ptrtype = nullptr );
    5256
    53         virtual void accept( Visitor & v ) override { v.visit( this ); }
    54         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    55         virtual Constant * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    56         virtual void print( std::ostream & os, Indenter indent = 0 ) const override;
    57 
     57        virtual void accept( Visitor & v ) { v.visit( this ); }
     58        virtual Constant * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     59        virtual void print( std::ostream & os, Indenter indent = 0 ) const;
     60  private:
    5861        Type * type;
    5962        std::string rep;
    60         std::optional<unsigned long long> ival;
     63        union Val {
     64                unsigned long long ival;
     65                double dval;
     66                Val( unsigned long long ival ) : ival( ival ) {}
     67                Val( double dval ) : dval( dval ) {}
     68        } val;
    6169};
    6270
  • src/SynTree/DeclReplacer.cc

    rb067d9b r7951100  
    3030                        bool debug;
    3131                public:
    32                         size_t replaced;
    33 
    34                 public:
    3532                        DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
    3633
     
    4138                        void previsit( TypeInstType * inst );
    4239                };
    43 
    44                 /// Mutator that replaces uses of declarations with arbitrary expressions, according to the supplied mapping
    45                 struct ExprDeclReplacer {
    46                 private:
    47                         const ExprMap & exprMap;
    48                         bool debug;
    49                 public:
    50                         size_t replaced;
    51 
    52                 public:
    53                         ExprDeclReplacer( const ExprMap & exprMap, bool debug = false );
    54 
    55                         // replace variable with new node from expr map
    56                         Expression * postmutate( VariableExpr * varExpr );
    57                 };
    5840        }
    5941
    60         size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
     42        void replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
    6143                PassVisitor<DeclReplacer> replacer( declMap, typeMap, debug );
    6244                maybeAccept( node, replacer );
    63                 return replacer.pass.replaced;
    6445        }
    6546
    66         size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug ) {
     47        void replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug ) {
    6748                TypeMap typeMap;
    68                 return replace( node, declMap, typeMap, debug );
     49                replace( node, declMap, typeMap, debug );
    6950        }
    7051
    71         size_t replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug ) {
     52        void replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug ) {
    7253                DeclMap declMap;
    73                 return replace( node, declMap, typeMap, debug );
    74         }
    75 
    76         size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug ) {
    77                 PassVisitor<ExprDeclReplacer> replacer( exprMap, debug );
    78                 node = maybeMutate( node, replacer );
    79                 return replacer.pass.replaced;
     54                replace( node, declMap, typeMap, debug );
    8055        }
    8156
    8257        namespace {
    83                 DeclReplacer::DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug ) : declMap( declMap ), typeMap( typeMap ) , debug( debug ), replaced( 0 ) {}
     58                DeclReplacer::DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug ) : declMap( declMap ), typeMap( typeMap ) , debug( debug ) {}
    8459
    8560                // replace variable with new node from decl map
     
    8762                        // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
    8863                        if ( declMap.count( varExpr->var ) ) {
    89                                 replaced++;
    9064                                auto replacement = declMap.at( varExpr->var );
    9165                                if ( debug ) {
     
    9872                void DeclReplacer::previsit( TypeInstType * inst ) {
    9973                        if ( typeMap.count( inst->baseType ) ) {
    100                                 replaced++;
    10174                                auto replacement = typeMap.at( inst->baseType );
    10275                                if ( debug ) {
     
    10679                        }
    10780                }
    108 
    109                 ExprDeclReplacer::ExprDeclReplacer( const ExprMap & exprMap, bool debug ) : exprMap( exprMap ), debug( debug ), replaced( 0 ) {}
    110 
    111                 Expression * ExprDeclReplacer::postmutate( VariableExpr * varExpr ) {
    112                         if ( exprMap.count( varExpr->var ) ) {
    113                                 replaced++;
    114                                 Expression * replacement = exprMap.at( varExpr->var )->clone();
    115                                 if ( debug ) {
    116                                         std::cerr << "replacing variable reference: " << (void*)varExpr->var << " " << varExpr->var << " with " << (void*)replacement << " " << replacement << std::endl;
    117                                 }
    118                                 std::swap( varExpr->env, replacement->env );
    119                                 delete varExpr;
    120                                 return replacement;
    121                         }
    122                         return varExpr;
    123                 }
    12481        }
    12582} // namespace VarExprReplacer
  • src/SynTree/DeclReplacer.h

    rb067d9b r7951100  
    2626        typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
    2727        typedef std::map< TypeDecl *, TypeDecl * > TypeMap;
    28         typedef std::map< DeclarationWithType *, Expression * > ExprMap;
    2928
    30         size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug = false );
    31         size_t replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug = false );
    32         size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
    33 
    34         size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug = false);
    35 
    36         template<typename T>
    37         size_t replace( T *& node, const ExprMap & exprMap, bool debug = false ) {
    38                 if ( ! node ) return 0ul;
    39                 BaseSyntaxNode * arg = node;
    40                 size_t replaced = replace( arg, exprMap, debug );
    41                 node = dynamic_cast<T *>( arg );
    42                 assertf( node, "DeclReplacer fundamentally changed the type of its argument." );
    43                 return replaced;
    44         }
     29        void replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug = false );
     30        void replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug = false );
     31        void replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
    4532}
    4633
  • src/SynTree/Declaration.cc

    rb067d9b r7951100  
    2727
    2828static UniqueId lastUniqueId = 0;
     29typedef std::map< UniqueId, Declaration* > IdMapType;
     30static IdMapType idMap;
    2931
    3032Declaration::Declaration( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage )
    31                 : name( name ), linkage( linkage ), uniqueId( 0 ), storageClasses( scs ) {
     33                : name( name ), linkage( linkage ), storageClasses( scs ), uniqueId( 0 ) {
    3234}
    3335
    3436Declaration::Declaration( const Declaration &other )
    35         : BaseSyntaxNode( other ), name( other.name ), linkage( other.linkage ), extension( other.extension ), uniqueId( other.uniqueId ), storageClasses( other.storageClasses ) {
     37        : BaseSyntaxNode( other ), name( other.name ), linkage( other.linkage ), extension( other.extension ), storageClasses( other.storageClasses ), uniqueId( other.uniqueId ) {
    3638}
    3739
     
    4345        if ( uniqueId ) return;
    4446        uniqueId = ++lastUniqueId;
     47        idMap[ uniqueId ] = this;
    4548}
     49
     50Declaration *Declaration::declFromId( UniqueId id ) {
     51        IdMapType::const_iterator i = idMap.find( id );
     52        return i != idMap.end() ? i->second : 0;
     53}
     54
     55void Declaration::dumpIds( std::ostream &os ) {
     56        for ( IdMapType::const_iterator i = idMap.begin(); i != idMap.end(); ++i ) {
     57                os << i->first << " -> ";
     58                i->second->printShort( os );
     59                os << std::endl;
     60        } // for
     61}
     62
    4663
    4764AsmDecl::AsmDecl( AsmStmt *stmt ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), stmt( stmt ) {
  • src/SynTree/Declaration.h

    rb067d9b r7951100  
    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  2 10:47:00 2019
    13 // Update Count     : 135
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun Sep  3 19:24:06 2017
     13// Update Count     : 131
    1414//
    1515
     
    1919#include <iosfwd>                // for ostream
    2020#include <list>                  // for list
    21 #include <unordered_map>         // for unordered_map
    2221#include <string>                // for string, operator+, allocator, to_string
    2322
     
    6362        void fixUniqueId( void );
    6463        virtual Declaration *clone() const override = 0;
    65         virtual void accept( Visitor & v ) override = 0;
    66         virtual void accept( Visitor & v ) const override = 0;
     64        virtual void accept( Visitor &v ) override = 0;
    6765        virtual Declaration *acceptMutator( Mutator &m ) override = 0;
    6866        virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
    6967        virtual void printShort( std::ostream &os, Indenter indent = {} ) const = 0;
    7068
     69        static void dumpIds( std::ostream &os );
     70        static Declaration *declFromId( UniqueId id );
     71
     72  private:
     73        Type::StorageClasses storageClasses;
    7174        UniqueId uniqueId;
    72         Type::StorageClasses storageClasses;
    73   private:
    7475};
    7576
     
    140141
    141142        virtual ObjectDecl *clone() const override { return new ObjectDecl( *this ); }
    142         virtual void accept( Visitor & v ) override { v.visit( this ); }
    143         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     143        virtual void accept( Visitor &v ) override { v.visit( this ); }
    144144        virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    145145        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    166166        CompoundStmt *get_statements() const { return statements; }
    167167        void set_statements( CompoundStmt *newValue ) { statements = newValue; }
    168         bool has_body() const { return NULL != statements; }
    169168
    170169        static FunctionDecl * newFunction( const std::string & name, FunctionType * type, CompoundStmt * statements );
    171170
    172171        virtual FunctionDecl *clone() const override { return new FunctionDecl( *this ); }
    173         virtual void accept( Visitor & v ) override { v.visit( this ); }
    174         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     172        virtual void accept( Visitor &v ) override { v.visit( this ); }
    175173        virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    176174        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    204202        typedef NamedTypeDecl Parent;
    205203  public:
    206         enum Kind { Dtype, Ftype, Ttype, NUMBER_OF_KINDS };
     204        enum Kind { Dtype, Ftype, Ttype };
    207205
    208206        Type * init;
     
    213211                TypeDecl::Kind kind;
    214212                bool isComplete;
    215 
    216213                Data() : kind( (TypeDecl::Kind)-1 ), isComplete( false ) {}
    217214                Data( TypeDecl * typeDecl ) : Data( typeDecl->get_kind(), typeDecl->isComplete() ) {}
    218215                Data( Kind kind, bool isComplete ) : kind( kind ), isComplete( isComplete ) {}
    219                 Data( const Data& d1, const Data& d2 )
    220                 : kind( d1.kind ), isComplete ( d1.isComplete || d2.isComplete ) {}
    221 
    222216                bool operator==(const Data & other) const { return kind == other.kind && isComplete == other.isComplete; }
    223217                bool operator!=(const Data & other) const { return !(*this == other);}
     
    241235
    242236        virtual TypeDecl *clone() const override { return new TypeDecl( *this ); }
    243         virtual void accept( Visitor & v ) override { v.visit( this ); }
    244         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    245         virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    246         virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    247 
     237        virtual void accept( Visitor &v ) override { v.visit( this ); }
     238        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     239        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     240
     241  private:
    248242        Kind kind;
    249243};
     
    260254
    261255        virtual TypedefDecl *clone() const override { return new TypedefDecl( *this ); }
    262         virtual void accept( Visitor & v ) override { v.visit( this ); }
    263         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     256        virtual void accept( Visitor &v ) override { v.visit( this ); }
    264257        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    265258  private:
     
    273266        bool body;
    274267        std::list< Attribute * > attributes;
    275         AggregateDecl * parent = nullptr;
    276268
    277269        AggregateDecl( const std::string &name, const std::list< Attribute * > & attributes = std::list< class Attribute * >(), LinkageSpec::Spec linkage = LinkageSpec::Cforall );
     
    288280        AggregateDecl * set_body( bool body ) { AggregateDecl::body = body; return this; }
    289281
    290         virtual void print( std::ostream &os, Indenter indent = {} ) const override final;
     282        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    291283        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
    292284  protected:
     
    305297
    306298        virtual StructDecl *clone() const override { return new StructDecl( *this ); }
    307         virtual void accept( Visitor & v ) override { v.visit( this ); }
    308         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    309         virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     299        virtual void accept( Visitor &v ) override { v.visit( this ); }
     300        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     301  private:
    310302        DeclarationNode::Aggregate kind;
    311   private:
    312303        virtual std::string typeString() const override;
    313304};
     
    320311
    321312        virtual UnionDecl *clone() const override { return new UnionDecl( *this ); }
    322         virtual void accept( Visitor & v ) override { v.visit( this ); }
    323         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     313        virtual void accept( Visitor &v ) override { v.visit( this ); }
    324314        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    325315  private:
     
    336326
    337327        virtual EnumDecl *clone() const override { return new EnumDecl( *this ); }
    338         virtual void accept( Visitor & v ) override { v.visit( this ); }
    339         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    340         virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    341   private:
    342         std::unordered_map< std::string, long long int > enumValues;
     328        virtual void accept( Visitor &v ) override { v.visit( this ); }
     329        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     330  private:
     331        std::map< std::string, long long int > enumValues;
    343332        virtual std::string typeString() const override;
    344333};
     
    353342
    354343        virtual TraitDecl *clone() const override { return new TraitDecl( *this ); }
    355         virtual void accept( Visitor & v ) override { v.visit( this ); }
    356         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    357         virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    358   private:
    359         virtual std::string typeString() const override;
    360 };
    361 
    362 class WithStmt : public Declaration {
    363 public:
    364         std::list< Expression * > exprs;
    365         Statement * stmt;
    366 
    367         WithStmt( const std::list< Expression * > & exprs, Statement * stmt );
    368         WithStmt( const WithStmt & other );
    369         virtual ~WithStmt();
    370 
    371         virtual WithStmt * clone() const override { return new WithStmt( *this ); }
    372         virtual void accept( Visitor & v ) override { v.visit( this ); }
    373         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    374         virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    375         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    376         virtual void printShort( std::ostream & os, Indenter indent = {} ) const override { print(os, indent); }
     344        virtual void accept( Visitor &v ) override { v.visit( this ); }
     345        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     346  private:
     347        virtual std::string typeString() const override;
    377348};
    378349
     
    389360
    390361        virtual AsmDecl *clone() const override { return new AsmDecl( *this ); }
    391         virtual void accept( Visitor & v ) override { v.visit( this ); }
    392         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     362        virtual void accept( Visitor &v ) override { v.visit( this ); }
    393363        virtual AsmDecl *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    394364        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    406376
    407377        virtual StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
    408         virtual void accept( Visitor & v ) override { v.visit( this ); }
    409         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     378        virtual void accept( Visitor &v ) override { v.visit( this ); }
    410379        virtual StaticAssertDecl * acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    411380        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
  • src/SynTree/Expression.cc

    rb067d9b r7951100  
    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 Aug 15 13:43:00 2019
    13 // Update Count     : 64
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Jul 25 14:15:47 2017
     13// Update Count     : 54
    1414//
    1515
     
    1919#include <iostream>                  // for ostream, operator<<, basic_ostream
    2020#include <list>                      // for list, _List_iterator, list<>::co...
    21 #include <set>                       // for set
    2221
    2322#include "Common/utility.h"          // for maybeClone, cloneAll, deleteAll
     
    3433#include "GenPoly/Lvalue.h"
    3534
    36 void printInferParams( const InferredParams & inferParams, std::ostream & os, Indenter indent, int level ) {
     35void printInferParams( const InferredParams & inferParams, std::ostream &os, Indenter indent, int level ) {
    3736        if ( ! inferParams.empty() ) {
    3837                os << indent << "with inferred parameters " << level << ":" << std::endl;
    3938                for ( InferredParams::const_iterator i = inferParams.begin(); i != inferParams.end(); ++i ) {
    4039                        os << indent+1;
    41                         assert(i->second.declptr);
    42                         i->second.declptr->printShort( os, indent+1 );
     40                        Declaration::declFromId( i->second.decl )->printShort( os, indent+1 );
    4341                        os << std::endl;
    44                         printInferParams( i->second.expr->inferParams, os, indent+1, level+1 );
     42                        printInferParams( *i->second.inferParams, os, indent+1, level+1 );
    4543                } // for
    4644        } // if
     
    4947Expression::Expression() : result( 0 ), env( 0 ) {}
    5048
    51 Expression::Expression( const Expression & other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ), resnSlots( other.resnSlots ) {}
     49Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ) {
     50}
    5251
    5352void Expression::spliceInferParams( Expression * other ) {
     
    5655                inferParams[p.first] = std::move( p.second );
    5756        }
    58         resnSlots.insert( resnSlots.end(), other->resnSlots.begin(), other->resnSlots.end() );
    5957}
    6058
     
    6462}
    6563
    66 bool Expression::get_lvalue() const {
    67         return false;
    68 }
    69 
    70 void Expression::print( std::ostream & os, Indenter indent ) const {
     64void Expression::print( std::ostream &os, Indenter indent ) const {
    7165        printInferParams( inferParams, os, indent+1, 0 );
    7266
     
    8579}
    8680
    87 ConstantExpr::ConstantExpr( const ConstantExpr & other) : Expression( other ), constant( other.constant ) {
     81ConstantExpr::ConstantExpr( const ConstantExpr &other) : Expression( other ), constant( other.constant ) {
    8882}
    8983
    9084ConstantExpr::~ConstantExpr() {}
    9185
    92 void ConstantExpr::print( std::ostream & os, Indenter indent ) const {
     86void ConstantExpr::print( std::ostream &os, Indenter indent ) const {
    9387        os << "constant expression " ;
    9488        constant.print( os );
     
    109103}
    110104
    111 VariableExpr::VariableExpr() : Expression(), var( nullptr ) {}
    112 
    113105VariableExpr::VariableExpr( DeclarationWithType *_var ) : Expression(), var( _var ) {
    114106        assert( var );
    115107        assert( var->get_type() );
    116108        Type * type = var->get_type()->clone();
     109        type->set_lvalue( true );
    117110
    118111        // xxx - doesn't quite work yet - get different alternatives with the same cost
     
    124117        //      long long int value;
    125118        //      if ( decl->valueOf( var, value ) ) {
    126         //              type->set_lvalue( false ); // Would have to move to get_lvalue.
     119        //              type->set_lvalue( false );
    127120        //      }
    128121        // }
     
    131124}
    132125
    133 VariableExpr::VariableExpr( const VariableExpr & other ) : Expression( other ), var( other.var ) {
     126VariableExpr::VariableExpr( const VariableExpr &other ) : Expression( other ), var( other.var ) {
    134127}
    135128
    136129VariableExpr::~VariableExpr() {
    137130        // don't delete the declaration, since it points somewhere else in the tree
    138 }
    139 
    140 bool VariableExpr::get_lvalue() const {
    141         // It isn't always an lvalue, but it is never an rvalue.
    142         return true;
    143131}
    144132
     
    149137}
    150138
    151 void VariableExpr::print( std::ostream & os, Indenter indent ) const {
     139void VariableExpr::print( std::ostream &os, Indenter indent ) const {
    152140        os << "Variable Expression: ";
    153141        var->printShort(os, indent);
     
    155143}
    156144
    157 SizeofExpr::SizeofExpr( Expression * expr_ ) :
     145SizeofExpr::SizeofExpr( Expression *expr_ ) :
    158146                Expression(), expr(expr_), type(0), isType(false) {
    159147        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    160148}
    161149
    162 SizeofExpr::SizeofExpr( Type * type_ ) :
     150SizeofExpr::SizeofExpr( Type *type_ ) :
    163151                Expression(), expr(0), type(type_), isType(true) {
    164152        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    165153}
    166154
    167 SizeofExpr::SizeofExpr( const SizeofExpr & other ) :
     155SizeofExpr::SizeofExpr( const SizeofExpr &other ) :
    168156        Expression( other ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
    169157}
     
    174162}
    175163
    176 void SizeofExpr::print( std::ostream & os, Indenter indent) const {
     164void SizeofExpr::print( std::ostream &os, Indenter indent) const {
    177165        os << "Sizeof Expression on: ";
    178166        if (isType) type->print(os, indent+1);
     
    181169}
    182170
    183 AlignofExpr::AlignofExpr( Expression * expr_ ) :
     171AlignofExpr::AlignofExpr( Expression *expr_ ) :
    184172                Expression(), expr(expr_), type(0), isType(false) {
    185173        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    186174}
    187175
    188 AlignofExpr::AlignofExpr( Type * type_ ) :
     176AlignofExpr::AlignofExpr( Type *type_ ) :
    189177                Expression(), expr(0), type(type_), isType(true) {
    190178        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    191179}
    192180
    193 AlignofExpr::AlignofExpr( const AlignofExpr & other ) :
     181AlignofExpr::AlignofExpr( const AlignofExpr &other ) :
    194182        Expression( other ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
    195183}
     
    200188}
    201189
    202 void AlignofExpr::print( std::ostream & os, Indenter indent) const {
     190void AlignofExpr::print( std::ostream &os, Indenter indent) const {
    203191        os << "Alignof Expression on: ";
    204192        if (isType) type->print(os, indent+1);
     
    207195}
    208196
    209 UntypedOffsetofExpr::UntypedOffsetofExpr( Type * type, const std::string & member ) :
     197UntypedOffsetofExpr::UntypedOffsetofExpr( Type *type, const std::string &member ) :
    210198                Expression(), type(type), member(member) {
    211199        assert( type );
     
    213201}
    214202
    215 UntypedOffsetofExpr::UntypedOffsetofExpr( const UntypedOffsetofExpr & other ) :
     203UntypedOffsetofExpr::UntypedOffsetofExpr( const UntypedOffsetofExpr &other ) :
    216204        Expression( other ), type( maybeClone( other.type ) ), member( other.member ) {}
    217205
     
    220208}
    221209
    222 void UntypedOffsetofExpr::print( std::ostream & os, Indenter indent) const {
     210void UntypedOffsetofExpr::print( std::ostream &os, Indenter indent) const {
    223211        os << "Untyped Offsetof Expression on member " << member << " of ";
    224212        type->print(os, indent+1);
     
    226214}
    227215
    228 OffsetofExpr::OffsetofExpr( Type * type, DeclarationWithType * member ) :
     216OffsetofExpr::OffsetofExpr( Type *type, DeclarationWithType *member ) :
    229217                Expression(), type(type), member(member) {
    230218        assert( member );
     
    233221}
    234222
    235 OffsetofExpr::OffsetofExpr( const OffsetofExpr & other ) :
     223OffsetofExpr::OffsetofExpr( const OffsetofExpr &other ) :
    236224        Expression( other ), type( maybeClone( other.type ) ), member( other.member ) {}
    237225
     
    240228}
    241229
    242 void OffsetofExpr::print( std::ostream & os, Indenter indent) const {
     230void OffsetofExpr::print( std::ostream &os, Indenter indent) const {
    243231        os << "Offsetof Expression on member " << member->name << " of ";
    244232        type->print(os, indent+1);
     
    246234}
    247235
    248 OffsetPackExpr::OffsetPackExpr( StructInstType * type ) : Expression(), type( type ) {
     236OffsetPackExpr::OffsetPackExpr( StructInstType *type ) : Expression(), type( type ) {
    249237        assert( type );
    250238        set_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) );
    251239}
    252240
    253 OffsetPackExpr::OffsetPackExpr( const OffsetPackExpr & other ) : Expression( other ), type( maybeClone( other.type ) ) {}
     241OffsetPackExpr::OffsetPackExpr( const OffsetPackExpr &other ) : Expression( other ), type( maybeClone( other.type ) ) {}
    254242
    255243OffsetPackExpr::~OffsetPackExpr() { delete type; }
    256244
    257 void OffsetPackExpr::print( std::ostream & os, Indenter indent ) const {
     245void OffsetPackExpr::print( std::ostream &os, Indenter indent ) const {
    258246        os << "Offset pack expression on ";
    259247        type->print(os, indent+1);
     
    261249}
    262250
    263 CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {
     251AttrExpr::AttrExpr( Expression *attr, Expression *expr_ ) :
     252                Expression(), attr( attr ), expr(expr_), type(0), isType(false) {
     253}
     254
     255AttrExpr::AttrExpr( Expression *attr, Type *type_ ) :
     256                Expression(), attr( attr ), expr(0), type(type_), isType(true) {
     257}
     258
     259AttrExpr::AttrExpr( const AttrExpr &other ) :
     260                Expression( other ), attr( maybeClone( other.attr ) ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
     261}
     262
     263AttrExpr::~AttrExpr() {
     264        delete attr;
     265        delete expr;
     266        delete type;
     267}
     268
     269void AttrExpr::print( std::ostream &os, Indenter indent) const {
     270        os << "Attr ";
     271        attr->print( os, indent+1);
     272        if ( isType || expr ) {
     273                os << "applied to: ";
     274                if (isType) type->print(os, indent+1);
     275                else expr->print(os, indent+1);
     276        } // if
     277        Expression::print( os, indent );
     278}
     279
     280CastExpr::CastExpr( Expression *arg, Type *toType, bool isGenerated ) : Expression(), arg(arg), isGenerated( isGenerated ) {
    264281        set_result(toType);
    265282}
    266283
    267 CastExpr::CastExpr( Expression * arg, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {
     284CastExpr::CastExpr( Expression *arg, bool isGenerated ) : Expression(), arg(arg), isGenerated( isGenerated ) {
    268285        set_result( new VoidType( Type::Qualifiers() ) );
    269286}
    270287
    271 CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ) {
     288CastExpr::CastExpr( const CastExpr &other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ) {
    272289}
    273290
     
    276293}
    277294
    278 bool CastExpr::get_lvalue() const {
    279         // This is actually wrong by C, but it works with our current set-up.
    280         return arg->get_lvalue();
    281 }
    282 
    283 void CastExpr::print( std::ostream & os, Indenter indent ) const {
    284         os << (isGenerated ? "Generated " : "Explicit ") << "Cast of:" << std::endl << indent+1;
     295void CastExpr::print( std::ostream &os, Indenter indent ) const {
     296        os << "Cast of:" << std::endl << indent+1;
    285297        arg->print(os, indent+1);
    286298        os << std::endl << indent << "... to:";
     
    294306}
    295307
    296 KeywordCastExpr::KeywordCastExpr( Expression * arg, Target target ) : Expression(), arg(arg), target( target ) {
    297 }
    298 
    299 KeywordCastExpr::KeywordCastExpr( const KeywordCastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), target( other.target ) {
     308KeywordCastExpr::KeywordCastExpr( Expression *arg, Target target ) : Expression(), arg(arg), target( target ) {
     309}
     310
     311KeywordCastExpr::KeywordCastExpr( const KeywordCastExpr &other ) : Expression( other ), arg( maybeClone( other.arg ) ), target( other.target ) {
    300312}
    301313
     
    315327}
    316328
    317 void KeywordCastExpr::print( std::ostream & os, Indenter indent ) const {
     329void KeywordCastExpr::print( std::ostream &os, Indenter indent ) const {
    318330        os << "Keyword Cast of:" << std::endl << indent+1;
    319331        arg->print(os, indent+1);
     
    323335}
    324336
    325 VirtualCastExpr::VirtualCastExpr( Expression * arg_, Type * toType ) : Expression(), arg(arg_) {
     337VirtualCastExpr::VirtualCastExpr( Expression *arg_, Type *toType ) : Expression(), arg(arg_) {
    326338        set_result(toType);
    327339}
    328340
    329 VirtualCastExpr::VirtualCastExpr( const VirtualCastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ) {
     341VirtualCastExpr::VirtualCastExpr( const VirtualCastExpr &other ) : Expression( other ), arg( maybeClone( other.arg ) ) {
    330342}
    331343
     
    334346}
    335347
    336 void VirtualCastExpr::print( std::ostream & os, Indenter indent ) const {
     348void VirtualCastExpr::print( std::ostream &os, Indenter indent ) const {
    337349        os << "Virtual Cast of:" << std::endl << indent+1;
    338350        arg->print(os, indent+1);
     
    347359}
    348360
    349 UntypedMemberExpr::UntypedMemberExpr( Expression * member, Expression * aggregate ) :
     361UntypedMemberExpr::UntypedMemberExpr( Expression * member, Expression *aggregate ) :
    350362                Expression(), member(member), aggregate(aggregate) {
    351363        assert( aggregate );
    352364}
    353365
    354 UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr & other ) :
     366UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr &other ) :
    355367                Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) {
    356368}
     
    361373}
    362374
    363 bool UntypedMemberExpr::get_lvalue() const {
    364         return aggregate->get_lvalue();
    365 }
    366 
    367 void UntypedMemberExpr::print( std::ostream & os, Indenter indent ) const {
     375void UntypedMemberExpr::print( std::ostream &os, Indenter indent ) const {
    368376        os << "Untyped Member Expression, with field: " << std::endl << indent+1;
    369377        member->print(os, indent+1 );
    370         os << indent << "... from aggregate:" << std::endl << indent+1;
     378        os << indent << "... from aggregate: " << std::endl << indent+1;
    371379        aggregate->print(os, indent+1);
    372380        Expression::print( os, indent );
    373381}
    374382
    375 MemberExpr::MemberExpr( DeclarationWithType * member, Expression * aggregate ) :
     383MemberExpr::MemberExpr( DeclarationWithType *member, Expression *aggregate ) :
    376384                Expression(), member(member), aggregate(aggregate) {
    377385        assert( member );
     
    383391        sub.apply( res );
    384392        result = res;
     393        result->set_lvalue( true );
    385394        result->get_qualifiers() |= aggregate->result->get_qualifiers();
    386395}
    387396
    388 MemberExpr::MemberExpr( const MemberExpr & other ) :
     397MemberExpr::MemberExpr( const MemberExpr &other ) :
    389398                Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) {
    390399}
     
    395404}
    396405
    397 bool MemberExpr::get_lvalue() const {
    398         // This is actually wrong by C, but it works with our current set-up.
    399         return true;
    400 }
    401 
    402 void MemberExpr::print( std::ostream & os, Indenter indent ) const {
    403         os << "Member Expression, with field:" << std::endl;
     406void MemberExpr::print( std::ostream &os, Indenter indent ) const {
     407        os << "Member Expression, with field: " << std::endl;
    404408        os << indent+1;
    405409        member->print( os, indent+1 );
    406         os << std::endl << indent << "... from aggregate:" << std::endl << indent+1;
     410        os << std::endl << indent << "... from aggregate: " << std::endl << indent+1;
    407411        aggregate->print(os, indent + 1);
    408412        Expression::print( os, indent );
    409413}
    410414
    411 UntypedExpr::UntypedExpr( Expression * function, const std::list<Expression *> & args ) :
     415UntypedExpr::UntypedExpr( Expression *function, const std::list<Expression *> &args ) :
    412416                Expression(), function(function), args(args) {}
    413417
    414 UntypedExpr::UntypedExpr( const UntypedExpr & other ) :
     418UntypedExpr::UntypedExpr( const UntypedExpr &other ) :
    415419                Expression( other ), function( maybeClone( other.function ) ) {
    416420        cloneAll( other.args, args );
     
    431435                        // if references are still allowed in the AST, dereference returns a reference
    432436                        ret->set_result( new ReferenceType( Type::Qualifiers(), ret->get_result() ) );
     437                } else {
     438                        // references have been removed, in which case dereference returns an lvalue of the base type.
     439                        ret->result->set_lvalue( true );
    433440                }
    434441        }
     
    447454}
    448455
    449 bool UntypedExpr::get_lvalue() const {
    450         // from src/GenPoly/Lvalue.cc: isIntrinsicReference
    451         static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    452         std::string fname = InitTweak::getFunctionName( const_cast< UntypedExpr * >( this ) );
    453         return lvalueFunctions.count(fname);
    454 }
    455 
    456 void UntypedExpr::print( std::ostream & os, Indenter indent ) const {
    457         os << "Applying untyped:" << std::endl;
     456
     457void UntypedExpr::print( std::ostream &os, Indenter indent ) const {
     458        os << "Applying untyped: " << std::endl;
    458459        os << indent+1;
    459460        function->print(os, indent+1);
    460         os << std::endl << indent << "...to:" << std::endl;
     461        os << std::endl << indent << "...to: " << std::endl;
    461462        printAll(args, os, indent+1);
    462463        Expression::print( os, indent );
     
    468469}
    469470
    470 NameExpr::NameExpr( const NameExpr & other ) : Expression( other ), name( other.name ) {
     471NameExpr::NameExpr( const NameExpr &other ) : Expression( other ), name( other.name ) {
    471472}
    472473
    473474NameExpr::~NameExpr() {}
    474475
    475 void NameExpr::print( std::ostream & os, Indenter indent ) const {
     476void NameExpr::print( std::ostream &os, Indenter indent ) const {
    476477        os << "Name: " << get_name();
    477478        Expression::print( os, indent );
    478479}
    479480
    480 LogicalExpr::LogicalExpr( Expression * arg1_, Expression * arg2_, bool andp ) :
     481LogicalExpr::LogicalExpr( Expression *arg1_, Expression *arg2_, bool andp ) :
    481482                Expression(), arg1(arg1_), arg2(arg2_), isAnd(andp) {
    482483        set_result( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    483484}
    484485
    485 LogicalExpr::LogicalExpr( const LogicalExpr & other ) :
     486LogicalExpr::LogicalExpr( const LogicalExpr &other ) :
    486487                Expression( other ), arg1( maybeClone( other.arg1 ) ), arg2( maybeClone( other.arg2 ) ), isAnd( other.isAnd ) {
    487488}
     
    492493}
    493494
    494 void LogicalExpr::print( std::ostream & os, Indenter indent )const {
     495void LogicalExpr::print( std::ostream &os, Indenter indent )const {
    495496        os << "Short-circuited operation (" << (isAnd ? "and" : "or") << ") on: ";
    496497        arg1->print(os);
     
    503504                Expression(), arg1(arg1), arg2(arg2), arg3(arg3) {}
    504505
    505 ConditionalExpr::ConditionalExpr( const ConditionalExpr & other ) :
     506ConditionalExpr::ConditionalExpr( const ConditionalExpr &other ) :
    506507                Expression( other ), arg1( maybeClone( other.arg1 ) ), arg2( maybeClone( other.arg2 ) ), arg3( maybeClone( other.arg3 ) ) {
    507508}
     
    513514}
    514515
    515 bool ConditionalExpr::get_lvalue() const {
    516         return false;
    517 }
    518 
    519 void ConditionalExpr::print( std::ostream & os, Indenter indent ) const {
     516void ConditionalExpr::print( std::ostream &os, Indenter indent ) const {
    520517        os << "Conditional expression on: " << std::endl << indent+1;
    521518        arg1->print( os, indent+1 );
     
    530527
    531528
    532 void AsmExpr::print( std::ostream & os, Indenter indent ) const {
     529void AsmExpr::print( std::ostream &os, Indenter indent ) const {
    533530        os << "Asm Expression: " << std::endl;
    534531        if ( inout ) inout->print( os, indent+1 );
     
    541538        assert( callExpr );
    542539        assert( callExpr->result );
    543         set_result( callExpr->result->clone() );
     540        set_result( callExpr->get_result()->clone() );
    544541}
    545542
    546543ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other ) : Expression( other ), callExpr( maybeClone( other.callExpr ) ) {
     544        cloneAll( other.tempDecls, tempDecls );
     545        cloneAll( other.returnDecls, returnDecls );
     546        cloneAll( other.dtors, dtors );
    547547}
    548548
     
    550550        set_env( nullptr ); // ImplicitCopyCtorExpr does not take ownership of an environment
    551551        delete callExpr;
    552 }
    553 
    554 void ImplicitCopyCtorExpr::print( std::ostream & os, Indenter indent ) const {
     552        deleteAll( tempDecls );
     553        deleteAll( returnDecls );
     554        deleteAll( dtors );
     555}
     556
     557void ImplicitCopyCtorExpr::print( std::ostream &os, Indenter indent ) const {
    555558        os <<  "Implicit Copy Constructor Expression: " << std::endl << indent+1;
    556559        callExpr->print( os, indent+1 );
     560        os << std::endl << indent << "... with temporaries:" << std::endl;
     561        printAll( tempDecls, os, indent+1 );
     562        os << std::endl << indent << "... with return temporaries:" << std::endl;
     563        printAll( returnDecls, os, indent+1 );
     564        Expression::print( os, indent );
    557565}
    558566
     
    573581}
    574582
    575 bool ConstructorExpr::get_lvalue() const {
    576         return false;
    577 }
    578 
    579 void ConstructorExpr::print( std::ostream & os, Indenter indent ) const {
     583void ConstructorExpr::print( std::ostream &os, Indenter indent ) const {
    580584        os <<  "Constructor Expression: " << std::endl << indent+1;
    581585        callExpr->print( os, indent + 2 );
     
    586590CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : initializer( initializer ) {
    587591        assert( type && initializer );
     592        type->set_lvalue( true );
    588593        set_result( type );
    589594}
    590595
    591 CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr & other ) : Expression( other ), initializer( other.initializer->clone() ) {}
     596CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr &other ) : Expression( other ), initializer( other.initializer->clone() ) {}
    592597
    593598CompoundLiteralExpr::~CompoundLiteralExpr() {
     
    595600}
    596601
    597 bool CompoundLiteralExpr::get_lvalue() const {
    598         return true;
    599 }
    600 
    601 void CompoundLiteralExpr::print( std::ostream & os, Indenter indent ) const {
     602void CompoundLiteralExpr::print( std::ostream &os, Indenter indent ) const {
    602603        os << "Compound Literal Expression: " << std::endl << indent+1;
    603604        result->print( os, indent+1 );
     
    607608}
    608609
    609 RangeExpr::RangeExpr( Expression * low, Expression * high ) : low( low ), high( high ) {}
    610 RangeExpr::RangeExpr( const RangeExpr & other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
    611 void RangeExpr::print( std::ostream & os, Indenter indent ) const {
     610RangeExpr::RangeExpr( Expression *low, Expression *high ) : low( low ), high( high ) {}
     611RangeExpr::RangeExpr( const RangeExpr &other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
     612void RangeExpr::print( std::ostream &os, Indenter indent ) const {
    612613        os << "Range Expression: ";
    613614        low->print( os, indent );
     
    617618}
    618619
    619 StmtExpr::StmtExpr( CompoundStmt * statements ) : statements( statements ) {
     620StmtExpr::StmtExpr( CompoundStmt *statements ) : statements( statements ) {
    620621        computeResult();
    621622}
    622 StmtExpr::StmtExpr( const StmtExpr & other ) : Expression( other ), statements( other.statements->clone() ), resultExpr( other.resultExpr ) {
     623StmtExpr::StmtExpr( const StmtExpr &other ) : Expression( other ), statements( other.statements->clone() ) {
    623624        cloneAll( other.returnDecls, returnDecls );
    624625        cloneAll( other.dtors, dtors );
     
    649650        }
    650651}
    651 bool StmtExpr::get_lvalue() const {
    652         return false;
    653 }
    654 void StmtExpr::print( std::ostream & os, Indenter indent ) const {
     652void StmtExpr::print( std::ostream &os, Indenter indent ) const {
    655653        os << "Statement Expression: " << std::endl << indent+1;
    656654        statements->print( os, indent+1 );
     
    668666
    669667long long UniqueExpr::count = 0;
    670 UniqueExpr::UniqueExpr( Expression * expr, long long idVal ) : expr( expr ), object( nullptr ), var( nullptr ), id( idVal ) {
     668UniqueExpr::UniqueExpr( Expression *expr, long long idVal ) : expr( expr ), object( nullptr ), var( nullptr ), id( idVal ) {
    671669        assert( expr );
    672670        assert( count != -1 );
     
    676674        }
    677675}
    678 UniqueExpr::UniqueExpr( const UniqueExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), object( maybeClone( other.object ) ), var( maybeClone( other.var ) ), id( other.id ) {
     676UniqueExpr::UniqueExpr( const UniqueExpr &other ) : Expression( other ), expr( maybeClone( other.expr ) ), object( maybeClone( other.object ) ), var( maybeClone( other.var ) ), id( other.id ) {
    679677}
    680678UniqueExpr::~UniqueExpr() {
     
    683681        delete var;
    684682}
    685 void UniqueExpr::print( std::ostream & os, Indenter indent ) const {
     683void UniqueExpr::print( std::ostream &os, Indenter indent ) const {
    686684        os << "Unique Expression with id:" << id << std::endl << indent+1;
    687685        expr->print( os, indent+1 );
     
    734732}
    735733
    736 DeletedExpr::DeletedExpr( Expression * expr, Declaration * deleteStmt ) : expr( expr ), deleteStmt( deleteStmt ) {
     734DeletedExpr::DeletedExpr( Expression * expr, BaseSyntaxNode * deleteStmt ) : expr( expr ), deleteStmt( deleteStmt ) {
    737735        assert( expr->result );
    738736        result = expr->result->clone();
     
    748746        os << std::endl << indent+1 << "... deleted by: ";
    749747        deleteStmt->print( os, indent+1 );
    750 }
    751 
    752 
    753 DefaultArgExpr::DefaultArgExpr( Expression * expr ) : expr( expr ) {
    754         assert( expr->result );
    755         result = expr->result->clone();
    756 }
    757 DefaultArgExpr::DefaultArgExpr( const DefaultArgExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ) {}
    758 DefaultArgExpr::~DefaultArgExpr() {
    759         delete expr;
    760 }
    761 
    762 void DefaultArgExpr::print( std::ostream & os, Indenter indent ) const {
    763         os << "Default Argument Expression" << std::endl << indent+1;
    764         expr->print( os, indent+1 );
    765748}
    766749
  • src/SynTree/Expression.h

    rb067d9b r7951100  
    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 Aug 15 13:46:00 2019
    13 // Update Count     : 54
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun Sep  3 19:23:46 2017
     13// Update Count     : 48
    1414//
    1515
     
    2121#include <memory>                 // for allocator, unique_ptr
    2222#include <string>                 // for string
    23 #include <vector>                 // for vector
    2423
    2524#include "BaseSyntaxNode.h"       // for BaseSyntaxNode
     
    3938/// but subject to decay-to-pointer and type parameter renaming
    4039struct ParamEntry {
    41         ParamEntry(): decl( 0 ), declptr( nullptr ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
    42         ParamEntry( UniqueId decl, Declaration * declptr, Type * actualType, Type * formalType, Expression* expr );
     40        ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 ), inferParams( new InferredParams ) {}
     41        ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr ), inferParams( new InferredParams ) {}
    4342        ParamEntry( const ParamEntry & other );
    4443        ParamEntry( ParamEntry && other );
    4544        ~ParamEntry();
     45        ParamEntry & operator=( const ParamEntry & other );
    4646        ParamEntry & operator=( ParamEntry && other );
    4747
    48         UniqueId const decl;
    49         Declaration * const declptr;
    50         Type * const actualType;
    51         Type * const formalType;
     48        UniqueId decl;
     49        Type * actualType;
     50        Type * formalType;
    5251        Expression * expr;
     52        std::unique_ptr< InferredParams > inferParams;
    5353};
    5454
     
    5959        TypeSubstitution * env;
    6060        bool extension = false;
    61         InferredParams inferParams;       ///< Post-resolution inferred parameter slots
    62         std::vector<UniqueId> resnSlots;  ///< Pre-resolution inferred parameter slots
    63 
    64         // xxx - should turn inferParams+resnSlots into a union to save some memory
     61        InferredParams inferParams;
    6562
    6663        Expression();
     
    7168        const Type * get_result() const { return result; }
    7269        void set_result( Type * newValue ) { result = newValue; }
    73         virtual bool get_lvalue() const;
    7470
    7571        TypeSubstitution * get_env() const { return env; }
     
    7874        Expression * set_extension( bool exten ) { extension = exten; return this; }
    7975
     76        InferredParams & get_inferParams() { return inferParams; }
     77
    8078        // move other's inferParams to this
    8179        void spliceInferParams( Expression * other );
     
    8381        virtual Expression * clone() const override = 0;
    8482        virtual void accept( Visitor & v ) override = 0;
    85         virtual void accept( Visitor & v ) const override = 0;
    8683        virtual Expression * acceptMutator( Mutator & m ) override = 0;
    8784        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    9996        virtual ~ApplicationExpr();
    10097
    101         bool get_lvalue() const final;
    102 
    10398        Expression * get_function() const { return function; }
    10499        void set_function( Expression * newValue ) { function = newValue; }
    105100        std::list<Expression *>& get_args() { return args; }
    106101
    107         virtual ApplicationExpr * clone() const override { return new ApplicationExpr( * this ); }
    108         virtual void accept( Visitor & v ) override { v.visit( this ); }
    109         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    110         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    111         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     102        virtual ApplicationExpr * clone() const { return new ApplicationExpr( * this ); }
     103        virtual void accept( Visitor & v ) { v.visit( this ); }
     104        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     105        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    112106};
    113107
     
    124118        virtual ~UntypedExpr();
    125119
    126         bool get_lvalue() const final;
    127 
    128120        Expression * get_function() const { return function; }
    129121        void set_function( Expression * newValue ) { function = newValue; }
     
    136128        static UntypedExpr * createAssign( Expression * arg1, Expression * arg2 );
    137129
    138         virtual UntypedExpr * clone() const override { return new UntypedExpr( * this ); }
    139         virtual void accept( Visitor & v ) override { v.visit( this ); }
    140         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    141         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    142         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     130        virtual UntypedExpr * clone() const { return new UntypedExpr( * this ); }
     131        virtual void accept( Visitor & v ) { v.visit( this ); }
     132        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     133        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    143134};
    144135
     
    155146        void set_name( std::string newValue ) { name = newValue; }
    156147
    157         virtual NameExpr * clone() const override { return new NameExpr( * this ); }
    158         virtual void accept( Visitor & v ) override { v.visit( this ); }
    159         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    160         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    161         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     148        virtual NameExpr * clone() const { return new NameExpr( * this ); }
     149        virtual void accept( Visitor & v ) { v.visit( this ); }
     150        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     151        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    162152};
    163153
     
    177167        void set_arg(Expression * newValue ) { arg = newValue; }
    178168
    179         virtual AddressExpr * clone() const override { return new AddressExpr( * this ); }
    180         virtual void accept( Visitor & v ) override { v.visit( this ); }
    181         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    182         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    183         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     169        virtual AddressExpr * clone() const { return new AddressExpr( * this ); }
     170        virtual void accept( Visitor & v ) { v.visit( this ); }
     171        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     172        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    184173};
    185174
     
    194183        virtual ~LabelAddressExpr();
    195184
    196         virtual LabelAddressExpr * clone() const override { return new LabelAddressExpr( * this ); }
    197         virtual void accept( Visitor & v ) override { v.visit( this ); }
    198         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    199         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    200         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     185        virtual LabelAddressExpr * clone() const { return new LabelAddressExpr( * this ); }
     186        virtual void accept( Visitor & v ) { v.visit( this ); }
     187        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     188        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    201189};
    202190
     
    205193  public:
    206194        Expression * arg;
    207         bool isGenerated = true; // cast generated implicitly by code generation or explicit in program
     195        bool isGenerated = true; // whether this cast appeared in the source program
    208196
    209197        CastExpr( Expression * arg, bool isGenerated = true );
     
    213201        virtual ~CastExpr();
    214202
    215         bool get_lvalue() const final;
    216 
    217203        Expression * get_arg() const { return arg; }
    218204        void set_arg( Expression * newValue ) { arg = newValue; }
    219205
    220         virtual CastExpr * clone() const override { return new CastExpr( * this ); }
    221         virtual void accept( Visitor & v ) override { v.visit( this ); }
    222         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    223         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    224         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     206        virtual CastExpr * clone() const { return new CastExpr( * this ); }
     207        virtual void accept( Visitor & v ) { v.visit( this ); }
     208        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     209        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    225210};
    226211
     
    239224        const std::string & targetString() const;
    240225
    241         virtual KeywordCastExpr * clone() const override { return new KeywordCastExpr( * this ); }
    242         virtual void accept( Visitor & v ) override { v.visit( this ); }
    243         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    244         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    245         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     226        virtual KeywordCastExpr * clone() const { return new KeywordCastExpr( * this ); }
     227        virtual void accept( Visitor & v ) { v.visit( this ); }
     228        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     229        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    246230};
    247231
     
    258242        void set_arg( Expression * newValue ) { arg = newValue; }
    259243
    260         virtual VirtualCastExpr * clone() const override { return new VirtualCastExpr( * this ); }
    261         virtual void accept( Visitor & v ) override { v.visit( this ); }
    262         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    263         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    264         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     244        virtual VirtualCastExpr * clone() const { return new VirtualCastExpr( * this ); }
     245        virtual void accept( Visitor & v ) { v.visit( this ); }
     246        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     247        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    265248};
    266249
     
    274257        UntypedMemberExpr( const UntypedMemberExpr & other );
    275258        virtual ~UntypedMemberExpr();
    276 
    277         bool get_lvalue() const final;
    278259
    279260        Expression * get_member() const { return member; }
     
    282263        void set_aggregate( Expression * newValue ) { aggregate = newValue; }
    283264
    284         virtual UntypedMemberExpr * clone() const override { return new UntypedMemberExpr( * this ); }
    285         virtual void accept( Visitor & v ) override { v.visit( this ); }
    286         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    287         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    288         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     265        virtual UntypedMemberExpr * clone() const { return new UntypedMemberExpr( * this ); }
     266        virtual void accept( Visitor & v ) { v.visit( this ); }
     267        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     268        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    289269};
    290270
     
    299279        MemberExpr( const MemberExpr & other );
    300280        virtual ~MemberExpr();
    301 
    302         bool get_lvalue() const final;
    303281
    304282        DeclarationWithType * get_member() const { return member; }
     
    307285        void set_aggregate( Expression * newValue ) { aggregate = newValue; }
    308286
    309         virtual MemberExpr * clone() const override { return new MemberExpr( * this ); }
    310         virtual void accept( Visitor & v ) override { v.visit( this ); }
    311         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    312         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    313         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     287        virtual MemberExpr * clone() const { return new MemberExpr( * this ); }
     288        virtual void accept( Visitor & v ) { v.visit( this ); }
     289        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     290        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    314291};
    315292
     
    320297        DeclarationWithType * var;
    321298
    322         VariableExpr();
    323299        VariableExpr( DeclarationWithType * var );
    324300        VariableExpr( const VariableExpr & other );
    325301        virtual ~VariableExpr();
    326302
    327         bool get_lvalue() const final;
    328 
    329303        DeclarationWithType * get_var() const { return var; }
    330304        void set_var( DeclarationWithType * newValue ) { var = newValue; }
     
    332306        static VariableExpr * functionPointer( FunctionDecl * decl );
    333307
    334         virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
    335         virtual void accept( Visitor & v ) override { v.visit( this ); }
    336         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    337         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    338         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     308        virtual VariableExpr * clone() const { return new VariableExpr( * this ); }
     309        virtual void accept( Visitor & v ) { v.visit( this ); }
     310        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     311        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    339312};
    340313
     
    354327        long long int intValue() const;
    355328
    356         virtual ConstantExpr * clone() const override { return new ConstantExpr( * this ); }
    357         virtual void accept( Visitor & v ) override { v.visit( this ); }
    358         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    359         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    360         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     329        virtual ConstantExpr * clone() const { return new ConstantExpr( * this ); }
     330        virtual void accept( Visitor & v ) { v.visit( this ); }
     331        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     332        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    361333};
    362334
     
    380352        void set_isType( bool newValue ) { isType = newValue; }
    381353
    382         virtual SizeofExpr * clone() const override { return new SizeofExpr( * this ); }
    383         virtual void accept( Visitor & v ) override { v.visit( this ); }
    384         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    385         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    386         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     354        virtual SizeofExpr * clone() const { return new SizeofExpr( * this ); }
     355        virtual void accept( Visitor & v ) { v.visit( this ); }
     356        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     357        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    387358};
    388359
     
    406377        void set_isType( bool newValue ) { isType = newValue; }
    407378
    408         virtual AlignofExpr * clone() const override { return new AlignofExpr( * this ); }
    409         virtual void accept( Visitor & v ) override { v.visit( this ); }
    410         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    411         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    412         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     379        virtual AlignofExpr * clone() const { return new AlignofExpr( * this ); }
     380        virtual void accept( Visitor & v ) { v.visit( this ); }
     381        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     382        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    413383};
    414384
     
    428398        void set_type( Type * newValue ) { type = newValue; }
    429399
    430         virtual UntypedOffsetofExpr * clone() const override { return new UntypedOffsetofExpr( * this ); }
    431         virtual void accept( Visitor & v ) override { v.visit( this ); }
    432         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    433         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    434         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     400        virtual UntypedOffsetofExpr * clone() const { return new UntypedOffsetofExpr( * this ); }
     401        virtual void accept( Visitor & v ) { v.visit( this ); }
     402        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     403        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    435404};
    436405
     
    450419        void set_member( DeclarationWithType * newValue ) { member = newValue; }
    451420
    452         virtual OffsetofExpr * clone() const override { return new OffsetofExpr( * this ); }
    453         virtual void accept( Visitor & v ) override { v.visit( this ); }
    454         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    455         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    456         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     421        virtual OffsetofExpr * clone() const { return new OffsetofExpr( * this ); }
     422        virtual void accept( Visitor & v ) { v.visit( this ); }
     423        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     424        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    457425};
    458426
     
    469437        void set_type( StructInstType * newValue ) { type = newValue; }
    470438
    471         virtual OffsetPackExpr * clone() const override { return new OffsetPackExpr( * this ); }
    472         virtual void accept( Visitor & v ) override { v.visit( this ); }
    473         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    474         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    475         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     439        virtual OffsetPackExpr * clone() const { return new OffsetPackExpr( * this ); }
     440        virtual void accept( Visitor & v ) { v.visit( this ); }
     441        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     442        virtual void print( std::ostream & os, Indenter indent = {} ) const;
     443};
     444
     445/// AttrExpr represents an @attribute expression (like sizeof, but user-defined)
     446class AttrExpr : public Expression {
     447  public:
     448        Expression * attr;
     449        Expression * expr;
     450        Type * type;
     451        bool isType;
     452
     453        AttrExpr(Expression * attr, Expression * expr );
     454        AttrExpr( const AttrExpr & other );
     455        AttrExpr( Expression * attr, Type * type );
     456        virtual ~AttrExpr();
     457
     458        Expression * get_attr() const { return attr; }
     459        void set_attr( Expression * newValue ) { attr = newValue; }
     460        Expression * get_expr() const { return expr; }
     461        void set_expr( Expression * newValue ) { expr = newValue; }
     462        Type * get_type() const { return type; }
     463        void set_type( Type * newValue ) { type = newValue; }
     464        bool get_isType() const { return isType; }
     465        void set_isType( bool newValue ) { isType = newValue; }
     466
     467        virtual AttrExpr * clone() const { return new AttrExpr( * this ); }
     468        virtual void accept( Visitor & v ) { v.visit( this ); }
     469        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     470        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    476471};
    477472
     
    492487        void set_arg2( Expression * newValue ) { arg2 = newValue; }
    493488
    494         virtual LogicalExpr * clone() const override { return new LogicalExpr( * this ); }
    495         virtual void accept( Visitor & v ) override { v.visit( this ); }
    496         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    497         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    498         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     489        virtual LogicalExpr * clone() const { return new LogicalExpr( * this ); }
     490        virtual void accept( Visitor & v ) { v.visit( this ); }
     491        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     492        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    499493
    500494  private:
     
    512506        ConditionalExpr( const ConditionalExpr & other );
    513507        virtual ~ConditionalExpr();
    514 
    515         bool get_lvalue() const final;
    516508
    517509        Expression * get_arg1() const { return arg1; }
     
    522514        void set_arg3( Expression * newValue ) { arg3 = newValue; }
    523515
    524         virtual ConditionalExpr * clone() const override { return new ConditionalExpr( * this ); }
    525         virtual void accept( Visitor & v ) override { v.visit( this ); }
    526         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    527         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    528         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     516        virtual ConditionalExpr * clone() const { return new ConditionalExpr( * this ); }
     517        virtual void accept( Visitor & v ) { v.visit( this ); }
     518        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     519        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    529520};
    530521
     
    538529        CommaExpr( const CommaExpr & other );
    539530        virtual ~CommaExpr();
    540 
    541         bool get_lvalue() const final;
    542531
    543532        Expression * get_arg1() const { return arg1; }
     
    546535        void set_arg2( Expression * newValue ) { arg2 = newValue; }
    547536
    548         virtual CommaExpr * clone() const override { return new CommaExpr( * this ); }
    549         virtual void accept( Visitor & v ) override { v.visit( this ); }
    550         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    551         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    552         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     537        virtual CommaExpr * clone() const { return new CommaExpr( * this ); }
     538        virtual void accept( Visitor & v ) { v.visit( this ); }
     539        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     540        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    553541};
    554542
     
    565553        void set_type( Type * newValue ) { type = newValue; }
    566554
    567         virtual TypeExpr * clone() const override { return new TypeExpr( * this ); }
    568         virtual void accept( Visitor & v ) override { v.visit( this ); }
    569         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    570         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    571         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     555        virtual TypeExpr * clone() const { return new TypeExpr( * this ); }
     556        virtual void accept( Visitor & v ) { v.visit( this ); }
     557        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     558        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    572559};
    573560
     
    592579        void set_operand( Expression * newValue ) { operand = newValue; }
    593580
    594         virtual AsmExpr * clone() const override { return new AsmExpr( * this ); }
    595         virtual void accept( Visitor & v ) override { v.visit( this ); }
    596         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    597         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    598         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     581        virtual AsmExpr * clone() const { return new AsmExpr( * this ); }
     582        virtual void accept( Visitor & v ) { v.visit( this ); }
     583        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     584        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    599585
    600586        // https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
     
    605591class ImplicitCopyCtorExpr : public Expression {
    606592public:
    607         ApplicationExpr * callExpr = nullptr;
     593        ApplicationExpr * callExpr;
     594        std::list< ObjectDecl * > tempDecls;
     595        std::list< ObjectDecl * > returnDecls;
     596        std::list< Expression * > dtors;
    608597
    609598        ImplicitCopyCtorExpr( ApplicationExpr * callExpr );
     
    611600        virtual ~ImplicitCopyCtorExpr();
    612601
    613         virtual ImplicitCopyCtorExpr * clone() const override { return new ImplicitCopyCtorExpr( * this ); }
    614         virtual void accept( Visitor & v ) override { v.visit( this ); }
    615         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    616         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    617         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     602        ApplicationExpr * get_callExpr() const { return callExpr; }
     603        void set_callExpr( ApplicationExpr * newValue ) { callExpr = newValue; }
     604
     605        std::list< ObjectDecl * > & get_tempDecls() { return tempDecls; }
     606        std::list< ObjectDecl * > & get_returnDecls() { return returnDecls; }
     607        std::list< Expression * > & get_dtors() { return dtors; }
     608
     609        virtual ImplicitCopyCtorExpr * clone() const { return new ImplicitCopyCtorExpr( * this ); }
     610        virtual void accept( Visitor & v ) { v.visit( this ); }
     611        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     612        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    618613};
    619614
     
    627622        ~ConstructorExpr();
    628623
    629         bool get_lvalue() const final;
    630 
    631624        Expression * get_callExpr() const { return callExpr; }
    632625        void set_callExpr( Expression * newValue ) { callExpr = newValue; }
    633626
    634         virtual ConstructorExpr * clone() const override { return new ConstructorExpr( * this ); }
    635         virtual void accept( Visitor & v ) override { v.visit( this ); }
    636         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    637         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    638         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     627        virtual ConstructorExpr * clone() const { return new ConstructorExpr( * this ); }
     628        virtual void accept( Visitor & v ) { v.visit( this ); }
     629        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     630        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    639631};
    640632
     
    648640        virtual ~CompoundLiteralExpr();
    649641
    650         bool get_lvalue() const final;
    651 
    652642        Initializer * get_initializer() const { return initializer; }
    653643        void set_initializer( Initializer * i ) { initializer = i; }
    654644
    655         virtual CompoundLiteralExpr * clone() const override { return new CompoundLiteralExpr( * this ); }
    656         virtual void accept( Visitor & v ) override { v.visit( this ); }
    657         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    658         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    659         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     645        virtual CompoundLiteralExpr * clone() const { return new CompoundLiteralExpr( * this ); }
     646        virtual void accept( Visitor & v ) { v.visit( this ); }
     647        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     648        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    660649};
    661650
     
    673662        RangeExpr * set_high( Expression * high ) { RangeExpr::high = high; return this; }
    674663
    675         virtual RangeExpr * clone() const override { return new RangeExpr( * this ); }
    676         virtual void accept( Visitor & v ) override { v.visit( this ); }
    677         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    678         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    679         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     664        virtual RangeExpr * clone() const { return new RangeExpr( * this ); }
     665        virtual void accept( Visitor & v ) { v.visit( this ); }
     666        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     667        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    680668};
    681669
     
    691679        std::list<Expression*>& get_exprs() { return exprs; }
    692680
    693         virtual UntypedTupleExpr * clone() const override { return new UntypedTupleExpr( * this ); }
    694         virtual void accept( Visitor & v ) override { v.visit( this ); }
    695         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    696         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    697         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     681        virtual UntypedTupleExpr * clone() const { return new UntypedTupleExpr( * this ); }
     682        virtual void accept( Visitor & v ) { v.visit( this ); }
     683        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     684        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    698685};
    699686
     
    707694        virtual ~TupleExpr();
    708695
    709         bool get_lvalue() const final;
    710 
    711696        std::list<Expression*>& get_exprs() { return exprs; }
    712697
    713         virtual TupleExpr * clone() const override { return new TupleExpr( * this ); }
    714         virtual void accept( Visitor & v ) override { v.visit( this ); }
    715         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    716         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    717         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     698        virtual TupleExpr * clone() const { return new TupleExpr( * this ); }
     699        virtual void accept( Visitor & v ) { v.visit( this ); }
     700        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     701        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    718702};
    719703
     
    727711        TupleIndexExpr( const TupleIndexExpr & other );
    728712        virtual ~TupleIndexExpr();
    729 
    730         bool get_lvalue() const final;
    731713
    732714        Expression * get_tuple() const { return tuple; }
     
    735717        TupleIndexExpr * set_index( unsigned int newValue ) { index = newValue; return this; }
    736718
    737         virtual TupleIndexExpr * clone() const override { return new TupleIndexExpr( * this ); }
    738         virtual void accept( Visitor & v ) override { v.visit( this ); }
    739         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    740         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    741         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     719        virtual TupleIndexExpr * clone() const { return new TupleIndexExpr( * this ); }
     720        virtual void accept( Visitor & v ) { v.visit( this ); }
     721        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     722        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    742723};
    743724
     
    754735        StmtExpr * get_stmtExpr() const { return stmtExpr; }
    755736
    756         virtual TupleAssignExpr * clone() const override { return new TupleAssignExpr( * this ); }
    757         virtual void accept( Visitor & v ) override { v.visit( this ); }
    758         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    759         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    760         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    761 
    762         friend class ConverterNewToOld;
    763   private:
    764     TupleAssignExpr( StmtExpr * stmts );
     737        virtual TupleAssignExpr * clone() const { return new TupleAssignExpr( * this ); }
     738        virtual void accept( Visitor & v ) { v.visit( this ); }
     739        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     740        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    765741};
    766742
     
    772748        std::list< Expression * > dtors; // destructor(s) for return variable(s)
    773749
    774         // readonly
    775         ExprStmt * resultExpr = nullptr;
    776 
    777750        StmtExpr( CompoundStmt * statements );
    778751        StmtExpr( const StmtExpr & other );
    779752        virtual ~StmtExpr();
    780753
    781         bool get_lvalue() const final;
    782 
    783754        CompoundStmt * get_statements() const { return statements; }
    784755        StmtExpr * set_statements( CompoundStmt * newValue ) { statements = newValue; return this; }
     
    790761        std::list< Expression * > & get_dtors() { return dtors; }
    791762
    792         virtual StmtExpr * clone() const override { return new StmtExpr( * this ); }
    793         virtual void accept( Visitor & v ) override { v.visit( this ); }
    794         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    795         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    796         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     763        virtual StmtExpr * clone() const { return new StmtExpr( * this ); }
     764        virtual void accept( Visitor & v ) { v.visit( this ); }
     765        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     766        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    797767};
    798768
     
    818788        int get_id() const { return id; }
    819789
    820         virtual UniqueExpr * clone() const override { return new UniqueExpr( * this ); }
    821         virtual void accept( Visitor & v ) override { v.visit( this ); }
    822         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    823         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    824         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     790        virtual UniqueExpr * clone() const { return new UniqueExpr( * this ); }
     791        virtual void accept( Visitor & v ) { v.visit( this ); }
     792        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     793        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    825794
    826795private:
     
    853822        std::list<InitAlternative> & get_initAlts() { return initAlts; }
    854823
    855         virtual UntypedInitExpr * clone() const override { return new UntypedInitExpr( * this ); }
    856         virtual void accept( Visitor & v ) override { v.visit( this ); }
    857         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    858         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    859         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     824        virtual UntypedInitExpr * clone() const { return new UntypedInitExpr( * this ); }
     825        virtual void accept( Visitor & v ) { v.visit( this ); }
     826        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     827        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    860828};
    861829
     
    875843        InitExpr * set_designation( Designation * newValue ) { designation = newValue; return this; }
    876844
    877         virtual InitExpr * clone() const override { return new InitExpr( * this ); }
    878         virtual void accept( Visitor & v ) override { v.visit( this ); }
    879         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    880         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    881         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     845        virtual InitExpr * clone() const { return new InitExpr( * this ); }
     846        virtual void accept( Visitor & v ) { v.visit( this ); }
     847        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     848        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    882849};
    883850
     
    886853public:
    887854        Expression * expr;
    888         Declaration * deleteStmt;
    889 
    890         DeletedExpr( Expression * expr, Declaration * deleteStmt );
     855        BaseSyntaxNode * deleteStmt;
     856
     857        DeletedExpr( Expression * expr, BaseSyntaxNode * deleteStmt );
    891858        DeletedExpr( const DeletedExpr & other );
    892859        ~DeletedExpr();
    893860
    894         virtual DeletedExpr * clone() const override { return new DeletedExpr( * this ); }
    895         virtual void accept( Visitor & v ) override { v.visit( this ); }
    896         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    897         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    898         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    899 };
    900 
    901 /// expression wrapping the use of a default argument - should never make it past the resolver.
    902 class DefaultArgExpr : public Expression {
    903 public:
    904         Expression * expr;
    905 
    906         DefaultArgExpr( Expression * expr );
    907         DefaultArgExpr( const DefaultArgExpr & other );
    908         ~DefaultArgExpr();
    909 
    910         virtual DefaultArgExpr * clone() const override { return new DefaultArgExpr( * this ); }
    911         virtual void accept( Visitor & v ) override { v.visit( this ); }
    912         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    913         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    914         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     861        virtual DeletedExpr * clone() const { return new DeletedExpr( * this ); }
     862        virtual void accept( Visitor & v ) { v.visit( this ); }
     863        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     864        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    915865};
    916866
     
    937887        virtual ~GenericExpr();
    938888
    939         virtual GenericExpr * clone() const override { return new GenericExpr( * this ); }
    940         virtual void accept( Visitor & v ) override { v.visit( this ); }
    941         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    942         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    943         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     889        virtual GenericExpr * clone() const { return new GenericExpr( * this ); }
     890        virtual void accept( Visitor & v ) { v.visit( this ); }
     891        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     892        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    944893};
    945894
  • src/SynTree/FunctionDecl.cc

    rb067d9b r7951100  
    8787
    8888        if ( statements ) {
    89                 os << indent << "... with body" << endl << indent+1;
     89                os << indent << "... with body " << endl << indent+1;
    9090                statements->print( os, indent+1 );
    9191        } // if
  • src/SynTree/FunctionType.cc

    rb067d9b r7951100  
    6666                os << indent+1 << "accepting unspecified arguments" << endl;
    6767        } // if
    68         os << indent << "... returning";
     68        os << indent << "... returning ";
    6969        if ( returnVals.empty() ) {
    70                 os << " nothing" << endl;
     70                os << "nothing " << endl;
    7171        } else {
    7272                os << endl;
  • src/SynTree/Initializer.h

    rb067d9b r7951100  
    3838
    3939        virtual Designation * clone() const override { return new Designation( *this ); };
    40         virtual void accept( Visitor & v ) override { v.visit( this ); }
    41         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     40        virtual void accept( Visitor &v ) override { v.visit( this ); }
    4241        virtual Designation * acceptMutator( Mutator &m ) override { return m.mutate( this ); }
    4342        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    5352        virtual ~Initializer();
    5453
    55         bool get_maybeConstructed() const { return maybeConstructed; }
     54        bool get_maybeConstructed() { return maybeConstructed; }
    5655
    5756        virtual Initializer *clone() const override = 0;
    58         virtual void accept( Visitor & v ) override = 0;
    59         virtual void accept( Visitor & v ) const override = 0;
     57        virtual void accept( Visitor &v ) override = 0;
    6058        virtual Initializer *acceptMutator( Mutator &m ) override = 0;
    6159        virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
     
    7876
    7977        virtual SingleInit *clone() const override { return new SingleInit( *this); }
    80         virtual void accept( Visitor & v ) override { v.visit( this ); }
    81         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     78        virtual void accept( Visitor &v ) override { v.visit( this ); }
    8279        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    8380        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    107104
    108105        virtual ListInit *clone() const override { return new ListInit( *this ); }
    109         virtual void accept( Visitor & v ) override { v.visit( this ); }
    110         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     106        virtual void accept( Visitor &v ) override { v.visit( this ); }
    111107        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    112108        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    137133
    138134        ConstructorInit *clone() const override { return new ConstructorInit( *this ); }
    139         virtual void accept( Visitor & v ) override { v.visit( this ); }
    140         virtual void accept( Visitor & v ) const override { v.visit( this ); }
     135        virtual void accept( Visitor &v ) override { v.visit( this ); }
    141136        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    142137        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
  • src/SynTree/Label.h

    rb067d9b r7951100  
    3535        operator std::string() const { return name; }
    3636        bool empty() { return name.empty(); }
    37 
     37  private:
    3838        std::string name;
    3939        Statement * labelled;
  • src/SynTree/Mutator.h

    rb067d9b r7951100  
    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 : Thu Jul 25 22:37:46 2019
    13 // Update Count     : 17
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jul 24 16:31:00 2017
     13// Update Count     : 16
    1414//
    1515#pragma once
     
    5252        virtual Statement * mutate( FinallyStmt * catchStmt ) = 0;
    5353        virtual Statement * mutate( WaitForStmt * waitforStmt ) = 0;
    54         virtual Declaration * mutate( WithStmt * withStmt ) = 0;
     54        virtual Statement * mutate( WithStmt * withStmt ) = 0;
    5555        virtual NullStmt * mutate( NullStmt * nullStmt ) = 0;
    5656        virtual Statement * mutate( DeclStmt * declStmt ) = 0;
     
    7474        virtual Expression * mutate( OffsetofExpr * offsetofExpr ) = 0;
    7575        virtual Expression * mutate( OffsetPackExpr * offsetPackExpr ) = 0;
     76        virtual Expression * mutate( AttrExpr * attrExpr ) = 0;
    7677        virtual Expression * mutate( LogicalExpr * logicalExpr ) = 0;
    7778        virtual Expression * mutate( ConditionalExpr * conditionalExpr ) = 0;
     
    9293        virtual Expression * mutate( InitExpr  * initExpr ) = 0;
    9394        virtual Expression * mutate( DeletedExpr * delExpr ) = 0;
    94         virtual Expression * mutate( DefaultArgExpr * argExpr ) = 0;
    9595        virtual Expression * mutate( GenericExpr * genExpr ) = 0;
    9696
     
    100100        virtual Type * mutate( ArrayType * arrayType ) = 0;
    101101        virtual Type * mutate( ReferenceType * refType ) = 0;
    102         virtual Type * mutate( QualifiedType * qualType ) = 0;
    103102        virtual Type * mutate( FunctionType * functionType ) = 0;
    104103        virtual Type * mutate( StructInstType * aggregateUseType ) = 0;
     
    113112        virtual Type * mutate( ZeroType * zeroType ) = 0;
    114113        virtual Type * mutate( OneType * oneType ) = 0;
    115         virtual Type * mutate( GlobalScopeType * globalType ) = 0;
    116114
    117115        virtual Designation * mutate( Designation * designation ) = 0 ;
     
    119117        virtual Initializer * mutate( ListInit * listInit ) = 0 ;
    120118        virtual Initializer * mutate( ConstructorInit * ctorInit ) = 0 ;
     119
     120        virtual Subrange * mutate( Subrange * subrange ) = 0;
    121121
    122122        virtual Constant * mutate( Constant * constant ) = 0;
  • src/SynTree/ObjectDecl.cc

    rb067d9b r7951100  
    6666
    6767        if ( ! attributes.empty() ) {
    68                 os << std::endl << indent << "... with attributes:" << std::endl;
     68                os << std::endl << indent << "... with attributes: " << std::endl;
    6969                printAll( attributes, os, indent+1 );
    7070        }
  • src/SynTree/ReferenceToType.cc

    rb067d9b r7951100  
    7676bool StructInstType::isComplete() const { return baseStruct ? baseStruct->has_body() : false; }
    7777
    78 AggregateDecl * StructInstType::getAggr() const { return baseStruct; }
     78AggregateDecl * StructInstType::getAggr() { return baseStruct; }
    7979
    8080TypeSubstitution StructInstType::genericSubstitution() const {
     
    9393        else {
    9494                Type::print( os, indent );
    95                 os << "instance of " << typeString() << " " << name << " with body " << baseStruct->has_body();
     95                os << "instance of " << typeString() << " " << name << " with body " << baseStruct->has_body() << " ";
    9696                if ( ! parameters.empty() ) {
    9797                        os << endl << indent << "... with parameters" << endl;
     
    119119bool UnionInstType::isComplete() const { return baseUnion ? baseUnion->has_body() : false; }
    120120
    121 AggregateDecl * UnionInstType::getAggr() const { return baseUnion; }
     121AggregateDecl * UnionInstType::getAggr() { return baseUnion; }
    122122
    123123TypeSubstitution UnionInstType::genericSubstitution() const {
     
    136136        else {
    137137                Type::print( os, indent );
    138                 os << "instance of " << typeString() << " " << name << " with body " << baseUnion->has_body();
     138                os << "instance of " << typeString() << " " << name << " with body " << baseUnion->has_body() << " ";
    139139                if ( ! parameters.empty() ) {
    140140                        os << endl << indent << "... with parameters" << endl;
     
    152152bool EnumInstType::isComplete() const { return baseEnum ? baseEnum->has_body() : false; }
    153153
    154 AggregateDecl * EnumInstType::getAggr() const { return baseEnum; }
    155 
    156154void EnumInstType::print( std::ostream &os, Indenter indent ) const {
    157155        using std::endl;
     
    160158        else {
    161159                Type::print( os, indent );
    162                 os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body();
     160                os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body() << " ";
    163161        } // if
    164162}
     
    205203
    206204        Type::print( os, indent );
    207         os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type)";
     205        os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type) ";
    208206        if ( ! parameters.empty() ) {
    209207                os << endl << indent << "... with parameters" << endl;
  • src/SynTree/Statement.cc

    rb067d9b r7951100  
    493493
    494494
    495 WithStmt::WithStmt( const std::list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {}
    496 WithStmt::WithStmt( const WithStmt & other ) : Declaration( other ), stmt( maybeClone( other.stmt ) ) {
     495WithStmt::WithStmt( const std::list< Expression * > & exprs, Statement * stmt ) : Statement(), exprs( exprs ), stmt( stmt ) {}
     496WithStmt::WithStmt( const WithStmt & other ) : Statement( other ), stmt( maybeClone( other.stmt ) ) {
    497497        cloneAll( other.exprs, exprs );
    498498}
  • src/SynTree/Statement.h

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar 12 09:01:53 2019
    13 // Update Count     : 83
     12// Last Modified On : Thu Mar  8 14:53:02 2018
     13// Update Count     : 78
    1414//
    1515
     
    1919#include <list>                    // for list
    2020#include <memory>                  // for allocator
    21 #include <vector>                                  // for vector
     21#include <vector>                        // for vector
    2222
    2323#include "BaseSyntaxNode.h"        // for BaseSyntaxNode
     
    4343        const std::list<Label> & get_labels() const { return labels; }
    4444
    45         virtual Statement * clone() const override = 0;
    46         virtual void accept( Visitor & v ) override = 0;
    47         virtual void accept( Visitor & v ) const override = 0;
    48         virtual Statement * acceptMutator( Mutator & m ) override = 0;
    49         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     45        virtual Statement *clone() const override = 0;
     46        virtual void accept( Visitor &v ) override = 0;
     47        virtual Statement *acceptMutator( Mutator &m ) override = 0;
     48        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    5049};
    5150
     
    5655        CompoundStmt();
    5756        CompoundStmt( std::list<Statement *> stmts );
    58         CompoundStmt( const CompoundStmt & other );
     57        CompoundStmt( const CompoundStmt &other );
    5958        virtual ~CompoundStmt();
    6059
     
    6362        void push_front( Statement * stmt ) { kids.push_front( stmt ); }
    6463
    65         virtual CompoundStmt * clone() const override { return new CompoundStmt( *this ); }
    66         virtual void accept( Visitor & v ) override { v.visit( this ); }
    67         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    68         virtual CompoundStmt * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    69         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     64        virtual CompoundStmt *clone() const override { return new CompoundStmt( *this ); }
     65        virtual void accept( Visitor &v ) override { v.visit( this ); }
     66        virtual CompoundStmt *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     67        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    7068};
    7169
     
    7472        NullStmt( const std::list<Label> & labels = {} );
    7573
    76         virtual NullStmt * clone() const override { return new NullStmt( *this ); }
    77         virtual void accept( Visitor & v ) override { v.visit( this ); }
    78         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    79         virtual NullStmt * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    80         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     74        virtual NullStmt *clone() const override { return new NullStmt( *this ); }
     75        virtual void accept( Visitor &v ) override { v.visit( this ); }
     76        virtual NullStmt *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     77        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    8178};
    8279
    8380class ExprStmt : public Statement {
    8481  public:
    85         Expression * expr;
    86 
    87         ExprStmt( Expression * expr );
    88         ExprStmt( const ExprStmt & other );
     82        Expression *expr;
     83
     84        ExprStmt( Expression *expr );
     85        ExprStmt( const ExprStmt &other );
    8986        virtual ~ExprStmt();
    9087
    91         Expression * get_expr() { return expr; }
    92         void set_expr( Expression * newValue ) { expr = newValue; }
    93 
    94         virtual ExprStmt * clone() const override { return new ExprStmt( *this ); }
    95         virtual void accept( Visitor & v ) override { v.visit( this ); }
    96         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    97         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    98         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     88        Expression *get_expr() { return expr; }
     89        void set_expr( Expression *newValue ) { expr = newValue; }
     90
     91        virtual ExprStmt *clone() const override { return new ExprStmt( *this ); }
     92        virtual void accept( Visitor &v ) override { v.visit( this ); }
     93        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     94        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    9995};
    10096
     
    10298  public:
    10399        bool voltile;
    104         Expression * instruction;
     100        Expression *instruction;
    105101        std::list<Expression *> output, input;
    106102        std::list<ConstantExpr *> clobber;
    107103        std::list<Label> gotolabels;
    108104
    109         AsmStmt( bool voltile, Expression * instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels );
    110         AsmStmt( const AsmStmt & other );
     105        AsmStmt( bool voltile, Expression *instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels );
     106        AsmStmt( const AsmStmt &other );
    111107        virtual ~AsmStmt();
    112108
     
    118114        void set_output( const std::list<Expression *> & newValue ) { output = newValue; }
    119115        std::list<Expression *> & get_input() { return input; }
    120         void set_input( const std::list<Expression *> & newValue ) { input = newValue; }
     116        void set_input( const std::list<Expression *> &newValue ) { input = newValue; }
    121117        std::list<ConstantExpr *> & get_clobber() { return clobber; }
    122         void set_clobber( const std::list<ConstantExpr *> & newValue ) { clobber = newValue; }
     118        void set_clobber( const std::list<ConstantExpr *> &newValue ) { clobber = newValue; }
    123119        std::list<Label> & get_gotolabels() { return gotolabels; }
    124         void set_gotolabels( const std::list<Label> & newValue ) { gotolabels = newValue; }
    125 
    126         virtual AsmStmt * clone() const override { return new AsmStmt( *this ); }
    127         virtual void accept( Visitor & v ) override { v.visit( this ); }
    128         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    129         virtual Statement * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    130         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     120        void set_gotolabels( const std::list<Label> &newValue ) { gotolabels = newValue; }
     121
     122        virtual AsmStmt * clone() const { return new AsmStmt( *this ); }
     123        virtual void accept( Visitor & v ) { v.visit( this ); }
     124        virtual Statement * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     125        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    131126};
    132127
     
    138133        virtual ~DirectiveStmt(){}
    139134
    140         virtual DirectiveStmt * clone() const override { return new DirectiveStmt( *this ); }
    141         virtual void accept( Visitor & v ) override { v.visit( this ); }
    142         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    143         virtual Statement * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    144         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     135        virtual DirectiveStmt * clone() const { return new DirectiveStmt( *this ); }
     136        virtual void accept( Visitor & v ) { v.visit( this ); }
     137        virtual Statement * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     138        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    145139};
    146140
    147141class IfStmt : public Statement {
    148142  public:
    149         Expression * condition;
    150         Statement * thenPart;
    151         Statement * elsePart;
     143        Expression *condition;
     144        Statement *thenPart;
     145        Statement *elsePart;
    152146        std::list<Statement *> initialization;
    153147
    154         IfStmt( Expression * condition, Statement * thenPart, Statement * elsePart,
     148        IfStmt( Expression *condition, Statement *thenPart, Statement *elsePart,
    155149                        std::list<Statement *> initialization = std::list<Statement *>() );
    156         IfStmt( const IfStmt & other );
     150        IfStmt( const IfStmt &other );
    157151        virtual ~IfStmt();
    158152
    159         std::list<Statement *> & get_initialization() { return initialization; }
    160         Expression * get_condition() { return condition; }
    161         void set_condition( Expression * newValue ) { condition = newValue; }
    162         Statement * get_thenPart() { return thenPart; }
    163         void set_thenPart( Statement * newValue ) { thenPart = newValue; }
    164         Statement * get_elsePart() { return elsePart; }
    165         void set_elsePart( Statement * newValue ) { elsePart = newValue; }
    166 
    167         virtual IfStmt * clone() const override { return new IfStmt( *this ); }
    168         virtual void accept( Visitor & v ) override { v.visit( this ); }
    169         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    170         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    171         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     153        std::list<Statement *> &get_initialization() { return initialization; }
     154        Expression *get_condition() { return condition; }
     155        void set_condition( Expression *newValue ) { condition = newValue; }
     156        Statement *get_thenPart() { return thenPart; }
     157        void set_thenPart( Statement *newValue ) { thenPart = newValue; }
     158        Statement *get_elsePart() { return elsePart; }
     159        void set_elsePart( Statement *newValue ) { elsePart = newValue; }
     160
     161        virtual IfStmt *clone() const override { return new IfStmt( *this ); }
     162        virtual void accept( Visitor &v ) override { v.visit( this ); }
     163        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     164        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    172165};
    173166
     
    177170        std::list<Statement *> statements;
    178171
    179         SwitchStmt( Expression * condition, const std::list<Statement *> & statements );
    180         SwitchStmt( const SwitchStmt & other );
     172        SwitchStmt( Expression *condition, const std::list<Statement *> &statements );
     173        SwitchStmt( const SwitchStmt &other );
    181174        virtual ~SwitchStmt();
    182175
    183         Expression * get_condition() { return condition; }
    184         void set_condition( Expression * newValue ) { condition = newValue; }
     176        Expression *get_condition() { return condition; }
     177        void set_condition( Expression *newValue ) { condition = newValue; }
    185178
    186179        std::list<Statement *> & get_statements() { return statements; }
    187180
    188         virtual void accept( Visitor & v ) override { v.visit( this ); }
    189         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    190         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    191 
    192         virtual SwitchStmt * clone() const override { return new SwitchStmt( *this ); }
    193         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     181        virtual void accept( Visitor &v ) override { v.visit( this ); }
     182        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     183
     184        virtual SwitchStmt *clone() const override { return new SwitchStmt( *this ); }
     185        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    194186
    195187};
     
    200192        std::list<Statement *> stmts;
    201193
    202         CaseStmt( Expression * conditions, const std::list<Statement *> & stmts, bool isdef = false ) throw (SemanticErrorException);
    203         CaseStmt( const CaseStmt & other );
     194        CaseStmt( Expression *conditions, const std::list<Statement *> &stmts, bool isdef = false ) throw (SemanticErrorException);
     195        CaseStmt( const CaseStmt &other );
    204196        virtual ~CaseStmt();
    205197
     
    209201        void set_default(bool b) { _isDefault = b; }
    210202
    211         Expression * & get_condition() { return condition; }
    212         void set_condition( Expression * newValue ) { condition = newValue; }
    213 
    214         std::list<Statement *> & get_statements() { return stmts; }
    215         void set_statements( std::list<Statement *> & newValue ) { stmts = newValue; }
    216 
    217         virtual void accept( Visitor & v ) override { v.visit( this ); }
    218         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    219         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    220 
    221         virtual CaseStmt * clone() const override { return new CaseStmt( *this ); }
    222         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     203        Expression * &get_condition() { return condition; }
     204        void set_condition( Expression *newValue ) { condition = newValue; }
     205
     206        std::list<Statement *> &get_statements() { return stmts; }
     207        void set_statements( std::list<Statement *> &newValue ) { stmts = newValue; }
     208
     209        virtual void accept( Visitor &v ) override { v.visit( this ); }
     210        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     211
     212        virtual CaseStmt *clone() const override { return new CaseStmt( *this ); }
     213        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    223214  private:
    224215        bool _isDefault;
     
    227218class WhileStmt : public Statement {
    228219  public:
    229         Expression * condition;
    230         Statement * body;
     220        Expression *condition;
     221        Statement *body;
    231222        std::list<Statement *> initialization;
    232223        bool isDoWhile;
    233224
    234         WhileStmt( Expression * condition, Statement * body, std::list<Statement *> & initialization, bool isDoWhile = false );
    235         WhileStmt( const WhileStmt & other );
     225        WhileStmt( Expression *condition,
     226               Statement *body, std::list<Statement *> & initialization, bool isDoWhile = false );
     227        WhileStmt( const WhileStmt &other );
    236228        virtual ~WhileStmt();
    237229
    238         Expression * get_condition() { return condition; }
    239         void set_condition( Expression * newValue ) { condition = newValue; }
    240         Statement * get_body() { return body; }
    241         void set_body( Statement * newValue ) { body = newValue; }
     230        Expression *get_condition() { return condition; }
     231        void set_condition( Expression *newValue ) { condition = newValue; }
     232        Statement *get_body() { return body; }
     233        void set_body( Statement *newValue ) { body = newValue; }
    242234        bool get_isDoWhile() { return isDoWhile; }
    243235        void set_isDoWhile( bool newValue ) { isDoWhile = newValue; }
    244236
    245         virtual WhileStmt * clone() const override { return new WhileStmt( *this ); }
    246         virtual void accept( Visitor & v ) override { v.visit( this ); }
    247         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    248         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    249         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     237        virtual WhileStmt *clone() const override { return new WhileStmt( *this ); }
     238        virtual void accept( Visitor &v ) override { v.visit( this ); }
     239        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     240        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    250241};
    251242
     
    253244  public:
    254245        std::list<Statement *> initialization;
    255         Expression * condition;
    256         Expression * increment;
    257         Statement * body;
    258 
    259         ForStmt( std::list<Statement *> initialization, Expression * condition = 0, Expression * increment = 0, Statement * body = 0 );
    260         ForStmt( const ForStmt & other );
     246        Expression *condition;
     247        Expression *increment;
     248        Statement *body;
     249
     250        ForStmt( std::list<Statement *> initialization,
     251             Expression *condition = 0, Expression *increment = 0, Statement *body = 0 );
     252        ForStmt( const ForStmt &other );
    261253        virtual ~ForStmt();
    262254
    263         std::list<Statement *> & get_initialization() { return initialization; }
    264         Expression * get_condition() { return condition; }
    265         void set_condition( Expression * newValue ) { condition = newValue; }
    266         Expression * get_increment() { return increment; }
    267         void set_increment( Expression * newValue ) { increment = newValue; }
    268         Statement * get_body() { return body; }
    269         void set_body( Statement * newValue ) { body = newValue; }
    270 
    271         virtual ForStmt * clone() const override { return new ForStmt( *this ); }
    272         virtual void accept( Visitor & v ) override { v.visit( this ); }
    273         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    274         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    275         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     255        std::list<Statement *> &get_initialization() { return initialization; }
     256        Expression *get_condition() { return condition; }
     257        void set_condition( Expression *newValue ) { condition = newValue; }
     258        Expression *get_increment() { return increment; }
     259        void set_increment( Expression *newValue ) { increment = newValue; }
     260        Statement *get_body() { return body; }
     261        void set_body( Statement *newValue ) { body = newValue; }
     262
     263        virtual ForStmt *clone() const override { return new ForStmt( *this ); }
     264        virtual void accept( Visitor &v ) override { v.visit( this ); }
     265        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     266        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    276267};
    277268
     
    283274        const Label originalTarget;
    284275        Label target;
    285         Expression * computedTarget;
     276        Expression *computedTarget;
    286277        Type type;
    287278
    288279        BranchStmt( Label target, Type ) throw (SemanticErrorException);
    289         BranchStmt( Expression * computedTarget, Type ) throw (SemanticErrorException);
     280        BranchStmt( Expression *computedTarget, Type ) throw (SemanticErrorException);
    290281
    291282        Label get_originalTarget() { return originalTarget; }
     
    293284        void set_target( Label newValue ) { target = newValue; }
    294285
    295         Expression * get_computedTarget() { return computedTarget; }
     286        Expression *get_computedTarget() { return computedTarget; }
    296287        void set_target( Expression * newValue ) { computedTarget = newValue; }
    297288
    298289        Type get_type() { return type; }
    299         const char * get_typename() { return brType[ type ]; }
    300 
    301         virtual BranchStmt * clone() const override { return new BranchStmt( *this ); }
    302         virtual void accept( Visitor & v ) override { v.visit( this ); }
    303         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    304         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    305         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     290        const char *get_typename() { return brType[ type ]; }
     291
     292        virtual BranchStmt *clone() const override { return new BranchStmt( *this ); }
     293        virtual void accept( Visitor &v ) override { v.visit( this ); }
     294        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     295        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    306296  private:
    307         static const char * brType[];
     297        static const char *brType[];
    308298};
    309299
    310300class ReturnStmt : public Statement {
    311301  public:
    312         Expression * expr;
    313 
    314         ReturnStmt( Expression * expr );
    315         ReturnStmt( const ReturnStmt & other );
     302        Expression *expr;
     303
     304        ReturnStmt( Expression *expr );
     305        ReturnStmt( const ReturnStmt &other );
    316306        virtual ~ReturnStmt();
    317307
    318         Expression * get_expr() { return expr; }
    319         void set_expr( Expression * newValue ) { expr = newValue; }
    320 
    321         virtual ReturnStmt * clone() const override { return new ReturnStmt( *this ); }
    322         virtual void accept( Visitor & v ) override { v.visit( this ); }
    323         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    324         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    325         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     308        Expression *get_expr() { return expr; }
     309        void set_expr( Expression *newValue ) { expr = newValue; }
     310
     311        virtual ReturnStmt *clone() const override { return new ReturnStmt( *this ); }
     312        virtual void accept( Visitor &v ) override { v.visit( this ); }
     313        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     314        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    326315};
    327316
     
    335324
    336325        ThrowStmt( Kind kind, Expression * expr, Expression * target = nullptr );
    337         ThrowStmt( const ThrowStmt & other );
     326        ThrowStmt( const ThrowStmt &other );
    338327        virtual ~ThrowStmt();
    339328
     
    344333        void set_target( Expression * newTarget ) { target = newTarget; }
    345334
    346         virtual ThrowStmt * clone() const override { return new ThrowStmt( *this ); }
    347         virtual void accept( Visitor & v ) override { v.visit( this ); }
    348         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    349         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    350         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     335        virtual ThrowStmt *clone() const override { return new ThrowStmt( *this ); }
     336        virtual void accept( Visitor &v ) override { v.visit( this ); }
     337        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     338        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    351339};
    352340
     
    357345        FinallyStmt * finallyBlock;
    358346
    359         TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = 0 );
    360         TryStmt( const TryStmt & other );
     347        TryStmt( CompoundStmt *tryBlock, std::list<CatchStmt *> &handlers, FinallyStmt *finallyBlock = 0 );
     348        TryStmt( const TryStmt &other );
    361349        virtual ~TryStmt();
    362350
    363         CompoundStmt * get_block() const { return block; }
    364         void set_block( CompoundStmt * newValue ) { block = newValue; }
     351        CompoundStmt *get_block() const { return block; }
     352        void set_block( CompoundStmt *newValue ) { block = newValue; }
    365353        std::list<CatchStmt *>& get_catchers() { return handlers; }
    366354
    367         FinallyStmt * get_finally() const { return finallyBlock; }
    368         void set_finally( FinallyStmt * newValue ) { finallyBlock = newValue; }
    369 
    370         virtual TryStmt * clone() const override { return new TryStmt( *this ); }
    371         virtual void accept( Visitor & v ) override { v.visit( this ); }
    372         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    373         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    374         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     355        FinallyStmt *get_finally() const { return finallyBlock; }
     356        void set_finally( FinallyStmt *newValue ) { finallyBlock = newValue; }
     357
     358        virtual TryStmt *clone() const override { return new TryStmt( *this ); }
     359        virtual void accept( Visitor &v ) override { v.visit( this ); }
     360        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     361        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    375362};
    376363
     
    380367
    381368        const Kind kind;
    382         Declaration * decl;
    383         Expression * cond;
    384         Statement * body;
    385 
    386         CatchStmt( Kind kind, Declaration * decl,
    387                    Expression * cond, Statement * body );
    388         CatchStmt( const CatchStmt & other );
     369        Declaration *decl;
     370        Expression *cond;
     371        Statement *body;
     372
     373        CatchStmt( Kind kind, Declaration *decl,
     374                   Expression *cond, Statement *body );
     375        CatchStmt( const CatchStmt &other );
    389376        virtual ~CatchStmt();
    390377
    391378        Kind get_kind() { return kind; }
    392         Declaration * get_decl() { return decl; }
    393         void set_decl( Declaration * newValue ) { decl = newValue; }
    394         Expression * get_cond() { return cond; }
    395         void set_cond( Expression * newCond ) { cond = newCond; }
    396         Statement * get_body() { return body; }
    397         void set_body( Statement * newValue ) { body = newValue; }
    398 
    399         virtual CatchStmt * clone() const override { return new CatchStmt( *this ); }
    400         virtual void accept( Visitor & v ) override { v.visit( this ); }
    401         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    402         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    403         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     379        Declaration *get_decl() { return decl; }
     380        void set_decl( Declaration *newValue ) { decl = newValue; }
     381        Expression *get_cond() { return cond; }
     382        void set_cond( Expression *newCond ) { cond = newCond; }
     383        Statement *get_body() { return body; }
     384        void set_body( Statement *newValue ) { body = newValue; }
     385
     386        virtual CatchStmt *clone() const override { return new CatchStmt( *this ); }
     387        virtual void accept( Visitor &v ) override { v.visit( this ); }
     388        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     389        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    404390};
    405391
    406392class FinallyStmt : public Statement {
    407393  public:
    408         CompoundStmt * block;
    409 
    410         FinallyStmt( CompoundStmt * block );
    411         FinallyStmt( const FinallyStmt & other );
     394        CompoundStmt *block;
     395
     396        FinallyStmt( CompoundStmt *block );
     397        FinallyStmt( const FinallyStmt &other );
    412398        virtual ~FinallyStmt();
    413399
    414         CompoundStmt * get_block() const { return block; }
    415         void set_block( CompoundStmt * newValue ) { block = newValue; }
    416 
    417         virtual FinallyStmt * clone() const override { return new FinallyStmt( *this ); }
    418         virtual void accept( Visitor & v ) override { v.visit( this ); }
    419         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    420         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    421         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     400        CompoundStmt *get_block() const { return block; }
     401        void set_block( CompoundStmt *newValue ) { block = newValue; }
     402
     403        virtual FinallyStmt *clone() const override { return new FinallyStmt( *this ); }
     404        virtual void accept( Visitor &v ) override { v.visit( this ); }
     405        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     406        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    422407};
    423408
     
    453438        } orelse;
    454439
    455         virtual WaitForStmt * clone() const override { return new WaitForStmt( *this ); }
     440        virtual WaitForStmt *clone() const override { return new WaitForStmt( *this ); }
     441        virtual void accept( Visitor &v ) override { v.visit( this ); }
     442        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     443        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     444
     445};
     446
     447class WithStmt : public Statement {
     448public:
     449        std::list< Expression * > exprs;
     450        Statement * stmt;
     451
     452        WithStmt( const std::list< Expression * > & exprs, Statement * stmt );
     453        WithStmt( const WithStmt & other );
     454        virtual ~WithStmt();
     455
     456        virtual WithStmt * clone() const override { return new WithStmt( *this ); }
    456457        virtual void accept( Visitor & v ) override { v.visit( this ); }
    457         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    458458        virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    459459        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    460 
    461 };
    462 
    463 // class WithStmt : public Statement {
    464 // public:
    465 //      std::list< Expression * > exprs;
    466 //      Statement * stmt;
    467 
    468 //      WithStmt( const std::list< Expression * > & exprs, Statement * stmt );
    469 //      WithStmt( const WithStmt & other );
    470 //      virtual ~WithStmt();
    471 
    472 //      virtual WithStmt * clone() const override { return new WithStmt( *this ); }
    473 //      virtual void accept( Visitor & v ) override { v.visit( this ); }
    474 //      virtual void accept( Visitor & v ) const override { v.visit( this ); }
    475 //      virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    476 //      virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    477 // };
     460};
    478461
    479462
     
    481464class DeclStmt : public Statement {
    482465  public:
    483         Declaration * decl;
    484 
    485         DeclStmt( Declaration * decl );
    486         DeclStmt( const DeclStmt & other );
     466        Declaration *decl;
     467
     468        DeclStmt( Declaration *decl );
     469        DeclStmt( const DeclStmt &other );
    487470        virtual ~DeclStmt();
    488471
    489         Declaration * get_decl() const { return decl; }
    490         void set_decl( Declaration * newValue ) { decl = newValue; }
    491 
    492         virtual DeclStmt * clone() const override { return new DeclStmt( *this ); }
    493         virtual void accept( Visitor & v ) override { v.visit( this ); }
    494         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    495         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    496         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    497 };
    498 
    499 
    500 /// represents an implicit application of a constructor or destructor. Qualifiers are replaced immediately before and
    501 /// after the call so that qualified objects can be constructed with the same functions as unqualified objects.
     472        Declaration *get_decl() const { return decl; }
     473        void set_decl( Declaration *newValue ) { decl = newValue; }
     474
     475        virtual DeclStmt *clone() const override { return new DeclStmt( *this ); }
     476        virtual void accept( Visitor &v ) override { v.visit( this ); }
     477        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     478        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     479};
     480
     481
     482/// represents an implicit application of a constructor or destructor. Qualifiers are replaced
     483/// immediately before and after the call so that qualified objects can be constructed
     484/// with the same functions as unqualified objects.
    502485class ImplicitCtorDtorStmt : public Statement {
    503486  public:
     
    509492        virtual ~ImplicitCtorDtorStmt();
    510493
    511         Statement * get_callStmt() const { return callStmt; }
     494        Statement *get_callStmt() const { return callStmt; }
    512495        void set_callStmt( Statement * newValue ) { callStmt = newValue; }
    513496
    514         virtual ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt( *this ); }
    515         virtual void accept( Visitor & v ) override { v.visit( this ); }
    516         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    517         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    518         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     497        virtual ImplicitCtorDtorStmt *clone() const override { return new ImplicitCtorDtorStmt( *this ); }
     498        virtual void accept( Visitor &v ) override { v.visit( this ); }
     499        virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     500        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
    519501};
    520502
  • src/SynTree/SynTree.h

    rb067d9b r7951100  
    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 : Thu Jul 25 22:37:45 2019
    13 // Update Count     : 12
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jul 24 16:54:00 2017
     13// Update Count     : 11
    1414//
    1515
     
    3434class NamedTypeDecl;
    3535class TypeDecl;
     36class FtypeDecl;
     37class DtypeDecl;
    3638class TypedefDecl;
    3739class AsmDecl;
     
    7981class OffsetofExpr;
    8082class OffsetPackExpr;
     83class AttrExpr;
    8184class LogicalExpr;
    8285class ConditionalExpr;
     
    8790class ConstructorExpr;
    8891class CompoundLiteralExpr;
     92class UntypedValofExpr;
    8993class RangeExpr;
    9094class UntypedTupleExpr;
     
    97101class InitExpr;
    98102class DeletedExpr;
    99 class DefaultArgExpr;
    100103class GenericExpr;
    101104
     
    106109class ArrayType;
    107110class ReferenceType;
    108 class QualifiedType;
    109111class FunctionType;
    110112class ReferenceToType;
     
    120122class ZeroType;
    121123class OneType;
    122 class GlobalScopeType;
    123124
    124125class Designation;
     
    127128class ListInit;
    128129class ConstructorInit;
     130
     131class Subrange;
    129132
    130133//template <class T>    // emulate a union with templates?
  • src/SynTree/TupleExpr.cc

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Aug 14 14:34:00 2019
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Mar 17 09:42:29 2017
     13// Update Count     : 3
    1414//
    1515
     
    5757}
    5858
    59 bool TupleExpr::get_lvalue() const {
    60         return false;
    61 }
    62 
    6359void TupleExpr::print( std::ostream &os, Indenter indent ) const {
    6460        os << "Tuple:" << std::endl;
     
    7167        assertf( type->size() > index, "TupleIndexExpr index out of bounds: tuple size %d, requested index %d in expr %s", type->size(), index, toString( tuple ).c_str() );
    7268        set_result( (*std::next( type->get_types().begin(), index ))->clone() );
     69        // like MemberExpr, TupleIndexExpr is always an lvalue
     70        get_result()->set_lvalue( true );
    7371}
    7472
     
    7876TupleIndexExpr::~TupleIndexExpr() {
    7977        delete tuple;
    80 }
    81 
    82 bool TupleIndexExpr::get_lvalue() const {
    83         return tuple->get_lvalue();
    8478}
    8579
     
    111105}
    112106
    113 TupleAssignExpr::TupleAssignExpr(
    114         StmtExpr * s )
    115 : Expression(), stmtExpr(s) {
    116 }
    117 
    118 
    119107TupleAssignExpr::~TupleAssignExpr() {
    120108        delete stmtExpr;
  • src/SynTree/Type.cc

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug  4 21:05:07 2019
    13 // Update Count     : 45
     12// Last Modified On : Mon Sep 25 15:16:32 2017
     13// Update Count     : 38
    1414//
    1515#include "Type.h"
     
    2424using namespace std;
    2525
    26 const char * BasicType::typeNames[] = {
     26const char *BasicType::typeNames[] = {
    2727        "_Bool",
    2828        "char",
     
    3737        "signed long long int",
    3838        "unsigned long long int",
     39        "float",
     40        "double",
     41        "long double",
     42        "float _Complex",
     43        "double _Complex",
     44        "long double _Complex",
     45        "float _Imaginary",
     46        "double _Imaginary",
     47        "long double _Imaginary",
    3948        "__int128",
    4049        "unsigned __int128",
    41         "_Float16",
    42         "_Float16 _Complex",
    43         "_Float32",
    44         "_Float32 _Complex",
    45         "float",
    46         "float _Complex",
    47         //"float _Imaginary",
    48         "_Float32x",
    49         "_Float32x _Complex",
    50         "_Float64",
    51         "_Float64 _Complex",
    52         "double",
    53         "double _Complex",
    54         //"double _Imaginary",
    55         "_Float64x",
    56         "_Float64x _Complex",
    5750        "__float80",
    58         "_Float128",
    59         "_Float128 _Complex",
    60         "__float128",
    61         "long double",
    62         "long double _Complex",
    63         //"long double _Imaginary",
    64         "_Float128x",
    65         "_Float128x _Complex",
     51        "__float128"
    6652};
    6753static_assert(
    68         sizeof(BasicType::typeNames) / sizeof(BasicType::typeNames[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
     54        sizeof(BasicType::typeNames)/sizeof(BasicType::typeNames[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
    6955        "Each basic type name should have a corresponding kind enum value"
    7056);
     
    8369
    8470// These must remain in the same order as the corresponding bit fields.
    85 const char * Type::FuncSpecifiersNames[] = { "inline", "_Noreturn", "fortran" };
     71const char * Type::FuncSpecifiersNames[] = { "inline", "fortran", "_Noreturn" };
    8672const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "_Thread_local" };
    87 const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "mutex", "_Atomic" };
     73const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
    8874
    8975Type * Type::stripDeclarator() {
     
    10086}
    10187
    102 const Type * Type::stripReferences() const {
    103         const Type * type;
    104         const ReferenceType * ref;
    105         for ( type = this; (ref = dynamic_cast<const ReferenceType *>( type )); type = ref->base );
    106         return type;
    107 }
    108 
    10988int Type::referenceDepth() const { return 0; }
    11089
    11190TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
    11291
    113 void Type::print( std::ostream & os, Indenter indent ) const {
     92void Type::print( std::ostream &os, Indenter indent ) const {
    11493        if ( ! forall.empty() ) {
    11594                os << "forall" << std::endl;
     
    126105}
    127106
    128 
    129 QualifiedType::QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child ) : Type( tq, {} ), parent( parent ), child( child ) {
    130 }
    131 
    132 QualifiedType::QualifiedType( const QualifiedType & other ) : Type( other ), parent( maybeClone( other.parent ) ), child( maybeClone( other.child ) ) {
    133 }
    134 
    135 QualifiedType::~QualifiedType() {
    136         delete parent;
    137         delete child;
    138 }
    139 
    140 void QualifiedType::print( std::ostream & os, Indenter indent ) const {
    141         os << "Qualified Type:" << endl;
    142         os << indent+1;
    143         parent->print( os, indent+1 );
    144         os << endl << indent+1;
    145         child->print( os, indent+1 );
    146         os << endl;
    147         Type::print( os, indent+1 );
    148 }
    149 
    150 GlobalScopeType::GlobalScopeType() : Type( Type::Qualifiers(), {} ) {}
    151 
    152 void GlobalScopeType::print( std::ostream & os, Indenter ) const {
    153         os << "Global Scope Type" << endl;
    154 }
    155 
    156 
    157107// Empty Variable declarations:
    158108const Type::FuncSpecifiers noFuncSpecifiers;
  • src/SynTree/Type.h

    rb067d9b r7951100  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Sep  4 09:58:00 2019
    13 // Update Count     : 170
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Sep 25 14:14:01 2017
     13// Update Count     : 154
    1414//
    1515
     
    102102        }; // StorageClasses
    103103
    104         enum { Const = 1 << 0, Restrict = 1 << 1, Volatile = 1 << 2, Mutex = 1 << 3, Atomic = 1 << 4, NumTypeQualifier = 5 };
     104        enum { Const = 1 << 0, Restrict = 1 << 1, Volatile = 1 << 2, Lvalue = 1 << 3, Mutex = 1 << 4, Atomic = 1 << 5, NumTypeQualifier = 6 };
    105105        static const char * QualifiersNames[];
    106106        union Qualifiers {
    107                 enum { Mask = ~Restrict };
     107                enum { Mask = ~(Restrict | Lvalue) };
    108108                unsigned int val;
    109109                struct {
     
    111111                        bool is_restrict : 1;
    112112                        bool is_volatile : 1;
     113                        bool is_lvalue : 1;
    113114                        bool is_mutex : 1;
    114115                        bool is_atomic : 1;
     
    130131                bool operator>( Qualifiers other ) const { return *this != other && *this >= other; }
    131132                BFCommon( Qualifiers, NumTypeQualifier )
    132 
    133                 Qualifiers unify( Qualifiers const & other ) const {
    134                         int or_flags = Mask & (val | other.val);
    135                         int and_flags = val & other.val;
    136                         return Qualifiers( or_flags | and_flags );
    137                 }
    138133        }; // Qualifiers
    139134
     
    149144
    150145        Qualifiers & get_qualifiers() { return tq; }
    151         bool get_const() const { return tq.is_const; }
    152         bool get_volatile() const { return tq.is_volatile; }
    153         bool get_restrict() const { return tq.is_restrict; }
    154         bool get_mutex() const { return tq.is_mutex; }
    155         bool get_atomic() const { return tq.is_atomic; }
     146        bool get_const() { return tq.is_const; }
     147        bool get_volatile() { return tq.is_volatile; }
     148        bool get_restrict() { return tq.is_restrict; }
     149        bool get_lvalue() { return tq.is_lvalue; }
     150        bool get_mutex() { return tq.is_mutex; }
     151        bool get_atomic() { return tq.is_atomic; }
    156152        void set_const( bool newValue ) { tq.is_const = newValue; }
    157153        void set_volatile( bool newValue ) { tq.is_volatile = newValue; }
    158154        void set_restrict( bool newValue ) { tq.is_restrict = newValue; }
     155        void set_lvalue( bool newValue ) { tq.is_lvalue = newValue; }
    159156        void set_mutex( bool newValue ) { tq.is_mutex = newValue; }
    160157        void set_atomic( bool newValue ) { tq.is_atomic = newValue; }
     
    175172        /// return type without outer references
    176173        Type * stripReferences();
    177         const Type * stripReferences() const;
    178174
    179175        /// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types)
     
    182178        virtual bool isComplete() const { return true; }
    183179
    184         virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
     180        virtual AggregateDecl * getAggr() { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
    185181
    186182        virtual TypeSubstitution genericSubstitution() const;
     
    188184        virtual Type *clone() const = 0;
    189185        virtual void accept( Visitor & v ) = 0;
    190         virtual void accept( Visitor & v ) const = 0;
    191186        virtual Type *acceptMutator( Mutator & m ) = 0;
    192187        virtual void print( std::ostream & os, Indenter indent = {} ) const;
     
    206201        virtual VoidType *clone() const override { return new VoidType( *this ); }
    207202        virtual void accept( Visitor & v ) override { v.visit( this ); }
    208         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    209203        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    210204        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    213207class BasicType : public Type {
    214208  public:
    215         // GENERATED START, DO NOT EDIT
    216         // GENERATED BY BasicTypes-gen.cc
    217209        enum Kind {
    218210                Bool,
     
    228220                LongLongSignedInt,
    229221                LongLongUnsignedInt,
     222                Float,
     223                Double,
     224                LongDouble,
     225                FloatComplex,
     226                DoubleComplex,
     227                LongDoubleComplex,
     228                FloatImaginary,
     229                DoubleImaginary,
     230                LongDoubleImaginary,
    230231                SignedInt128,
    231232                UnsignedInt128,
    232                 uFloat16,
    233                 uFloat16Complex,
    234                 uFloat32,
    235                 uFloat32Complex,
    236                 Float,
    237                 FloatComplex,
    238                 uFloat32x,
    239                 uFloat32xComplex,
    240                 uFloat64,
    241                 uFloat64Complex,
    242                 Double,
    243                 DoubleComplex,
    244                 uFloat64x,
    245                 uFloat64xComplex,
    246                 uuFloat80,
    247                 uFloat128,
    248                 uFloat128Complex,
    249                 uuFloat128,
    250                 LongDouble,
    251                 LongDoubleComplex,
    252                 uFloat128x,
    253                 uFloat128xComplex,
     233                Float80,
     234                Float128,
    254235                NUMBER_OF_BASIC_TYPES
    255236        } kind;
    256         // GENERATED END
    257237
    258238        static const char *typeNames[];                                         // string names for basic types, MUST MATCH with Kind
     
    260240        BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    261241
    262         Kind get_kind() const { return kind; }
     242        Kind get_kind() { return kind; }
    263243        void set_kind( Kind newValue ) { kind = newValue; }
    264244
    265245        virtual BasicType *clone() const override { return new BasicType( *this ); }
    266246        virtual void accept( Visitor & v ) override { v.visit( this ); }
    267         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    268247        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    269248        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    301280        virtual PointerType *clone() const override { return new PointerType( *this ); }
    302281        virtual void accept( Visitor & v ) override { v.visit( this ); }
    303         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    304282        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    305283        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    333311        virtual ArrayType *clone() const override { return new ArrayType( *this ); }
    334312        virtual void accept( Visitor & v ) override { v.visit( this ); }
    335         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    336         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    337         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    338 };
    339 
    340 class QualifiedType : public Type {
    341 public:
    342         Type * parent;
    343         Type * child;
    344 
    345         QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child );
    346         QualifiedType( const QualifiedType & tq );
    347         virtual ~QualifiedType();
    348 
    349         virtual QualifiedType *clone() const override { return new QualifiedType( *this ); }
    350         virtual void accept( Visitor & v ) override { v.visit( this ); }
    351         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    352313        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    353314        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    376337        virtual ReferenceType *clone() const override { return new ReferenceType( *this ); }
    377338        virtual void accept( Visitor & v ) override { v.visit( this ); }
    378         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    379339        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    380340        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    406366        virtual FunctionType *clone() const override { return new FunctionType( *this ); }
    407367        virtual void accept( Visitor & v ) override { v.visit( this ); }
    408         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    409368        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    410369        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    457416        virtual bool isComplete() const override;
    458417
    459         virtual AggregateDecl * getAggr() const override;
     418        virtual AggregateDecl * getAggr() override;
    460419
    461420        virtual TypeSubstitution genericSubstitution() const override;
     
    467426        virtual StructInstType *clone() const override { return new StructInstType( *this ); }
    468427        virtual void accept( Visitor & v ) override { v.visit( this ); }
    469         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    470428        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    471429
     
    495453        virtual bool isComplete() const override;
    496454
    497         virtual AggregateDecl * getAggr() const override;
     455        virtual AggregateDecl * getAggr() override;
    498456
    499457        virtual TypeSubstitution genericSubstitution() const override;
     
    505463        virtual UnionInstType *clone() const override { return new UnionInstType( *this ); }
    506464        virtual void accept( Visitor & v ) override { v.visit( this ); }
    507         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    508465        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    509466
     
    529486        virtual bool isComplete() const override;
    530487
    531         virtual AggregateDecl * getAggr() const override;
    532 
    533488        virtual EnumInstType *clone() const override { return new EnumInstType( *this ); }
    534489        virtual void accept( Visitor & v ) override { v.visit( this ); }
    535         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    536490        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    537491
     
    557511        virtual TraitInstType *clone() const override { return new TraitInstType( *this ); }
    558512        virtual void accept( Visitor & v ) override { v.visit( this ); }
    559         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    560513        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    561514  private:
     
    585538        virtual TypeInstType *clone() const override { return new TypeInstType( *this ); }
    586539        virtual void accept( Visitor & v ) override { v.visit( this ); }
    587         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    588540        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    589541        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    623575        virtual TupleType *clone() const override { return new TupleType( *this ); }
    624576        virtual void accept( Visitor & v ) override { v.visit( this ); }
    625         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    626577        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    627578        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    630581class TypeofType : public Type {
    631582  public:
    632         Expression *expr;    ///< expression to take the type of
    633         bool is_basetypeof;  ///< true iff is basetypeof type
    634 
    635         TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    636         TypeofType( const Type::Qualifiers & tq, Expression *expr, bool is_basetypeof,
    637                 const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     583        Expression *expr;
     584
     585        TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    638586        TypeofType( const TypeofType& );
    639587        virtual ~TypeofType();
     
    646594        virtual TypeofType *clone() const override { return new TypeofType( *this ); }
    647595        virtual void accept( Visitor & v ) override { v.visit( this ); }
    648         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    649596        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    650597        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    676623        virtual AttrType *clone() const override { return new AttrType( *this ); }
    677624        virtual void accept( Visitor & v ) override { v.visit( this ); }
    678         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    679625        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    680626        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    691637        virtual VarArgsType *clone() const override { return new VarArgsType( *this ); }
    692638        virtual void accept( Visitor & v ) override { v.visit( this ); }
    693         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    694639        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    695640        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    704649        virtual ZeroType *clone() const override { return new ZeroType( *this ); }
    705650        virtual void accept( Visitor & v ) override { v.visit( this ); }
    706         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    707651        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    708652        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    717661        virtual OneType *clone() const override { return new OneType( *this ); }
    718662        virtual void accept( Visitor & v ) override { v.visit( this ); }
    719         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    720         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    721         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    722 };
    723 
    724 class GlobalScopeType : public Type {
    725   public:
    726         GlobalScopeType();
    727 
    728         virtual GlobalScopeType *clone() const override { return new GlobalScopeType( *this ); }
    729         virtual void accept( Visitor & v ) override { v.visit( this ); }
    730         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    731663        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    732664        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
  • src/SynTree/TypeSubstitution.cc

    rb067d9b r7951100  
    6464}
    6565
    66 void TypeSubstitution::addVar( std::string formalExpr, Expression *actualExpr ) {
    67         varEnv[ formalExpr ] = actualExpr;
    68 }
    69 
    7066void TypeSubstitution::remove( std::string formalType ) {
    7167        TypeEnvType::iterator i = typeEnv.find( formalType );
     
    112108namespace {
    113109        struct EnvTrimmer {
    114                 const TypeSubstitution * env;
    115                 TypeSubstitution * newEnv;
    116                 EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
     110                TypeSubstitution * env, * newEnv;
     111                EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
    117112                void previsit( TypeDecl * tyDecl ) {
    118113                        // transfer known bindings for seen type variables
     
    125120
    126121/// reduce environment to just the parts that are referenced in a given expression
    127 TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, const TypeSubstitution * env ) {
     122TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, TypeSubstitution * env ) {
    128123        if ( env ) {
    129124                TypeSubstitution * newEnv = new TypeSubstitution();
  • src/SynTree/TypeSubstitution.h

    rb067d9b r7951100  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Apr 30 22:52:47 2019
    13 // Update Count     : 9
     12// Last Modified On : Sat Jul 22 09:52:24 2017
     13// Update Count     : 3
    1414//
    1515
     
    1919#include <iosfwd>                  // for ostream
    2020#include <list>                    // for list<>::iterator, _List_iterator
    21 #include <unordered_map>
    22 #include <unordered_set>
     21#include <map>                     // for _Rb_tree_iterator, map, map<>::val...
     22#include <set>                     // for set
    2323#include <string>                  // for string, operator!=
    2424#include <utility>                 // for pair
     
    3939        TypeSubstitution &operator=( const TypeSubstitution &other );
    4040
    41         template< typename SynTreeClass > int apply( SynTreeClass *&input ) const;
    42         template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const;
     41        template< typename SynTreeClass > int apply( SynTreeClass *&input );
     42        template< typename SynTreeClass > int applyFree( SynTreeClass *&input );
    4343
    4444        void add( std::string formalType, Type *actualType );
     
    4848        bool empty() const;
    4949
    50         void addVar( std::string formalExpr, Expression *actualExpr );
    51 
    5250        template< typename FormalIterator, typename ActualIterator >
    5351        void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
     
    5856
    5957        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
    60         static TypeSubstitution * newFromExpr( Expression * expr, const TypeSubstitution * env );
     58        static TypeSubstitution * newFromExpr( Expression * expr, TypeSubstitution * env );
    6159
    6260        void normalize();
     
    8078        friend class PassVisitor;
    8179
    82         typedef std::unordered_map< std::string, Type * > TypeEnvType;
    83         typedef std::unordered_map< std::string, Expression * > VarEnvType;
     80        typedef std::map< std::string, Type* > TypeEnvType;
     81        typedef std::map< std::string, Expression* > VarEnvType;
    8482        TypeEnvType typeEnv;
    8583        VarEnvType varEnv;
     
    9189        auto begin() const -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
    9290        auto   end() const -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
    93 
    94         auto beginVar()       -> decltype( varEnv.begin() ) { return varEnv.begin(); }
    95         auto   endVar()       -> decltype( varEnv.  end() ) { return varEnv.  end(); }
    96         auto beginVar() const -> decltype( varEnv.begin() ) { return varEnv.begin(); }
    97         auto   endVar() const -> decltype( varEnv.  end() ) { return varEnv.  end(); }
    9891};
    9992
     
    10598        ActualIterator actualIt = actualBegin;
    10699        for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) {
    107                 if ( TypeDecl *formal = dynamic_cast< TypeDecl * >( *formalIt ) ) {
    108                         if ( TypeExpr *actual = dynamic_cast< TypeExpr * >( *actualIt ) ) {
     100                if ( TypeDecl *formal = dynamic_cast< TypeDecl* >( *formalIt ) ) {
     101                        if ( TypeExpr *actual = dynamic_cast< TypeExpr* >( *actualIt ) ) {
    109102                                if ( formal->get_name() != "" ) {
    110103                                        TypeEnvType::iterator i = typeEnv.find( formal->get_name() );
     
    137130// definitition must happen after PassVisitor is included so that WithGuards can be used
    138131struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
    139                 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
     132                Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    140133
    141134                Type * postmutate( TypeInstType * aggregateUseType );
     
    150143                void premutate( UnionInstType * aggregateUseType );
    151144
    152                 const TypeSubstitution & sub;
     145                TypeSubstitution & sub;
    153146                int subCount = 0;
    154147                bool freeOnly;
    155                 typedef std::unordered_set< std::string > BoundVarsType;
     148                typedef std::set< std::string > BoundVarsType;
    156149                BoundVarsType boundVars;
    157150};
    158151
    159152template< typename SynTreeClass >
    160 int TypeSubstitution::apply( SynTreeClass *&input ) const {
     153int TypeSubstitution::apply( SynTreeClass *&input ) {
    161154        assert( input );
    162155        PassVisitor<Substituter> sub( *this, false );
     
    170163
    171164template< typename SynTreeClass >
    172 int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
     165int TypeSubstitution::applyFree( SynTreeClass *&input ) {
    173166        assert( input );
    174167        PassVisitor<Substituter> sub( *this, true );
  • src/SynTree/TypeofType.cc

    rb067d9b r7951100  
    2323class Attribute;
    2424
    25 TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr,
    26         const std::list< Attribute * > & attributes )
    27 : Type( tq, attributes ), expr( expr ), is_basetypeof(false) {}
     25TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), expr( expr ) {
     26}
    2827
    29 TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr, bool is_basetypeof,
    30         const std::list< Attribute * > & attributes )
    31 : Type( tq, attributes ), expr( expr ), is_basetypeof( is_basetypeof ) {}
    32 
    33 TypeofType::TypeofType( const TypeofType &other )
    34 : Type( other ), expr( maybeClone( other.expr ) ), is_basetypeof( other.is_basetypeof ) {}
     28TypeofType::TypeofType( const TypeofType &other ) : Type( other ), expr( maybeClone( other.expr ) ) {
     29}
    3530
    3631TypeofType::~TypeofType() {
     
    4035void TypeofType::print( std::ostream &os, Indenter indent ) const {
    4136        Type::print( os, indent );
    42         if ( is_basetypeof ) { os << "base-"; }
    4337        os << "type-of expression ";
    4438        if ( expr ) {
  • src/SynTree/Visitor.h

    rb067d9b r7951100  
    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 : Thu Jul 25 22:21:49 2019
    13 // Update Count     : 14
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jul 24 16:28:00 2017
     13// Update Count     : 13
    1414//
    1515
     
    2727        // of the given syntax node, but performs no other action.
    2828
    29         virtual void visit( ObjectDecl * node ) { visit( const_cast<const ObjectDecl *>(node) ); }
    30         virtual void visit( const ObjectDecl * objectDecl ) = 0;
    31         virtual void visit( FunctionDecl * node ) { visit( const_cast<const FunctionDecl *>(node) ); }
    32         virtual void visit( const FunctionDecl * functionDecl ) = 0;
    33         virtual void visit( StructDecl * node ) { visit( const_cast<const StructDecl *>(node) ); }
    34         virtual void visit( const StructDecl * aggregateDecl ) = 0;
    35         virtual void visit( UnionDecl * node ) { visit( const_cast<const UnionDecl *>(node) ); }
    36         virtual void visit( const UnionDecl * aggregateDecl ) = 0;
    37         virtual void visit( EnumDecl * node ) { visit( const_cast<const EnumDecl *>(node) ); }
    38         virtual void visit( const EnumDecl * aggregateDecl ) = 0;
    39         virtual void visit( TraitDecl * node ) { visit( const_cast<const TraitDecl *>(node) ); }
    40         virtual void visit( const TraitDecl * aggregateDecl ) = 0;
    41         virtual void visit( TypeDecl * node ) { visit( const_cast<const TypeDecl *>(node) ); }
    42         virtual void visit( const TypeDecl * typeDecl ) = 0;
    43         virtual void visit( TypedefDecl * node ) { visit( const_cast<const TypedefDecl *>(node) ); }
    44         virtual void visit( const TypedefDecl * typeDecl ) = 0;
    45         virtual void visit( AsmDecl * node ) { visit( const_cast<const AsmDecl *>(node) ); }
    46         virtual void visit( const AsmDecl * asmDecl ) = 0;
    47         virtual void visit( StaticAssertDecl * node ) { visit( const_cast<const StaticAssertDecl *>(node) ); }
    48         virtual void visit( const StaticAssertDecl * assertDecl ) = 0;
     29        virtual void visit( ObjectDecl * objectDecl ) = 0;
     30        virtual void visit( FunctionDecl * functionDecl ) = 0;
     31        virtual void visit( StructDecl * aggregateDecl ) = 0;
     32        virtual void visit( UnionDecl * aggregateDecl ) = 0;
     33        virtual void visit( EnumDecl * aggregateDecl ) = 0;
     34        virtual void visit( TraitDecl * aggregateDecl ) = 0;
     35        virtual void visit( TypeDecl * typeDecl ) = 0;
     36        virtual void visit( TypedefDecl * typeDecl ) = 0;
     37        virtual void visit( AsmDecl * asmDecl ) = 0;
     38        virtual void visit( StaticAssertDecl * assertDecl ) = 0;
    4939
    50         virtual void visit( CompoundStmt * node ) { visit( const_cast<const CompoundStmt *>(node) ); }
    51         virtual void visit( const CompoundStmt * compoundStmt ) = 0;
    52         virtual void visit( ExprStmt * node ) { visit( const_cast<const ExprStmt *>(node) ); }
    53         virtual void visit( const ExprStmt * exprStmt ) = 0;
    54         virtual void visit( AsmStmt * node ) { visit( const_cast<const AsmStmt *>(node) ); }
    55         virtual void visit( const AsmStmt * asmStmt ) = 0;
    56         virtual void visit( DirectiveStmt * node ) { visit( const_cast<const DirectiveStmt *>(node) ); }
    57         virtual void visit( const DirectiveStmt * directiveStmt ) = 0;
    58         virtual void visit( IfStmt * node ) { visit( const_cast<const IfStmt *>(node) ); }
    59         virtual void visit( const IfStmt * ifStmt ) = 0;
    60         virtual void visit( WhileStmt * node ) { visit( const_cast<const WhileStmt *>(node) ); }
    61         virtual void visit( const WhileStmt * whileStmt ) = 0;
    62         virtual void visit( ForStmt * node ) { visit( const_cast<const ForStmt *>(node) ); }
    63         virtual void visit( const ForStmt * forStmt ) = 0;
    64         virtual void visit( SwitchStmt * node ) { visit( const_cast<const SwitchStmt *>(node) ); }
    65         virtual void visit( const SwitchStmt * switchStmt ) = 0;
    66         virtual void visit( CaseStmt * node ) { visit( const_cast<const CaseStmt *>(node) ); }
    67         virtual void visit( const CaseStmt * caseStmt ) = 0;
    68         virtual void visit( BranchStmt * node ) { visit( const_cast<const BranchStmt *>(node) ); }
    69         virtual void visit( const BranchStmt * branchStmt ) = 0;
    70         virtual void visit( ReturnStmt * node ) { visit( const_cast<const ReturnStmt *>(node) ); }
    71         virtual void visit( const ReturnStmt * returnStmt ) = 0;
    72         virtual void visit( ThrowStmt * node ) { visit( const_cast<const ThrowStmt *>(node) ); }
    73         virtual void visit( const ThrowStmt * throwStmt ) = 0;
    74         virtual void visit( TryStmt * node ) { visit( const_cast<const TryStmt *>(node) ); }
    75         virtual void visit( const TryStmt * tryStmt ) = 0;
    76         virtual void visit( CatchStmt * node ) { visit( const_cast<const CatchStmt *>(node) ); }
    77         virtual void visit( const CatchStmt * catchStmt ) = 0;
    78         virtual void visit( FinallyStmt * node ) { visit( const_cast<const FinallyStmt *>(node) ); }
    79         virtual void visit( const FinallyStmt * finallyStmt ) = 0;
    80         virtual void visit( WaitForStmt * node ) { visit( const_cast<const WaitForStmt *>(node) ); }
    81         virtual void visit( const WaitForStmt * waitforStmt ) = 0;
    82         virtual void visit( WithStmt * node ) { visit( const_cast<const WithStmt *>(node) ); }
    83         virtual void visit( const WithStmt * withStmt ) = 0;
    84         virtual void visit( NullStmt * node ) { visit( const_cast<const NullStmt *>(node) ); }
    85         virtual void visit( const NullStmt * nullStmt ) = 0;
    86         virtual void visit( DeclStmt * node ) { visit( const_cast<const DeclStmt *>(node) ); }
    87         virtual void visit( const DeclStmt * declStmt ) = 0;
    88         virtual void visit( ImplicitCtorDtorStmt * node ) { visit( const_cast<const ImplicitCtorDtorStmt *>(node) ); }
    89         virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
     40        virtual void visit( CompoundStmt * compoundStmt ) = 0;
     41        virtual void visit( ExprStmt * exprStmt ) = 0;
     42        virtual void visit( AsmStmt * asmStmt ) = 0;
     43        virtual void visit( DirectiveStmt * directiveStmt ) = 0;
     44        virtual void visit( IfStmt * ifStmt ) = 0;
     45        virtual void visit( WhileStmt * whileStmt ) = 0;
     46        virtual void visit( ForStmt * forStmt ) = 0;
     47        virtual void visit( SwitchStmt * switchStmt ) = 0;
     48        virtual void visit( CaseStmt * caseStmt ) = 0;
     49        virtual void visit( BranchStmt * branchStmt ) = 0;
     50        virtual void visit( ReturnStmt * returnStmt ) = 0;
     51        virtual void visit( ThrowStmt * throwStmt ) = 0;
     52        virtual void visit( TryStmt * tryStmt ) = 0;
     53        virtual void visit( CatchStmt * catchStmt ) = 0;
     54        virtual void visit( FinallyStmt * finallyStmt ) = 0;
     55        virtual void visit( WaitForStmt * waitforStmt ) = 0;
     56        virtual void visit( WithStmt * withStmt ) = 0;
     57        virtual void visit( NullStmt * nullStmt ) = 0;
     58        virtual void visit( DeclStmt * declStmt ) = 0;
     59        virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
    9060
    91         virtual void visit( ApplicationExpr * node ) { visit( const_cast<const ApplicationExpr *>(node) ); }
    92         virtual void visit( const ApplicationExpr * applicationExpr ) = 0;
    93         virtual void visit( UntypedExpr * node ) { visit( const_cast<const UntypedExpr *>(node) ); }
    94         virtual void visit( const UntypedExpr * untypedExpr ) = 0;
    95         virtual void visit( NameExpr * node ) { visit( const_cast<const NameExpr *>(node) ); }
    96         virtual void visit( const NameExpr * nameExpr ) = 0;
    97         virtual void visit( CastExpr * node ) { visit( const_cast<const CastExpr *>(node) ); }
    98         virtual void visit( const CastExpr * castExpr ) = 0;
    99         virtual void visit( KeywordCastExpr * node ) { visit( const_cast<const KeywordCastExpr *>(node) ); }
    100         virtual void visit( const KeywordCastExpr * castExpr ) = 0;
    101         virtual void visit( VirtualCastExpr * node ) { visit( const_cast<const VirtualCastExpr *>(node) ); }
    102         virtual void visit( const VirtualCastExpr * castExpr ) = 0;
    103         virtual void visit( AddressExpr * node ) { visit( const_cast<const AddressExpr *>(node) ); }
    104         virtual void visit( const AddressExpr * addressExpr ) = 0;
    105         virtual void visit( LabelAddressExpr * node ) { visit( const_cast<const LabelAddressExpr *>(node) ); }
    106         virtual void visit( const LabelAddressExpr * labAddressExpr ) = 0;
    107         virtual void visit( UntypedMemberExpr * node ) { visit( const_cast<const UntypedMemberExpr *>(node) ); }
    108         virtual void visit( const UntypedMemberExpr * memberExpr ) = 0;
    109         virtual void visit( MemberExpr * node ) { visit( const_cast<const MemberExpr *>(node) ); }
    110         virtual void visit( const MemberExpr * memberExpr ) = 0;
    111         virtual void visit( VariableExpr * node ) { visit( const_cast<const VariableExpr *>(node) ); }
    112         virtual void visit( const VariableExpr * variableExpr ) = 0;
    113         virtual void visit( ConstantExpr * node ) { visit( const_cast<const ConstantExpr *>(node) ); }
    114         virtual void visit( const ConstantExpr * constantExpr ) = 0;
    115         virtual void visit( SizeofExpr * node ) { visit( const_cast<const SizeofExpr *>(node) ); }
    116         virtual void visit( const SizeofExpr * sizeofExpr ) = 0;
    117         virtual void visit( AlignofExpr * node ) { visit( const_cast<const AlignofExpr *>(node) ); }
    118         virtual void visit( const AlignofExpr * alignofExpr ) = 0;
    119         virtual void visit( UntypedOffsetofExpr * node ) { visit( const_cast<const UntypedOffsetofExpr *>(node) ); }
    120         virtual void visit( const UntypedOffsetofExpr * offsetofExpr ) = 0;
    121         virtual void visit( OffsetofExpr * node ) { visit( const_cast<const OffsetofExpr *>(node) ); }
    122         virtual void visit( const OffsetofExpr * offsetofExpr ) = 0;
    123         virtual void visit( OffsetPackExpr * node ) { visit( const_cast<const OffsetPackExpr *>(node) ); }
    124         virtual void visit( const OffsetPackExpr * offsetPackExpr ) = 0;
    125         virtual void visit( LogicalExpr * node ) { visit( const_cast<const LogicalExpr *>(node) ); }
    126         virtual void visit( const LogicalExpr * logicalExpr ) = 0;
    127         virtual void visit( ConditionalExpr * node ) { visit( const_cast<const ConditionalExpr *>(node) ); }
    128         virtual void visit( const ConditionalExpr * conditionalExpr ) = 0;
    129         virtual void visit( CommaExpr * node ) { visit( const_cast<const CommaExpr *>(node) ); }
    130         virtual void visit( const CommaExpr * commaExpr ) = 0;
    131         virtual void visit( TypeExpr * node ) { visit( const_cast<const TypeExpr *>(node) ); }
    132         virtual void visit( const TypeExpr * typeExpr ) = 0;
    133         virtual void visit( AsmExpr * node ) { visit( const_cast<const AsmExpr *>(node) ); }
    134         virtual void visit( const AsmExpr * asmExpr ) = 0;
    135         virtual void visit( ImplicitCopyCtorExpr * node ) { visit( const_cast<const ImplicitCopyCtorExpr *>(node) ); }
    136         virtual void visit( const ImplicitCopyCtorExpr * impCpCtorExpr ) = 0;
    137         virtual void visit( ConstructorExpr * node ) { visit( const_cast<const ConstructorExpr *>(node) ); }
    138         virtual void visit( const ConstructorExpr *  ctorExpr ) = 0;
    139         virtual void visit( CompoundLiteralExpr * node ) { visit( const_cast<const CompoundLiteralExpr *>(node) ); }
    140         virtual void visit( const CompoundLiteralExpr * compLitExpr ) = 0;
    141         virtual void visit( RangeExpr * node ) { visit( const_cast<const RangeExpr *>(node) ); }
    142         virtual void visit( const RangeExpr * rangeExpr ) = 0;
    143         virtual void visit( UntypedTupleExpr * node ) { visit( const_cast<const UntypedTupleExpr *>(node) ); }
    144         virtual void visit( const UntypedTupleExpr * tupleExpr ) = 0;
    145         virtual void visit( TupleExpr * node ) { visit( const_cast<const TupleExpr *>(node) ); }
    146         virtual void visit( const TupleExpr * tupleExpr ) = 0;
    147         virtual void visit( TupleIndexExpr * node ) { visit( const_cast<const TupleIndexExpr *>(node) ); }
    148         virtual void visit( const TupleIndexExpr * tupleExpr ) = 0;
    149         virtual void visit( TupleAssignExpr * node ) { visit( const_cast<const TupleAssignExpr *>(node) ); }
    150         virtual void visit( const TupleAssignExpr * assignExpr ) = 0;
    151         virtual void visit( StmtExpr * node ) { visit( const_cast<const StmtExpr *>(node) ); }
    152         virtual void visit( const StmtExpr *  stmtExpr ) = 0;
    153         virtual void visit( UniqueExpr * node ) { visit( const_cast<const UniqueExpr *>(node) ); }
    154         virtual void visit( const UniqueExpr *  uniqueExpr ) = 0;
    155         virtual void visit( UntypedInitExpr * node ) { visit( const_cast<const UntypedInitExpr *>(node) ); }
    156         virtual void visit( const UntypedInitExpr *  initExpr ) = 0;
    157         virtual void visit( InitExpr * node ) { visit( const_cast<const InitExpr *>(node) ); }
    158         virtual void visit( const InitExpr *  initExpr ) = 0;
    159         virtual void visit( DeletedExpr * node ) { visit( const_cast<const DeletedExpr *>(node) ); }
    160         virtual void visit( const DeletedExpr * delExpr ) = 0;
    161         virtual void visit( DefaultArgExpr * node ) { visit( const_cast<const DefaultArgExpr *>(node) ); }
    162         virtual void visit( const DefaultArgExpr * argExpr ) = 0;
    163         virtual void visit( GenericExpr * node ) { visit( const_cast<const GenericExpr *>(node) ); }
    164         virtual void visit( const GenericExpr * genExpr ) = 0;
     61        virtual void visit( ApplicationExpr * applicationExpr ) = 0;
     62        virtual void visit( UntypedExpr * untypedExpr ) = 0;
     63        virtual void visit( NameExpr * nameExpr ) = 0;
     64        virtual void visit( CastExpr * castExpr ) = 0;
     65        virtual void visit( KeywordCastExpr * castExpr ) = 0;
     66        virtual void visit( VirtualCastExpr * castExpr ) = 0;
     67        virtual void visit( AddressExpr * addressExpr ) = 0;
     68        virtual void visit( LabelAddressExpr * labAddressExpr ) = 0;
     69        virtual void visit( UntypedMemberExpr * memberExpr ) = 0;
     70        virtual void visit( MemberExpr * memberExpr ) = 0;
     71        virtual void visit( VariableExpr * variableExpr ) = 0;
     72        virtual void visit( ConstantExpr * constantExpr ) = 0;
     73        virtual void visit( SizeofExpr * sizeofExpr ) = 0;
     74        virtual void visit( AlignofExpr * alignofExpr ) = 0;
     75        virtual void visit( UntypedOffsetofExpr * offsetofExpr ) = 0;
     76        virtual void visit( OffsetofExpr * offsetofExpr ) = 0;
     77        virtual void visit( OffsetPackExpr * offsetPackExpr ) = 0;
     78        virtual void visit( AttrExpr * attrExpr ) = 0;
     79        virtual void visit( LogicalExpr * logicalExpr ) = 0;
     80        virtual void visit( ConditionalExpr * conditionalExpr ) = 0;
     81        virtual void visit( CommaExpr * commaExpr ) = 0;
     82        virtual void visit( TypeExpr * typeExpr ) = 0;
     83        virtual void visit( AsmExpr * asmExpr ) = 0;
     84        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) = 0;
     85        virtual void visit( ConstructorExpr *  ctorExpr ) = 0;
     86        virtual void visit( CompoundLiteralExpr * compLitExpr ) = 0;
     87        virtual void visit( RangeExpr * rangeExpr ) = 0;
     88        virtual void visit( UntypedTupleExpr * tupleExpr ) = 0;
     89        virtual void visit( TupleExpr * tupleExpr ) = 0;
     90        virtual void visit( TupleIndexExpr * tupleExpr ) = 0;
     91        virtual void visit( TupleAssignExpr * assignExpr ) = 0;
     92        virtual void visit( StmtExpr *  stmtExpr ) = 0;
     93        virtual void visit( UniqueExpr *  uniqueExpr ) = 0;
     94        virtual void visit( UntypedInitExpr *  initExpr ) = 0;
     95        virtual void visit( InitExpr *  initExpr ) = 0;
     96        virtual void visit( DeletedExpr * delExpr ) = 0;
     97        virtual void visit( GenericExpr * genExpr ) = 0;
    16598
    166         virtual void visit( VoidType * node ) { visit( const_cast<const VoidType *>(node) ); }
    167         virtual void visit( const VoidType * basicType ) = 0;
    168         virtual void visit( BasicType * node ) { visit( const_cast<const BasicType *>(node) ); }
    169         virtual void visit( const BasicType * basicType ) = 0;
    170         virtual void visit( PointerType * node ) { visit( const_cast<const PointerType *>(node) ); }
    171         virtual void visit( const PointerType * pointerType ) = 0;
    172         virtual void visit( ArrayType * node ) { visit( const_cast<const ArrayType *>(node) ); }
    173         virtual void visit( const ArrayType * arrayType ) = 0;
    174         virtual void visit( ReferenceType * node ) { visit( const_cast<const ReferenceType *>(node) ); }
    175         virtual void visit( const ReferenceType * refType ) = 0;
    176         virtual void visit( QualifiedType * node ) { visit( const_cast<const QualifiedType *>(node) ); }
    177         virtual void visit( const QualifiedType * qualType ) = 0;
    178         virtual void visit( FunctionType * node ) { visit( const_cast<const FunctionType *>(node) ); }
    179         virtual void visit( const FunctionType * functionType ) = 0;
    180         virtual void visit( StructInstType * node ) { visit( const_cast<const StructInstType *>(node) ); }
    181         virtual void visit( const StructInstType * aggregateUseType ) = 0;
    182         virtual void visit( UnionInstType * node ) { visit( const_cast<const UnionInstType *>(node) ); }
    183         virtual void visit( const UnionInstType * aggregateUseType ) = 0;
    184         virtual void visit( EnumInstType * node ) { visit( const_cast<const EnumInstType *>(node) ); }
    185         virtual void visit( const EnumInstType * aggregateUseType ) = 0;
    186         virtual void visit( TraitInstType * node ) { visit( const_cast<const TraitInstType *>(node) ); }
    187         virtual void visit( const TraitInstType * aggregateUseType ) = 0;
    188         virtual void visit( TypeInstType * node ) { visit( const_cast<const TypeInstType *>(node) ); }
    189         virtual void visit( const TypeInstType * aggregateUseType ) = 0;
    190         virtual void visit( TupleType * node ) { visit( const_cast<const TupleType *>(node) ); }
    191         virtual void visit( const TupleType * tupleType ) = 0;
    192         virtual void visit( TypeofType * node ) { visit( const_cast<const TypeofType *>(node) ); }
    193         virtual void visit( const TypeofType * typeofType ) = 0;
    194         virtual void visit( AttrType * node ) { visit( const_cast<const AttrType *>(node) ); }
    195         virtual void visit( const AttrType * attrType ) = 0;
    196         virtual void visit( VarArgsType * node ) { visit( const_cast<const VarArgsType *>(node) ); }
    197         virtual void visit( const VarArgsType * varArgsType ) = 0;
    198         virtual void visit( ZeroType * node ) { visit( const_cast<const ZeroType *>(node) ); }
    199         virtual void visit( const ZeroType * zeroType ) = 0;
    200         virtual void visit( OneType * node ) { visit( const_cast<const OneType *>(node) ); }
    201         virtual void visit( const OneType * oneType ) = 0;
    202         virtual void visit( GlobalScopeType * node ) { visit( const_cast<const GlobalScopeType *>(node) ); }
    203         virtual void visit( const GlobalScopeType * globalType ) = 0;
     99        virtual void visit( VoidType * basicType ) = 0;
     100        virtual void visit( BasicType * basicType ) = 0;
     101        virtual void visit( PointerType * pointerType ) = 0;
     102        virtual void visit( ArrayType * arrayType ) = 0;
     103        virtual void visit( ReferenceType * refType ) = 0;
     104        virtual void visit( FunctionType * functionType ) = 0;
     105        virtual void visit( StructInstType * aggregateUseType ) = 0;
     106        virtual void visit( UnionInstType * aggregateUseType ) = 0;
     107        virtual void visit( EnumInstType * aggregateUseType ) = 0;
     108        virtual void visit( TraitInstType * aggregateUseType ) = 0;
     109        virtual void visit( TypeInstType * aggregateUseType ) = 0;
     110        virtual void visit( TupleType * tupleType ) = 0;
     111        virtual void visit( TypeofType * typeofType ) = 0;
     112        virtual void visit( AttrType * attrType ) = 0;
     113        virtual void visit( VarArgsType * varArgsType ) = 0;
     114        virtual void visit( ZeroType * zeroType ) = 0;
     115        virtual void visit( OneType * oneType ) = 0;
    204116
    205         virtual void visit( Designation * node ) { visit( const_cast<const Designation *>(node) ); }
    206         virtual void visit( const Designation * designation ) = 0;
    207         virtual void visit( SingleInit * node ) { visit( const_cast<const SingleInit *>(node) ); }
    208         virtual void visit( const SingleInit * singleInit ) = 0;
    209         virtual void visit( ListInit * node ) { visit( const_cast<const ListInit *>(node) ); }
    210         virtual void visit( const ListInit * listInit ) = 0;
    211         virtual void visit( ConstructorInit * node ) { visit( const_cast<const ConstructorInit *>(node) ); }
    212         virtual void visit( const ConstructorInit * ctorInit ) = 0;
     117        virtual void visit( Designation * designation ) = 0;
     118        virtual void visit( SingleInit * singleInit ) = 0;
     119        virtual void visit( ListInit * listInit ) = 0;
     120        virtual void visit( ConstructorInit * ctorInit ) = 0;
    213121
    214         virtual void visit( Constant * node ) { visit( const_cast<const Constant *>(node) ); }
    215         virtual void visit( const Constant * constant ) = 0;
     122        virtual void visit( Subrange * subrange ) = 0;
    216123
    217         virtual void visit( Attribute * node ) { visit( const_cast<const Attribute *>(node) ); }
    218         virtual void visit( const Attribute * attribute ) = 0;
     124        virtual void visit( Constant * constant ) = 0;
     125
     126        virtual void visit( Attribute * attribute ) = 0;
    219127};
    220128
    221129template< typename TreeType, typename VisitorType >
    222 inline void maybeAccept( TreeType * tree, VisitorType & visitor ) {
    223         if ( tree ) {
    224                 tree->accept( visitor );
    225         }
    226 }
    227 
    228 template< typename TreeType, typename VisitorType >
    229 inline void maybeAccept( const TreeType * tree, VisitorType & visitor ) {
     130inline void maybeAccept( TreeType *tree, VisitorType &visitor ) {
    230131        if ( tree ) {
    231132                tree->accept( visitor );
     
    234135
    235136template< typename Container, typename VisitorType >
    236 inline void acceptAll( Container & container, VisitorType & visitor ) {
     137inline void acceptAll( Container &container, VisitorType &visitor ) {
    237138        SemanticErrorException errors;
    238         for ( auto * i : container ) {
     139        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    239140                try {
    240                         if ( i ) {
    241                                 i->accept( visitor );
    242                         }
    243                 } catch( SemanticErrorException & e ) {
    244                         errors.append( e );
    245                 }
    246         }
    247         if ( ! errors.isEmpty() ) {
    248                 throw errors;
    249         }
    250 }
    251 
    252 template< typename Container, typename VisitorType >
    253 inline void acceptAll( const Container & container, VisitorType & visitor ) {
    254         SemanticErrorException errors;
    255         for ( const auto * i : container ) {
    256                 try {
    257                         if ( i ) {
    258                                 i->accept( visitor );
     141                        if ( *i ) {
     142                                (*i)->accept( visitor );
    259143                        }
    260144                } catch( SemanticErrorException &e ) {
  • src/SynTree/module.mk

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 SRC_SYNTREE = \
    18       SynTree/Type.cc \
    19       SynTree/VoidType.cc \
    20       SynTree/BasicType.cc \
    21       SynTree/PointerType.cc \
    22       SynTree/ArrayType.cc \
    23       SynTree/ReferenceType.cc \
    24       SynTree/FunctionType.cc \
    25       SynTree/ReferenceToType.cc \
    26       SynTree/TupleType.cc \
    27       SynTree/TypeofType.cc \
    28       SynTree/AttrType.cc \
    29       SynTree/VarArgsType.cc \
    30       SynTree/ZeroOneType.cc \
    31       SynTree/Constant.cc \
    32       SynTree/Expression.cc \
    33       SynTree/TupleExpr.cc \
    34       SynTree/CommaExpr.cc \
    35       SynTree/TypeExpr.cc \
    36       SynTree/ApplicationExpr.cc \
    37       SynTree/AddressExpr.cc \
    38       SynTree/Statement.cc \
    39       SynTree/CompoundStmt.cc \
    40       SynTree/DeclStmt.cc \
    41       SynTree/Declaration.cc \
    42       SynTree/DeclarationWithType.cc \
    43       SynTree/ObjectDecl.cc \
    44       SynTree/FunctionDecl.cc \
    45       SynTree/AggregateDecl.cc \
    46       SynTree/NamedTypeDecl.cc \
    47       SynTree/TypeDecl.cc \
    48       SynTree/Initializer.cc \
    49       SynTree/TypeSubstitution.cc \
    50       SynTree/Attribute.cc \
    51       SynTree/DeclReplacer.cc
     17SRC += SynTree/Type.cc \
     18       SynTree/VoidType.cc \
     19       SynTree/BasicType.cc \
     20       SynTree/PointerType.cc \
     21       SynTree/ArrayType.cc \
     22       SynTree/ReferenceType.cc \
     23       SynTree/FunctionType.cc \
     24       SynTree/ReferenceToType.cc \
     25       SynTree/TupleType.cc \
     26       SynTree/TypeofType.cc \
     27       SynTree/AttrType.cc \
     28       SynTree/VarArgsType.cc \
     29       SynTree/ZeroOneType.cc \
     30       SynTree/Constant.cc \
     31       SynTree/Expression.cc \
     32       SynTree/TupleExpr.cc \
     33       SynTree/CommaExpr.cc \
     34       SynTree/TypeExpr.cc \
     35       SynTree/ApplicationExpr.cc \
     36       SynTree/AddressExpr.cc \
     37       SynTree/Statement.cc \
     38       SynTree/CompoundStmt.cc \
     39       SynTree/DeclStmt.cc \
     40       SynTree/Declaration.cc \
     41       SynTree/DeclarationWithType.cc \
     42       SynTree/ObjectDecl.cc \
     43       SynTree/FunctionDecl.cc \
     44       SynTree/AggregateDecl.cc \
     45       SynTree/NamedTypeDecl.cc \
     46       SynTree/TypeDecl.cc \
     47       SynTree/Initializer.cc \
     48       SynTree/TypeSubstitution.cc \
     49       SynTree/Attribute.cc \
     50       SynTree/DeclReplacer.cc
    5251
    53 SRC += $(SRC_SYNTREE)
    54 SRCDEMANGLE += $(SRC_SYNTREE)
  • src/Tuples/Explode.cc

    rb067d9b r7951100  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 12 16:40:00 2016
    13 // Update Count     : 3
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Nov 9 13:20:24 2016
     13// Update Count     : 2
    1414//
    1515
     
    106106                return expr;
    107107        }
    108 
    109 namespace {
    110 
    111 // Remove one level of reference from a reference type.
    112 const ast::Type * getReferenceBase( const ast::Type * t ) {
    113         if ( const ast::ReferenceType * ref = dynamic_cast< const ast::ReferenceType * >( t ) ) {
    114                 return ref->base;
    115         } else {
    116                 assertf( false, "getReferenceBase for non-ref: %s", toString( t ).c_str() );
    117                 return nullptr;
    118         }
    119 }
    120 
    121 struct CastExploderCore {
    122         bool castAdded = false;
    123         bool foundUniqueExpr = false;
    124         const ast::Expr * applyCast( const ast::Expr * expr, bool first = true ) {
    125                 // On tuple push the cast down.
    126                 if ( const ast::TupleExpr * tupleExpr = dynamic_cast< const ast::TupleExpr * >( expr ) ) {
    127                         foundUniqueExpr = true;
    128                         std::vector< ast::ptr< ast::Expr > > exprs;
    129                         for ( const ast::Expr * expr : tupleExpr->exprs ) {
    130                                 exprs.emplace_back( applyCast( expr, false ) );
    131                                 //exprs.emplace_back( ast::ptr< ast::Expr >( applyCast( expr, false ) ) );
    132                         }
    133                         if ( first ) {
    134                                 castAdded = true;
    135                                 const ast::Expr * tuple = new ast::TupleExpr{
    136                                         tupleExpr->location, std::move( exprs ) };
    137                                 return new ast::CastExpr{ tuple, new ast::ReferenceType{ tuple->result } };
    138                         } else {
    139                                 return new ast::TupleExpr( tupleExpr->location, std::move( exprs ) );
    140                         }
    141                 }
    142                 if ( dynamic_cast< const ast::ReferenceType * >( expr->result.get() ) ) {
    143                         return expr;
    144                 } else {
    145                         castAdded = true;
    146                         return new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
    147                 }
    148         }
    149 
    150         const ast::Expr * postmutate( const ast::UniqueExpr * node ) {
    151                 // move cast into unique expr so that the unique expr has type T& rather than
    152                 // type T. In particular, this transformation helps with generating the
    153                 // correct code for reference-cast member tuple expressions, since the result
    154                 // should now be a tuple of references rather than a reference to a tuple.
    155                 // Still, this code is a bit awkward, and could use some improvement.
    156                 const ast::UniqueExpr * newNode = new ast::UniqueExpr( node->location,
    157                                 applyCast( node->expr ), node->id );
    158                 if ( castAdded ) {
    159                         // if a cast was added by applyCast, then unique expr now has one more layer of reference
    160                         // than it had coming into this function. To ensure types still match correctly, need to cast
    161                         //  to reference base so that outer expressions are still correct.
    162                         castAdded = false;
    163                         const ast::Type * newType = getReferenceBase( newNode->result );
    164                         return new ast::CastExpr{ newNode->location, node, newType };
    165                 }
    166                 return newNode;
    167         }
    168 
    169         const ast::Expr * postmutate( const ast::TupleIndexExpr * tupleExpr ) {
    170                 // tuple index expr needs to be rebuilt to ensure that the type of the
    171                 // field is consistent with the type of the tuple expr, since the field
    172                 // may have changed from type T to T&.
    173                 return new ast::TupleIndexExpr( tupleExpr->location, tupleExpr->tuple, tupleExpr->index );
    174         }
    175 };
    176 
    177 } // namespace
    178 
    179 const ast::Expr * distributeReference( const ast::Expr * expr ) {
    180         ast::Pass<CastExploderCore> exploder;
    181         expr = expr->accept( exploder );
    182         if ( ! exploder.pass.foundUniqueExpr ) {
    183                 expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
    184         }
    185         return expr;
    186 }
    187 
    188108} // namespace Tuples
    189109
  • src/Tuples/Explode.h

    rb067d9b r7951100  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun 17 14:36:00 2019
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:55:16 2017
     13// Update Count     : 3
    1414//
    1515
     
    1919#include <utility>                      // for forward
    2020
    21 #include "AST/Expr.hpp"
    2221#include "ResolvExpr/Alternative.h"     // for Alternative, AltList
    23 #include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
    2422#include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
    25 #include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
    2623#include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
    2724#include "SynTree/Type.h"               // for TupleType, Type
    2825#include "Tuples.h"                     // for maybeImpure
    29 
    30 namespace ast {
    31         class SymbolTable;
    32 }
    3326
    3427namespace SymTab {
     
    5144        template<typename OutputIterator>
    5245        void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
    53                         const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
    5446                        const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
    55                 *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
     47                *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };
    5648        }
    5749
    5850        /// Append alternative to an ExplodedActual
    5951        static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
    60                         const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
    61                         const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
     52                        const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    6253                ea.exprs.emplace_back( expr );
    63                 /// xxx -- merge environment, openVars, need, cost?
     54                /// xxx -- merge environment, cost?
    6455        }
    6556
     
    7768                                        // distribute reference cast over all components
    7869                                        append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
    79                                                 alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost );
     70                                                alt.env, alt.cost, alt.cvtCost );
    8071                                }
    8172                                // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
     
    111102                } else {
    112103                        // atomic (non-tuple) type - output a clone of the expression in a new alternative
    113                         append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need,
    114                                 alt.cost, alt.cvtCost );
     104                        append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost );
    115105                }
    116106        }
     
    137127                explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
    138128        }
    139 
    140 const ast::Expr * distributeReference( const ast::Expr * );
    141 
    142 /// Append candidate to an OutputIterator of Candidates.
    143 template<typename OutputIterator>
    144 void append( OutputIterator out, const ast::Expr * expr, const ast::TypeEnvironment & env,
    145                 const ast::OpenVarSet & open, const ast::AssertionList & need,
    146                 const ResolvExpr::Cost & cost, const ResolvExpr::Cost & cvtCost ) {
    147         ast::TypeEnvironment copyEnv = env;
    148         ast::OpenVarSet copyOpen = open;
    149         ast::AssertionSet set;
    150         mergeAssertionSet( set, need );
    151         *out++ = std::make_shared<ResolvExpr::Candidate>( expr, std::move( copyEnv ),
    152                 std::move( copyOpen ), std::move( set ), cost, cvtCost );
    153 }
    154 
    155 /// Append candidate to an ExplodedArg.
    156 static inline void append( ResolvExpr::ExplodedArg& ea, const ast::Expr * expr,
    157                 const ast::TypeEnvironment&, const ast::OpenVarSet&,
    158                 const ast::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    159         // I'm not sure why most of the arguments are unused. But they were in the old version.
    160         ea.exprs.emplace_back( expr );
    161 }
    162 
    163 /// Check if the expression is a cast to a reference type, return it if it is.
    164 static inline const ast::CastExpr * isReferenceCast( const ast::Expr * expr ) {
    165         if ( const ast::CastExpr * cast = dynamic_cast< const ast::CastExpr * >( expr ) ) {
    166                 if ( dynamic_cast< const ast::ReferenceType * >( cast->result.get() ) ) {
    167                         return cast;
    168                 }
    169         }
    170         return nullptr;
    171 }
    172 
    173 /// helper function (indirectely) used by explode
    174 template< typename Output >
    175 void explodeRecursive(
    176         const ast::CastExpr *, const ResolvExpr::Candidate &,
    177         const ast::SymbolTable &, Output &&
    178 ) {
    179 }
    180 
    181 /// helper function used by explode
    182 template< typename Output >
    183 void explodeUnique(
    184         const ast::ptr< ast::Expr > & expr, const ResolvExpr::Candidate & arg,
    185         const ast::SymbolTable & symtab, Output && out, bool isTupleAssign
    186 ) {
    187         // Tuple assignment can use a faster method if it is cast. Uses recursive exploding.
    188         if ( isTupleAssign ) if ( const ast::CastExpr * castExpr = isReferenceCast( expr ) ) {
    189                 ResolvExpr::CandidateList candidates;
    190                 explodeUnique( castExpr->arg, arg, symtab, back_inserter( candidates ), true );
    191                 for ( ResolvExpr::CandidateRef & cand : candidates ) {
    192                         // Distribute the reference cast over all components of the candidate.
    193                         append( std::forward<Output>(out), distributeReference( cand->expr ), cand->env,
    194                                 cand->open, cand->need, cand->cost, cand->cvtCost );
    195                 }
    196                 return;
    197         }
    198         const ast::Type * res = expr->result->stripReferences();
    199         if ( const ast::TupleType * tupleType = dynamic_cast< const ast::TupleType * >( res ) ) {
    200                 if ( const ast::ptr< ast::TupleExpr > & tupleExpr = expr.as< ast::TupleExpr >() ) {
    201                         // Open the tuple expr and continue on its components.
    202                         for ( const ast::Expr * expr : tupleExpr->exprs ) {
    203                                 explodeUnique( expr, arg, symtab, std::forward<Output>(out), isTupleAssign );
    204                         }
    205                 } else {
    206                         ast::ptr< ast::Expr > local = expr;
    207                         // Expressions which may have side effects require a single unique instance.
    208                         if ( Tuples::maybeImpureIgnoreUnique( local ) ) {
    209                                 local = new ast::UniqueExpr( local->location, local );
    210                         }
    211                         // Cast a reference away to a value-type to allow further explosion.
    212                         if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) {
    213                                 local = new ast::CastExpr{ local, tupleType };
    214                         }
    215                         // Now we have to go across the tuple via indexing.
    216                         for ( unsigned int i = 0 ; i < tupleType->size() ; ++i ) {
    217                                 ast::TupleIndexExpr * idx = new ast::TupleIndexExpr( local->location, local, i );
    218                                 explodeUnique( idx, arg, symtab, std::forward<Output>(out), isTupleAssign );
    219                                 // TODO: We need more input to figure out the exact lifetimes of these types.
    220                                 // delete idx;
    221                         }
    222                         // delete local;
    223                 }
    224         } else {
    225                 // For atomic/non-tuple types, no explosion is used.
    226                 append( std::forward<Output>(out), expr, arg.env, arg.open, arg.need, arg.cost,
    227                         arg.cvtCost );
    228         }
    229 }
    230 
    231 /// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type
    232 template< typename Output >
    233 void explode(
    234         const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,
    235         bool isTupleAssign = false
    236 ) {
    237         explodeUnique( arg.expr, arg, symtab, std::forward< Output >( out ), isTupleAssign );
    238 }
    239 
    240 /// explode list of candidates into flattened list of candidates
    241 template< typename Output >
    242 void explode(
    243         const ResolvExpr::CandidateList & cands, const ast::SymbolTable & symtab, Output && out,
    244         bool isTupleAssign = false
    245 ) {
    246         for ( const ResolvExpr::CandidateRef & cand : cands ) {
    247                 explode( *cand, symtab, std::forward< Output >( out ), isTupleAssign );
    248         }
    249 }
    250 
    251129} // namespace Tuples
    252130
  • src/Tuples/TupleAssignment.cc

    rb067d9b r7951100  
    2222#include <vector>
    2323
    24 #include "AST/Decl.hpp"
    25 #include "AST/Init.hpp"
    26 #include "AST/Pass.hpp"
    27 #include "AST/Stmt.hpp"
    28 #include "AST/TypeEnvironment.hpp"
    2924#include "CodeGen/OperatorTable.h"
    3025#include "Common/PassVisitor.h"
    3126#include "Common/UniqueName.h"             // for UniqueName
    32 #include "Common/utility.h"                // for splice, zipWith
     27#include "Common/utility.h"                // for zipWith
    3328#include "Explode.h"                       // for explode
    3429#include "InitTweak/GenInit.h"             // for genCtorInit
     
    5651
    5752namespace Tuples {
    58         class TupleAssignSpotter_old {
     53        class TupleAssignSpotter {
    5954          public:
    6055                // dispatcher for Tuple (multiple and mass) assignment operations
    61                 TupleAssignSpotter_old( ResolvExpr::AlternativeFinder & );
     56                TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
    6257                void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );
    6358
     
    6762                struct Matcher {
    6863                  public:
    69                         Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    70                                 const ResolvExpr::AltList& rhs );
     64                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
     65                                ResolvExpr::AltList& rhs );
    7166                        virtual ~Matcher() {}
    72 
    7367                        virtual void match( std::list< Expression * > &out ) = 0;
    7468                        ObjectDecl * newObject( UniqueName & namer, Expression * expr );
    75 
    76                         void combineState( const ResolvExpr::Alternative& alt ) {
    77                                 compositeEnv.simpleCombine( alt.env );
    78                                 ResolvExpr::mergeOpenVars( openVars, alt.openVars );
    79                                 cloneAll( alt.need, need );
    80                         }
    81 
    82                         void combineState( const ResolvExpr::AltList& alts ) {
    83                                 for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }
    84                         }
    85 
    8669                        ResolvExpr::AltList lhs, rhs;
    87                         TupleAssignSpotter_old &spotter;
     70                        TupleAssignSpotter &spotter;
    8871                        ResolvExpr::Cost baseCost;
    8972                        std::list< ObjectDecl * > tmpDecls;
    9073                        ResolvExpr::TypeEnvironment compositeEnv;
    91                         ResolvExpr::OpenVarSet openVars;
    92                         ResolvExpr::AssertionSet need;
    9374                };
    9475
    9576                struct MassAssignMatcher : public Matcher {
    9677                  public:
    97                         MassAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
     78                        MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
    9879                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    9980                        virtual void match( std::list< Expression * > &out );
     
    10283                struct MultipleAssignMatcher : public Matcher {
    10384                  public:
    104                         MultipleAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
     85                        MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
    10586                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    10687                        virtual void match( std::list< Expression * > &out );
     
    141122        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
    142123                                std::vector<ResolvExpr::AlternativeFinder> &args ) {
    143                 TupleAssignSpotter_old spotter( currentFinder );
     124                TupleAssignSpotter spotter( currentFinder );
    144125                spotter.spot( expr, args );
    145126        }
    146127
    147         TupleAssignSpotter_old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f )
     128        TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
    148129                : currentFinder(f) {}
    149130
    150         void TupleAssignSpotter_old::spot( UntypedExpr * expr,
     131        void TupleAssignSpotter::spot( UntypedExpr * expr,
    151132                        std::vector<ResolvExpr::AlternativeFinder> &args ) {
    152133                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
     
    229210        }
    230211
    231         void TupleAssignSpotter_old::match() {
     212        void TupleAssignSpotter::match() {
    232213                assert ( matcher != 0 );
    233214
     
    264245                }
    265246
    266                 // extract expressions from the assignment alternatives to produce a list of assignments
    267                 // that together form a single alternative
     247                // extract expressions from the assignment alternatives to produce a list of assignments that
     248                // together form a single alternative
    268249                std::list< Expression *> solved_assigns;
    269250                for ( ResolvExpr::Alternative & alt : current ) {
    270251                        solved_assigns.push_back( alt.expr->clone() );
    271                         matcher->combineState( alt );
    272                 }
    273 
     252                }
     253                // combine assignment environments into combined expression environment
     254                simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
    274255                // xxx -- was push_front
    275                 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
    276                         new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
    277                         matcher->openVars,
    278                         ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
    279                         ResolvExpr::sumCost( current ) + matcher->baseCost } );
    280         }
    281 
    282         TupleAssignSpotter_old::Matcher::Matcher( TupleAssignSpotter_old &spotter,
     256                currentFinder.get_alternatives().push_back( ResolvExpr::Alternative(
     257                        new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv,
     258                        ResolvExpr::sumCost( current ) + matcher->baseCost ) );
     259        }
     260
     261        TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter,
    283262                const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
    284263        : lhs(lhs), rhs(rhs), spotter(spotter),
    285264          baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
    286                 combineState( lhs );
    287                 combineState( rhs );
     265                simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );
     266                simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv );
    288267        }
    289268
     
    318297        };
    319298
    320         ObjectDecl * TupleAssignSpotter_old::Matcher::newObject( UniqueName & namer, Expression * expr ) {
     299        ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) {
    321300                assert( expr->result && ! expr->get_result()->isVoid() );
    322301                ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) );
     
    334313        }
    335314
    336         void TupleAssignSpotter_old::MassAssignMatcher::match( std::list< Expression * > &out ) {
     315        void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
    337316                static UniqueName lhsNamer( "__massassign_L" );
    338317                static UniqueName rhsNamer( "__massassign_R" );
     
    352331        }
    353332
    354         void TupleAssignSpotter_old::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
     333        void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
    355334                static UniqueName lhsNamer( "__multassign_L" );
    356335                static UniqueName rhsNamer( "__multassign_R" );
     
    382361                }
    383362        }
    384 
    385 namespace {
    386         /// true if `expr` is of tuple type
    387         bool isTuple( const ast::Expr * expr ) {
    388                 if ( ! expr ) return false;
    389                 assert( expr->result );
    390                 return dynamic_cast< const ast::TupleType * >( expr->result->stripReferences() );
    391         }
    392 
    393         /// true if `expr` is of tuple type or a reference to one
    394         bool refToTuple( const ast::Expr * expr ) {
    395                 assert( expr->result );
    396                 // check for function returning tuple of reference types
    397                 if ( auto castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) {
    398                         return refToTuple( castExpr->arg );
    399                 } else {
    400                         return isTuple( expr );
    401                 }
    402         }
    403 
    404         /// Dispatcher for tuple (multiple and mass) assignment operations
    405         class TupleAssignSpotter_new final {
    406                 /// Actually finds tuple assignment operations, by subclass
    407                 struct Matcher {
    408                         ResolvExpr::CandidateList lhs, rhs;
    409                         TupleAssignSpotter_new & spotter;
    410                         CodeLocation location;
    411                         ResolvExpr::Cost baseCost;
    412                         std::vector< ast::ptr< ast::ObjectDecl > > tmpDecls;
    413                         ast::TypeEnvironment env;
    414                         ast::OpenVarSet open;
    415                         ast::AssertionSet need;
    416 
    417                         void combineState( const ResolvExpr::Candidate & cand ) {
    418                                 env.simpleCombine( cand.env );
    419                                 ast::mergeOpenVars( open, cand.open );
    420                                 need.insert( cand.need.begin(), cand.need.end() );
    421                         }
    422 
    423                         Matcher(
    424                                 TupleAssignSpotter_new & s, const CodeLocation & loc,
    425                                 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
    426                         : lhs( l ), rhs( r ), spotter( s ), location( loc ),
    427                           baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(),
    428                           env(), open(), need() {
    429                                 for ( auto & cand : lhs ) combineState( *cand );
    430                                 for ( auto & cand : rhs ) combineState( *cand );
    431                         }
    432                         virtual ~Matcher() = default;
    433 
    434                         virtual std::vector< ast::ptr< ast::Expr > > match() = 0;
    435 
    436                         /// removes environments from subexpressions within statement expressions, which could
    437                         /// throw off later passes like those in Box which rely on PolyMutator, and adds the
    438                         /// bindings to the env
    439                         struct EnvRemover {
    440                                 /// environment to hoist ExprStmt environments to
    441                                 ast::TypeEnvironment & tenv;
    442 
    443                                 EnvRemover( ast::TypeEnvironment & e ) : tenv( e ) {}
    444 
    445                                 const ast::ExprStmt * previsit( const ast::ExprStmt * stmt ) {
    446                                         if ( stmt->expr->env ) {
    447                                                 tenv.add( *stmt->expr->env );
    448                                                 ast::ExprStmt * mut = mutate( stmt );
    449                                                 mut->expr.get_and_mutate()->env = nullptr;
    450                                                 return mut;
    451                                         }
    452                                         return stmt;
    453                                 }
    454                         };
    455 
    456                         ast::ObjectDecl * newObject( UniqueName & namer, const ast::Expr * expr ) {
    457                                 assert( expr->result && ! expr->result->isVoid() );
    458 
    459                                 ast::ObjectDecl * ret = new ast::ObjectDecl{
    460                                         location, namer.newName(), expr->result, new ast::SingleInit{ location, expr },
    461                                         ast::Storage::Classes{}, ast::Linkage::Cforall };
    462 
    463                                 // if expression type is a reference, just need an initializer, otherwise construct
    464                                 if ( ! expr->result.as< ast::ReferenceType >() ) {
    465                                         // resolve ctor/dtor for the new object
    466                                         ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
    467                                                         InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
    468                                         // remove environments from subexpressions of stmtExpr
    469                                         ast::Pass< EnvRemover > rm{ env };
    470                                         ret->init = ctorInit->accept( rm );
    471                                 }
    472 
    473                                 PRINT( std::cerr << "new object: " << ret << std::endl; )
    474                                 return ret;
    475                         }
    476 
    477                         ast::UntypedExpr * createFunc(
    478                                 const std::string & fname, const ast::ObjectDecl * left,
    479                                 const ast::ObjectDecl * right
    480                         ) {
    481                                 assert( left );
    482                                 std::vector< ast::ptr< ast::Expr > > args;
    483                                 args.emplace_back( new ast::VariableExpr{ location, left } );
    484                                 if ( right ) { args.emplace_back( new ast::VariableExpr{ location, right } ); }
    485 
    486                                 if ( left->type->referenceDepth() > 1 && CodeGen::isConstructor( fname ) ) {
    487                                         args.front() = new ast::AddressExpr{ location, args.front() };
    488                                         if ( right ) { args.back() = new ast::AddressExpr{ location, args.back() }; }
    489                                         return new ast::UntypedExpr{
    490                                                 location, new ast::NameExpr{ location, "?=?" }, std::move(args) };
    491                                 } else {
    492                                         return new ast::UntypedExpr{
    493                                                 location, new ast::NameExpr{ location, fname }, std::move(args) };
    494                                 }
    495                         }
    496                 };
    497 
    498                 /// Finds mass-assignment operations
    499                 struct MassAssignMatcher final : public Matcher {
    500                         MassAssignMatcher(
    501                                 TupleAssignSpotter_new & s, const CodeLocation & loc,
    502                                 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
    503                         : Matcher( s, loc, l, r ) {}
    504 
    505                         std::vector< ast::ptr< ast::Expr > > match() override {
    506                                 static UniqueName lhsNamer( "__massassign_L" );
    507                                 static UniqueName rhsNamer( "__massassign_R" );
    508                                 // empty tuple case falls into this matcher
    509                                 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 );
    510 
    511                                 ast::ptr< ast::ObjectDecl > rtmp =
    512                                         rhs.size() == 1 ? newObject( rhsNamer, rhs.front()->expr ) : nullptr;
    513 
    514                                 std::vector< ast::ptr< ast::Expr > > out;
    515                                 for ( ResolvExpr::CandidateRef & lhsCand : lhs ) {
    516                                         // create a temporary object for each value in the LHS and create a call
    517                                         // involving the RHS
    518                                         ast::ptr< ast::ObjectDecl > ltmp = newObject( lhsNamer, lhsCand->expr );
    519                                         out.emplace_back( createFunc( spotter.fname, ltmp, rtmp ) );
    520                                         tmpDecls.emplace_back( std::move( ltmp ) );
    521                                 }
    522                                 if ( rtmp ) tmpDecls.emplace_back( std::move( rtmp ) );
    523 
    524                                 return out;
    525                         }
    526                 };
    527 
    528                 /// Finds multiple-assignment operations
    529                 struct MultipleAssignMatcher final : public Matcher {
    530                         MultipleAssignMatcher(
    531                                 TupleAssignSpotter_new & s, const CodeLocation & loc,
    532                                 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
    533                         : Matcher( s, loc, l, r ) {}
    534 
    535                         std::vector< ast::ptr< ast::Expr > > match() override {
    536                                 static UniqueName lhsNamer( "__multassign_L" );
    537                                 static UniqueName rhsNamer( "__multassign_R" );
    538 
    539                                 if ( lhs.size() != rhs.size() ) return {};
    540 
    541                                 // produce a new temporary object for each value in the LHS and RHS and pairwise
    542                                 // create the calls
    543                                 std::vector< ast::ptr< ast::ObjectDecl > > ltmp, rtmp;
    544 
    545                                 std::vector< ast::ptr< ast::Expr > > out;
    546                                 for ( unsigned i = 0; i < lhs.size(); ++i ) {
    547                                         ResolvExpr::CandidateRef & lhsCand = lhs[i];
    548                                         ResolvExpr::CandidateRef & rhsCand = rhs[i];
    549 
    550                                         // convert RHS to LHS type minus one reference -- important for case where LHS
    551                                         // is && and RHS is lvalue
    552                                         auto lhsType = lhsCand->expr->result.strict_as< ast::ReferenceType >();
    553                                         rhsCand->expr = new ast::CastExpr{ rhsCand->expr, lhsType->base };
    554                                         ast::ptr< ast::ObjectDecl > lobj = newObject( lhsNamer, lhsCand->expr );
    555                                         ast::ptr< ast::ObjectDecl > robj = newObject( rhsNamer, rhsCand->expr );
    556                                         out.emplace_back( createFunc( spotter.fname, lobj, robj ) );
    557                                         ltmp.emplace_back( std::move( lobj ) );
    558                                         rtmp.emplace_back( std::move( robj ) );
    559 
    560                                         // resolve the cast expression so that rhsCand return type is bound by the cast
    561                                         // type as needed, and transfer the resulting environment
    562                                         ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
    563                                         finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
    564                                         assert( finder.candidates.size() == 1 );
    565                                         env = std::move( finder.candidates.front()->env );
    566                                 }
    567 
    568                                 splice( tmpDecls, ltmp );
    569                                 splice( tmpDecls, rtmp );
    570 
    571                                 return out;
    572                         }
    573                 };
    574 
    575                 ResolvExpr::CandidateFinder & crntFinder;
    576                 std::string fname;
    577                 std::unique_ptr< Matcher > matcher;
    578 
    579         public:
    580                 TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f )
    581                 : crntFinder( f ), fname(), matcher() {}
    582 
    583                 // find left- and right-hand-sides for mass or multiple assignment
    584                 void spot(
    585                         const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
    586                 ) {
    587                         if ( auto op = expr->func.as< ast::NameExpr >() ) {
    588                                 // skip non-assignment functions
    589                                 if ( ! CodeGen::isCtorDtorAssign( op->name ) ) return;
    590                                 fname = op->name;
    591 
    592                                 // handled by CandidateFinder if applicable (both odd cases)
    593                                 if ( args.empty() || ( args.size() == 1 && CodeGen::isAssignment( fname ) ) ) {
    594                                         return;
    595                                 }
    596 
    597                                 // look over all possible left-hand-side
    598                                 for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) {
    599                                         // skip non-tuple LHS
    600                                         if ( ! refToTuple( lhsCand->expr ) ) continue;
    601 
    602                                         // explode is aware of casts - ensure every LHS is sent into explode with a
    603                                         // reference cast
    604                                         if ( ! lhsCand->expr.as< ast::CastExpr >() ) {
    605                                                 lhsCand->expr = new ast::CastExpr{
    606                                                         lhsCand->expr, new ast::ReferenceType{ lhsCand->expr->result } };
    607                                         }
    608 
    609                                         // explode the LHS so that each field of a tuple-valued expr is assigned
    610                                         ResolvExpr::CandidateList lhs;
    611                                         explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
    612                                         for ( ResolvExpr::CandidateRef & cand : lhs ) {
    613                                                 // each LHS value must be a reference - some come in with a cast, if not
    614                                                 // just cast to reference here
    615                                                 if ( ! cand->expr->result.as< ast::ReferenceType >() ) {
    616                                                         cand->expr = new ast::CastExpr{
    617                                                                 cand->expr, new ast::ReferenceType{ cand->expr->result } };
    618                                                 }
    619                                         }
    620 
    621                                         if ( args.size() == 1 ) {
    622                                                 // mass default-initialization/destruction
    623                                                 ResolvExpr::CandidateList rhs{};
    624                                                 matcher.reset( new MassAssignMatcher{ *this, expr->location, lhs, rhs } );
    625                                                 match();
    626                                         } else if ( args.size() == 2 ) {
    627                                                 for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) {
    628                                                         ResolvExpr::CandidateList rhs;
    629                                                         if ( isTuple( rhsCand->expr ) ) {
    630                                                                 // multiple assignment
    631                                                                 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
    632                                                                 matcher.reset(
    633                                                                         new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
    634                                                         } else {
    635                                                                 // mass assignment
    636                                                                 rhs.emplace_back( rhsCand );
    637                                                                 matcher.reset(
    638                                                                         new MassAssignMatcher{ *this, expr->location, lhs, rhs } );
    639                                                         }
    640                                                         match();
    641                                                 }
    642                                         } else {
    643                                                 // expand all possible RHS possibilities
    644                                                 std::vector< ResolvExpr::CandidateList > rhsCands;
    645                                                 combos(
    646                                                         std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) );
    647                                                 for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) {
    648                                                         // multiple assignment
    649                                                         ResolvExpr::CandidateList rhs;
    650                                                         explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
    651                                                         matcher.reset(
    652                                                                 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
    653                                                         match();
    654                                                 }
    655                                         }
    656                                 }
    657                         }
    658                 }
    659 
    660                 void match() {
    661                         assert( matcher );
    662 
    663                         std::vector< ast::ptr< ast::Expr > > newAssigns = matcher->match();
    664 
    665                         if ( ! ( matcher->lhs.empty() && matcher->rhs.empty() ) ) {
    666                                 // if both LHS and RHS are empty than this is the empty tuple case, wherein it's
    667                                 // okay for newAssigns to be empty. Otherwise, return early so that no new
    668                                 // candidates are generated
    669                                 if ( newAssigns.empty() ) return;
    670                         }
    671 
    672                         ResolvExpr::CandidateList crnt;
    673                         // now resolve new assignments
    674                         for ( const ast::Expr * expr : newAssigns ) {
    675                                 PRINT(
    676                                         std::cerr << "== resolving tuple assign ==" << std::endl;
    677                                         std::cerr << expr << std::endl;
    678                                 )
    679 
    680                                 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };
    681 
    682                                 try {
    683                                         finder.find( expr, ResolvExpr::ResolvMode::withAdjustment() );
    684                                 } catch (...) {
    685                                         // no match is not failure, just that this tuple assignment is invalid
    686                                         return;
    687                                 }
    688 
    689                                 ResolvExpr::CandidateList & cands = finder.candidates;
    690                                 assert( cands.size() == 1 );
    691                                 assert( cands.front()->expr );
    692                                 crnt.emplace_back( std::move( cands.front() ) );
    693                         }
    694 
    695                         // extract expressions from the assignment candidates to produce a list of assignments
    696                         // that together form a sigle candidate
    697                         std::vector< ast::ptr< ast::Expr > > solved;
    698                         for ( ResolvExpr::CandidateRef & cand : crnt ) {
    699                                 solved.emplace_back( cand->expr );
    700                                 matcher->combineState( *cand );
    701                         }
    702 
    703                         crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >(
    704                                 new ast::TupleAssignExpr{
    705                                         matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) },
    706                                 std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ),
    707                                 ResolvExpr::sumCost( crnt ) + matcher->baseCost ) );
    708                 }
    709         };
    710 } // anonymous namespace
    711 
    712 void handleTupleAssignment(
    713         ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
    714         std::vector< ResolvExpr::CandidateFinder > & args
    715 ) {
    716         TupleAssignSpotter_new spotter{ finder };
    717         spotter.spot( assign, args );
    718 }
    719 
    720363} // namespace Tuples
    721364
  • src/Tuples/TupleExpansion.cc

    rb067d9b r7951100  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 19 14:39:00 2019
    13 // Update Count     : 22
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jun 21 17:35:04 2017
     13// Update Count     : 19
    1414//
    1515
     
    1717#include <cassert>                // for assert
    1818#include <list>                   // for list
    19 #include <vector>
    20 
    21 #include "AST/CVQualifiers.hpp"
    22 #include "AST/Expr.hpp"
    23 #include "AST/Node.hpp"
    24 #include "AST/Type.hpp"
     19
    2520#include "Common/PassVisitor.h"   // for PassVisitor, WithDeclsToAdd, WithGu...
    2621#include "Common/ScopedMap.h"     // for ScopedMap
     
    6358                };
    6459
    65                 struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithConstTypeSubstitution {
     60                struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithTypeSubstitution {
    6661                        Type * postmutate( TupleType * tupleType );
    6762
     
    304299                // produce the TupleType which aggregates the types of the exprs
    305300                std::list< Type * > types;
    306                 Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic | Type::Mutex );
     301                Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Lvalue | Type::Atomic | Type::Mutex );
    307302                for ( Expression * expr : exprs ) {
    308303                        assert( expr->get_result() );
     
    319314                return new TupleType( qualifiers, types );
    320315        }
    321         const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs ) {
    322                 // produce the TupleType which aggregates the types of the exprs
    323                 std::vector<ast::ptr<ast::Type>> types;
    324                 ast::CV::Qualifiers quals{
    325                         ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Lvalue |
    326                         ast::CV::Atomic | ast::CV::Mutex };
    327 
    328                 for ( const ast::Expr * expr : exprs ) {
    329                         assert( expr->result );
    330                         // if the type of any expr is void, the type of the entire tuple is void
    331                         if ( expr->result->isVoid() ) return new ast::VoidType{};
    332 
    333                         // qualifiers on the tuple type are the qualifiers that exist on all components
    334                         quals &= expr->result->qualifiers;
    335 
    336                         types.emplace_back( expr->result );
    337                 }
    338 
    339                 if ( exprs.empty() ) { quals = ast::CV::Qualifiers{}; }
    340                 return new ast::TupleType{ std::move(types), quals };
    341         }
    342316
    343317        TypeInstType * isTtype( Type * type ) {
     
    350324        }
    351325
    352         const TypeInstType * isTtype( const Type * type ) {
    353                 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type ) ) {
    354                         if ( inst->baseType && inst->baseType->kind == TypeDecl::Ttype ) {
    355                                 return inst;
    356                         }
    357                 }
    358                 return nullptr;
    359         }
    360 
    361         const ast::TypeInstType * isTtype( const ast::Type * type ) {
    362                 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    363                         if ( inst->base && inst->base->kind == ast::TypeVar::Ttype ) {
    364                                 return inst;
    365                         }
    366                 }
    367                 return nullptr;
    368         }
    369 
    370326        namespace {
    371327                /// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure
     
    373329                        ImpurityDetector( bool ignoreUnique ) : ignoreUnique( ignoreUnique ) {}
    374330
    375                         void previsit( const ApplicationExpr * appExpr ) {
     331                        void previsit( ApplicationExpr * appExpr ) {
    376332                                visit_children = false;
    377                                 if ( const DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
    378                                         if ( function->linkage == LinkageSpec::Intrinsic ) {
    379                                                 if ( function->name == "*?" || function->name == "?[?]" ) {
     333                                if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
     334                                        if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
     335                                                if ( function->get_name() == "*?" || function->get_name() == "?[?]" ) {
    380336                                                        // intrinsic dereference, subscript are pure, but need to recursively look for impurity
    381337                                                        visit_children = true;
     
    386342                                maybeImpure = true;
    387343                        }
    388                         void previsit( const UntypedExpr * ) { maybeImpure = true; visit_children = false; }
    389                         void previsit( const UniqueExpr * ) {
     344                        void previsit( UntypedExpr * ) { maybeImpure = true; visit_children = false; }
     345                        void previsit( UniqueExpr * ) {
    390346                                if ( ignoreUnique ) {
    391347                                        // bottom out at unique expression.
     
    402358        } // namespace
    403359
    404         bool maybeImpure( const Expression * expr ) {
     360        bool maybeImpure( Expression * expr ) {
    405361                PassVisitor<ImpurityDetector> detector( false );
    406362                expr->accept( detector );
     
    408364        }
    409365
    410         bool maybeImpureIgnoreUnique( const Expression * expr ) {
     366        bool maybeImpureIgnoreUnique( Expression * expr ) {
    411367                PassVisitor<ImpurityDetector> detector( true );
    412368                expr->accept( detector );
  • src/Tuples/Tuples.h

    rb067d9b r7951100  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jun 18 09:36:00 2019
    13 // Update Count     : 18
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:55:00 2017
     13// Update Count     : 16
    1414//
    1515
     
    1919#include <vector>
    2020
    21 #include "AST/Fwd.hpp"
    22 #include "AST/Node.hpp"
    2321#include "SynTree/Expression.h"
    2422#include "SynTree/Declaration.h"
     
    2624
    2725#include "ResolvExpr/AlternativeFinder.h"
    28 #include "ResolvExpr/CandidateFinder.hpp"
    2926
    3027namespace Tuples {
    3128        // TupleAssignment.cc
    32         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
     29        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, 
    3330                std::vector< ResolvExpr::AlternativeFinder >& args );
    34         void handleTupleAssignment(
    35                 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
    36                 std::vector< ResolvExpr::CandidateFinder > & args );
    37 
     31       
    3832        // TupleExpansion.cc
    3933        /// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
     
    4842        /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
    4943        Type * makeTupleType( const std::list< Expression * > & exprs );
    50         const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs );
    5144
    5245        /// returns a TypeInstType if `type` is a ttype, nullptr otherwise
    5346        TypeInstType * isTtype( Type * type );
    54         const TypeInstType * isTtype( const Type * type );
    55         const ast::TypeInstType * isTtype( const ast::Type * type );
    5647
    5748        /// returns true if the expression may contain side-effects.
    58         bool maybeImpure( const Expression * expr );
    59         bool maybeImpure( const ast::Expr * expr );
     49        bool maybeImpure( Expression * expr );
    6050
    61         /// Returns true if the expression may contain side-effect,
    62         /// ignoring the presence of unique expressions.
    63         bool maybeImpureIgnoreUnique( const Expression * expr );
    64         bool maybeImpureIgnoreUnique( const ast::Expr * expr );
     51        /// returns true if the expression may contain side-effect, ignoring the presence of unique expressions.
     52        bool maybeImpureIgnoreUnique( Expression * expr );
    6553} // namespace Tuples
    6654
  • src/Tuples/module.mk

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 SRC += Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc Tuples/Explode.cc \
    18         Tuples/Tuples.cc
    19 SRCDEMANGLE += Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc Tuples/Explode.cc \
    20         Tuples/Tuples.cc
     17SRC +=  Tuples/TupleAssignment.cc \
     18        Tuples/TupleExpansion.cc \
     19        Tuples/Explode.cc
  • src/Virtual/ExpandCasts.cc

    rb067d9b r7951100  
    147147                                //              )
    148148                                //      ),
    149                         new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
     149                        new UntypedExpr( new NameExpr( "__cfa__virtual_cast" ), {
    150150                                        new CastExpr(
    151151                                                new AddressExpr( new VariableExpr( table ) ),
    152152                                                pointer_to_pvt(1)
    153                                         ),
     153                                                ),
    154154                                        new CastExpr(
    155155                                                castExpr->get_arg(),
    156156                                                pointer_to_pvt(2)
    157                                         )
    158                         } ),
     157                                                )
     158                                } ),
    159159                        castExpr->get_result()->clone()
    160                 );
     160                        );
    161161
    162162                castExpr->set_arg( nullptr );
  • src/include/cassert

    rb067d9b r7951100  
    99// Author           : Peter A. Buhr
    1010// Created On       : Thu Aug 18 13:19:26 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun  3 13:11:00 2017
    13 // Update Count     : 18
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Aug  1 11:56:01 2017
     13// Update Count     : 16
    1414//
    1515
     
    1919
    2020#include_next <cassert>
    21 
    22 #include <string>
    23 
    24 template < typename ... Params >
    25 std::string toString( const Params & ... params );
    2621
    2722#ifdef NDEBUG
     
    4540template<typename T, typename U>
    4641static inline T strict_dynamic_cast( const U & src ) {
    47         assert(src);
    4842        T ret = dynamic_cast<T>(src);
    4943        assertf(ret, "%s", toString(src).c_str());
     
    5145}
    5246
    53 template<typename T, decltype(nullptr) null, typename U>
    54 static inline T strict_dynamic_cast( const U & src ) {
    55         return src ? strict_dynamic_cast<T, U>( src ) : nullptr;
    56 }
    57 
    58 extern void abort(const char *fmt, ...  ) noexcept __attribute__((noreturn, format(printf, 1, 2)));
    5947// Local Variables: //
    6048// tab-width: 4 //
  • src/main.cc

    rb067d9b r7951100  
    77// main.cc --
    88//
    9 // Author           : Peter Buhr and Rob Schluntz
     9// Author           : Richard C. Bilson
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Aug 23 06:50:08 2019
    13 // Update Count     : 607
     12// Last Modified On : Wed Jun  6 15:51:47 2018
     13// Update Count     : 498
    1414//
    1515
     
    1717#include <execinfo.h>                       // for backtrace, backtrace_symbols
    1818#include <getopt.h>                         // for no_argument, optind, geto...
     19#include <signal.h>                         // for signal, SIGABRT, SIGSEGV
    1920#include <cassert>                          // for assertf
    2021#include <cstdio>                           // for fopen, FILE, fclose, stdin
    2122#include <cstdlib>                          // for exit, free, abort, EXIT_F...
    22 #include <csignal>                         // for signal, SIGABRT, SIGSEGV
    2323#include <cstring>                          // for index
    2424#include <fstream>                          // for ofstream
    2525#include <iostream>                         // for operator<<, basic_ostream
    26 #include <iomanip>
    2726#include <iterator>                         // for back_inserter
    2827#include <list>                             // for list
    2928#include <string>                           // for char_traits, operator<<
    3029
    31 #include "CompilationState.h"
    3230#include "../config.h"                      // for CFA_LIBDIR
    3331#include "CodeGen/FixMain.h"                // for FixMain
     
    3533#include "CodeGen/Generate.h"               // for generate
    3634#include "CodeTools/DeclStats.h"            // for printDeclStats
    37 #include "CodeTools/ResolvProtoDump.h"      // for dumpAsResolvProto
    3835#include "CodeTools/TrackLoc.h"             // for fillLocations
    3936#include "Common/CompilerError.h"           // for CompilerError
    40 #include "Common/Stats.h"
     37#include "Common/Heap.h"
    4138#include "Common/PassVisitor.h"
    4239#include "Common/SemanticError.h"           // for SemanticError
     
    6461#include "Virtual/ExpandCasts.h"            // for expandCasts
    6562
    66 
    6763using namespace std;
    6864
    69 static void NewPass( const char * const name ) {
    70         Stats::Heap::newPass( name );
    71         using namespace Stats::Counters;
    72         {
    73                 static auto group = build<CounterGroup>( "Pass Visitor" );
    74                 auto pass = build<CounterGroup>( name, group );
    75                 pass_visitor_stats.depth = 0;
    76                 pass_visitor_stats.avg = build<AverageCounter<double>>( "Average Depth", pass );
    77                 pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass );
    78         }
    79         {
    80                 static auto group = build<CounterGroup>( "Syntax Node" );
    81                 auto pass = build<CounterGroup>( name, group );
    82                 BaseSyntaxNode::new_nodes = build<SimpleCounter>( "Allocs", pass );
    83         }
    84 }
    85 
    86 #define PASS( name, pass )                  \
     65#define PASS(name, pass)                   \
    8766        if ( errorp ) { cerr << name << endl; } \
    88         NewPass(name);                          \
    89         Stats::Time::StartBlock(name);          \
    90         pass;                                   \
    91         Stats::Time::StopBlock();
     67        HeapStats::newPass(name);               \
     68        pass;
    9269
    9370LinkageSpec::Spec linkage = LinkageSpec::Cforall;
     
    9572DeclarationNode * parseTree = nullptr;                                  // program parse tree
    9673
    97 static bool waiting_for_gdb = false;                                    // flag to set cfa-cpp to wait for gdb on start
    98 
    99 static std::string PreludeDirector = "";
    100 
    101 static void parse_cmdline( int argc, char *argv[] );
     74extern int yydebug;                                                                             // set for -g flag (Grammar)
     75bool
     76        astp = false,
     77        bresolvep = false,
     78        bboxp = false,
     79        bcodegenp = false,
     80        ctorinitp = false,
     81        declstatsp = false,
     82        exprp = false,
     83        expraltp = false,
     84        genericsp = false,
     85        libcfap = false,
     86        nopreludep = false,
     87        noprotop = false,
     88        nomainp = false,
     89        parsep = false,
     90        resolvep = false,                                                                       // used in AlternativeFinder
     91        symtabp = false,
     92        treep = false,
     93        tuplep = false,
     94        validp = false,
     95        errorp = false,
     96        codegenp = false,
     97        prettycodegenp = false,
     98        linemarks = false;
     99
     100static void parse_cmdline( int argc, char *argv[], const char *& filename );
    102101static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false );
    103102static void dump( list< Declaration * > & translationUnit, ostream & out = cout );
     
    153152} // backtrace
    154153
    155 static void sigSegvBusHandler( int sig_num ) {
     154void sigSegvBusHandler( int sig_num ) {
    156155        cerr << "*CFA runtime error* program cfa-cpp terminated with "
    157156                 <<     (sig_num == SIGSEGV ? "segment fault" : "bus error")
     
    159158        backtrace( 2 );                                                                         // skip first 2 stack frames
    160159        //_exit( EXIT_FAILURE );
    161         abort();                                                                                        // cause core dump for debugging
     160        abort();
    162161} // sigSegvBusHandler
    163162
    164 static void sigAbortHandler( __attribute__((unused)) int sig_num ) {
     163void sigAbortHandler( __attribute__((unused)) int sig_num ) {
    165164        backtrace( 6 );                                                                         // skip first 6 stack frames
    166165        signal( SIGABRT, SIG_DFL);                                                      // reset default signal handler
    167         raise( SIGABRT );                                                                       // reraise SIGABRT
     166    raise( SIGABRT );                                                                   // reraise SIGABRT
    168167} // sigAbortHandler
     168
    169169
    170170int main( int argc, char * argv[] ) {
    171171        FILE * input;                                                                           // use FILE rather than istream because yyin is FILE
    172         ostream * output = & cout;
     172        ostream *output = & cout;
     173        const char *filename = nullptr;
    173174        list< Declaration * > translationUnit;
    174175
     
    182183        // } // for
    183184
    184         parse_cmdline( argc, argv );                                            // process command-line arguments
     185        parse_cmdline( argc, argv, filename );                          // process command-line arguments
    185186        CodeGen::FixMain::setReplaceMain( !nomainp );
    186 
    187         if ( waiting_for_gdb ) {
    188                 std::cerr << "Waiting for gdb" << std::endl;
    189                 std::cerr << "run :" << std::endl;
    190                 std::cerr << "  gdb attach " << getpid() << std::endl;
    191                 raise(SIGSTOP);
    192         } // if
    193187
    194188        try {
     
    196190                if ( optind < argc ) {                                                  // any commands after the flags ? => input file name
    197191                        input = fopen( argv[ optind ], "r" );
    198                         assertf( input, "cannot open %s because %s\n", argv[ optind ], strerror( errno ) );
     192                        assertf( input, "cannot open %s\n", argv[ optind ] );
     193                        // if running cfa-cpp directly, might forget to pass -F option (and really shouldn't have to)
     194                        if ( filename == nullptr ) filename = argv[ optind ];
     195                        // prelude filename comes in differently
     196                        if ( libcfap ) filename = "prelude.cf";
    199197                        optind += 1;
    200198                } else {                                                                                // no input file name
    201199                        input = stdin;
    202                 } // if
    203 
    204                 Stats::Time::StartGlobal();
    205                 NewPass("Parse");
    206                 Stats::Time::StartBlock("Parse");
     200                        // if running cfa-cpp directly, might forget to pass -F option. Since this takes from stdin, pass
     201                        // a fake name along
     202                        if ( filename == nullptr ) filename = "stdin";
     203                } // if
    207204
    208205                // read in the builtins, extras, and the prelude
     
    210207                        // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here.
    211208
    212                         assertf( !PreludeDirector.empty(), "Can't find prelude without option --prelude-dir must be used." );
    213 
    214209                        // Read to gcc builtins, if not generating the cfa library
    215                         FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" );
     210                        FILE * gcc_builtins = fopen( libcfap | treep ? "../prelude/gcc-builtins.cf" : CFA_LIBDIR "/gcc-builtins.cf", "r" );
    216211                        assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" );
    217212                        parse( gcc_builtins, LinkageSpec::Compiler );
    218213
    219214                        // read the extra prelude in, if not generating the cfa library
    220                         FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" );
     215                        FILE * extras = fopen( libcfap | treep ? "../prelude/extras.cf" : CFA_LIBDIR "/extras.cf", "r" );
    221216                        assertf( extras, "cannot open extras.cf\n" );
    222217                        parse( extras, LinkageSpec::BuiltinC );
     
    224219                        if ( ! libcfap ) {
    225220                                // read the prelude in, if not generating the cfa library
    226                                 FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
    227                                 assertf( prelude, "cannot open prelude.cfa\n" );
     221                                FILE * prelude = fopen( treep ? "../prelude/prelude.cf" : CFA_LIBDIR "/prelude.cf", "r" );
     222                                assertf( prelude, "cannot open prelude.cf\n" );
    228223                                parse( prelude, LinkageSpec::Intrinsic );
    229224
    230225                                // Read to cfa builtins, if not generating the cfa library
    231                                 FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" );
     226                                FILE * builtins = fopen( libcfap | treep ? "../prelude/builtins.cf" : CFA_LIBDIR "/builtins.cf", "r" );
    232227                                assertf( builtins, "cannot open builtins.cf\n" );
    233228                                parse( builtins, LinkageSpec::BuiltinCFA );
     
    240235                        parseTree->printList( cout );
    241236                        delete parseTree;
    242                         return EXIT_SUCCESS;
     237                        return 0;
    243238                } // if
    244239
     
    249244                if ( astp ) {
    250245                        dump( translationUnit );
    251                         return EXIT_SUCCESS;
    252                 } // if
    253 
    254                 // Temporary: fill locations after parsing so that every node has a location, for early error messages.
    255                 // Eventually we should pass the locations from the parser to every node, but this quick and dirty solution
    256                 // works okay for now.
    257                 CodeTools::fillLocations( translationUnit );
    258                 Stats::Time::StopBlock();
     246                        return 0;
     247                } // if
    259248
    260249                // add the assignment statement after the initialization of a type parameter
    261                 PASS( "Validate", SymTab::validate( translationUnit, symtabp ) );
     250                PASS( "validate", SymTab::validate( translationUnit, symtabp ) );
    262251                if ( symtabp ) {
    263252                        deleteAll( translationUnit );
    264                         return EXIT_SUCCESS;
     253                        return 0;
    265254                } // if
    266255
     
    268257                        PassVisitor<ResolvExpr::AlternativePrinter> printer( cout );
    269258                        acceptAll( translationUnit, printer );
    270                         return EXIT_SUCCESS;
     259                        return 0;
    271260                } // if
    272261
    273262                if ( validp ) {
    274263                        dump( translationUnit );
    275                         return EXIT_SUCCESS;
    276                 } // if
    277 
    278                 PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    279                 PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
    280                 PASS( "Gen Init", InitTweak::genInit( translationUnit ) );
    281                 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( translationUnit ) );
     264                        return 0;
     265                } // if
     266
     267                PASS( "fixLabels", ControlStruct::fixLabels( translationUnit ) );
     268                PASS( "fixNames", CodeGen::fixNames( translationUnit ) );
     269                PASS( "genInit", InitTweak::genInit( translationUnit ) );
     270                PASS( "expandMemberTuples" , Tuples::expandMemberTuples( translationUnit ) );
    282271                if ( libcfap ) {
    283272                        // generate the bodies of cfa library functions
     
    288277                        CodeTools::printDeclStats( translationUnit );
    289278                        deleteAll( translationUnit );
    290                         return EXIT_SUCCESS;
    291                 } // if
     279                        return 0;
     280                }
    292281
    293282                if ( bresolvep ) {
    294283                        dump( translationUnit );
    295                         return EXIT_SUCCESS;
     284                        return 0;
    296285                } // if
    297286
    298287                CodeTools::fillLocations( translationUnit );
    299288
    300                 if ( resolvprotop ) {
    301                         CodeTools::dumpAsResolvProto( translationUnit );
    302                         return EXIT_SUCCESS;
    303                 } // if
    304 
    305                 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     289                PASS( "resolve", ResolvExpr::resolve( translationUnit ) );
    306290                if ( exprp ) {
    307291                        dump( translationUnit );
    308                         return EXIT_SUCCESS;
     292                        return 0;
    309293                } // if
    310294
    311295                // fix ObjectDecl - replaces ConstructorInit nodes
    312                 PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
     296                PASS( "fixInit", InitTweak::fix( translationUnit, filename, libcfap || treep ) );
    313297                if ( ctorinitp ) {
    314298                        dump ( translationUnit );
    315                         return EXIT_SUCCESS;
    316                 } // if
    317 
    318                 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    319 
    320                 PASS( "Translate EHM" , ControlStruct::translateEHM( translationUnit ) );
    321 
    322                 PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
    323 
    324                 PASS( "Convert Specializations",  GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded
    325 
    326                 PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?
     299                        return 0;
     300                } // if
     301
     302                PASS( "expandUniqueExpr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
     303
     304                PASS( "translateEHM" , ControlStruct::translateEHM( translationUnit ) );
     305
     306                PASS( "generateWaitfor" , Concurrency::generateWaitFor( translationUnit ) );
     307
     308                PASS( "convertSpecializations",  GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded
     309
     310                PASS( "expandTuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?
    327311
    328312                if ( tuplep ) {
    329313                        dump( translationUnit );
    330                         return EXIT_SUCCESS;
    331                 } // if
    332 
    333                 PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM
    334 
    335                 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( translationUnit ) );
     314                        return 0;
     315                }
     316
     317                PASS( "virtual expandCasts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM
     318
     319                PASS( "instantiateGenerics", GenPoly::instantiateGeneric( translationUnit ) );
    336320                if ( genericsp ) {
    337321                        dump( translationUnit );
    338                         return EXIT_SUCCESS;
    339                 } // if
    340 
    341                 PASS( "Convert L-Value", GenPoly::convertLvalue( translationUnit ) );
     322                        return 0;
     323                }
     324                PASS( "convertLvalue", GenPoly::convertLvalue( translationUnit ) );
     325
    342326
    343327                if ( bboxp ) {
    344328                        dump( translationUnit );
    345                         return EXIT_SUCCESS;
    346                 } // if
    347                 PASS( "Box", GenPoly::box( translationUnit ) );
     329                        return 0;
     330                } // if
     331                PASS( "box", GenPoly::box( translationUnit ) );
    348332
    349333                if ( bcodegenp ) {
    350334                        dump( translationUnit );
    351                         return EXIT_SUCCESS;
    352                 } // if
     335                        return 0;
     336                }
    353337
    354338                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     
    357341
    358342                CodeTools::fillLocations( translationUnit );
    359                 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );
    360 
    361                 CodeGen::FixMain::fix( *output, (PreludeDirector + "/bootloader.c").c_str() );
     343                PASS( "codegen", CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp, true, linemarks ) );
     344
     345                CodeGen::FixMain::fix( *output, treep ? "../prelude/bootloader.c" : CFA_LIBDIR "/bootloader.c" );
    362346                if ( output != &cout ) {
    363347                        delete output;
     
    373357                        delete output;
    374358                } // if
    375                 return EXIT_FAILURE;
     359                return 1;
    376360        } catch ( UnimplementedError &e ) {
    377361                cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
     
    379363                        delete output;
    380364                } // if
    381                 return EXIT_FAILURE;
     365                return 1;
    382366        } catch ( CompilerError &e ) {
    383367                cerr << "Compiler Error: " << e.get_what() << endl;
     
    386370                        delete output;
    387371                } // if
    388                 return EXIT_FAILURE;
    389         } catch ( ... ) {
     372                return 1;
     373        } catch(...) {
    390374                std::exception_ptr eptr = std::current_exception();
    391375                try {
    392376                        if (eptr) {
    393377                                std::rethrow_exception(eptr);
    394                         } else {
    395                                 std::cerr << "Exception Uncaught and Unknown" << std::endl;
    396                         } // if
     378                        }
     379                        else {
     380                                std::cerr << "Exception Uncaught and Unkown" << std::endl;
     381                        }
    397382                } catch(const std::exception& e) {
    398                         std::cerr << "Uncaught Exception \"" << e.what() << "\"\n";
    399                 } // try
    400                 return EXIT_FAILURE;
    401         } // try
     383                        std::cerr << "Unaught Exception \"" << e.what() << "\"\n";
     384                }
     385                return 1;
     386        }// try
    402387
    403388        deleteAll( translationUnit );
    404         Stats::print();
    405         return EXIT_SUCCESS;
     389        if(!libcfap && !treep) HeapStats::printStats();
     390        return 0;
    406391} // main
    407392
    408 
    409 static const char optstring[] = ":hlLmNnpP:S:twW:D:";
    410 
    411 enum { PreludeDir = 128 };
    412 static struct option long_opts[] = {
    413         { "help", no_argument, nullptr, 'h' },
    414         { "libcfa", no_argument, nullptr, 'l' },
    415         { "linemarks", no_argument, nullptr, 'L' },
    416         { "no-main", no_argument, 0, 'm' },
    417         { "no-linemarks", no_argument, nullptr, 'N' },
    418         { "no-prelude", no_argument, nullptr, 'n' },
    419         { "prototypes", no_argument, nullptr, 'p' },
    420         { "print", required_argument, nullptr, 'P' },
    421         { "prelude-dir", required_argument, nullptr, PreludeDir },
    422         { "statistics", required_argument, nullptr, 'S' },
    423         { "tree", no_argument, nullptr, 't' },
    424         { "gdb", no_argument, nullptr, 'g' },
    425         { "", no_argument, nullptr, 0 },                                        // -w
    426         { "", no_argument, nullptr, 0 },                                        // -W
    427         { "", no_argument, nullptr, 0 },                                        // -D
    428         { nullptr, 0, nullptr, 0 }
    429 }; // long_opts
    430 
    431 static const char * description[] = {
    432         "print help message",                                                           // -h
    433         "generate libcfa.c",                                                            // -l
    434         "generate line marks",                                                          // -L
    435         "do not replace main",                                                          // -m
    436         "do not generate line marks",                                           // -N
    437         "do not read prelude",                                                          // -n
    438         "generate prototypes for prelude functions",            // -p
    439         "print",                                                                                        // -P
    440         "<directory> prelude directory for debug/nodebug",      // no flag
    441         "<option-list> enable profiling information:\n          counters,heap,time,all,none", // -S
    442         "building cfa standard lib",                                                                    // -t
    443         "wait for gdb to attach",                                                                       // -g
    444         "",                                                                                                     // -w
    445         "",                                                                                                     // -W
    446         "",                                                                                                     // -D
    447 }; // description
    448 
    449 static_assert( sizeof( long_opts ) / sizeof( long_opts[0] ) - 1 == sizeof( description ) / sizeof( description[0] ), "Long opts and description must match" );
    450 
    451 static struct Printopts {
    452         const char * name;
    453         int & flag;
    454         int val;
    455         const char * descript;
    456 } printopts[] = {
    457         { "ascodegen", codegenp, true, "print AST as codegen rather than AST" },
    458         { "asterr", errorp, true, "print AST on error" },
    459         { "declstats", declstatsp, true, "code property statistics" },
    460         { "parse", yydebug, true, "yacc (parsing) debug information" },
    461         { "pretty", prettycodegenp, true, "prettyprint for ascodegen flag" },
    462         { "rproto", resolvprotop, true, "resolver-proto instance" },
    463         { "rsteps", resolvep, true, "print resolver steps" },
    464         { "tree", parsep, true, "print parse tree" },
    465         // code dumps
    466         { "ast", astp, true, "print AST after parsing" },
    467         { "symevt", symtabp, true, "print AST after symbol table events" },
    468         { "altexpr", expraltp, true, "print alternatives for expressions" },
    469         { "astdecl", validp, true, "print AST after declaration validation pass" },
    470         { "resolver", bresolvep, true, "print AST before resolver step" },
    471         { "astexpr", exprp, true, "print AST after expression analysis" },
    472         { "ctordtor", ctorinitp, true, "print AST after ctor/dtor are replaced" },
    473         { "tuple", tuplep, true, "print AST after tuple expansion" },
    474         { "astgen", genericsp, true, "print AST after instantiate generics" },
    475         { "box", bboxp, true, "print AST before box step" },
    476         { "codegen", bcodegenp, true, "print AST before code generation" },
    477 };
    478 enum { printoptsSize = sizeof( printopts ) / sizeof( printopts[0] ) };
    479 
    480 static void usage( char *argv[] ) {
    481     cout << "Usage: " << argv[0] << " [options] [input-file (default stdin)] [output-file (default stdout)], where options are:" << endl;
    482         int i = 0, j = 1;                                                                       // j skips starting colon
    483         for ( ; long_opts[i].name != 0 && optstring[j] != '\0'; i += 1, j += 1 ) {
    484                 if ( long_opts[i].name[0] != '\0' ) {                   // hidden option, internal usage only
    485                         if ( strcmp( long_opts[i].name, "prelude-dir" ) != 0 ) { // flag
    486                                 cout << "  -" << optstring[j] << ",";
    487                         } else {                                                                        // no flag
    488                                 j -= 1;                                                                 // compensate
    489                                 cout << "     ";
    490                         } // if
    491                         cout << " --" << left << setw(12) << long_opts[i].name << "  ";
    492                         if ( strcmp( long_opts[i].name, "print" ) == 0 ) {
    493                                 cout << "one of: " << endl;
    494                                 for ( int i = 0; i < printoptsSize; i += 1 ) {
    495                                         cout << setw(10) << " " << left << setw(10) << printopts[i].name << "  " << printopts[i].descript << endl;
    496                                 } // for
    497                         } else {
    498                                 cout << description[i] << endl;
    499                         } // if
    500                 } // if
    501                 if ( optstring[j + 1] == ':' ) j += 1;
    502         } // for
    503         if ( long_opts[i].name != 0 || optstring[j] != '\0' ) assertf( false, "internal error, mismatch of option flags and names\n" );
    504     exit( EXIT_FAILURE );
    505 } // usage
    506 
    507 static void parse_cmdline( int argc, char * argv[] ) {
     393void parse_cmdline( int argc, char * argv[], const char *& filename ) {
     394        enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, TupleExpansion, Validate, };
     395
     396        static struct option long_opts[] = {
     397                { "ast", no_argument, 0, Ast },
     398                { "before-box", no_argument, 0, Bbox },
     399                { "before-resolver", no_argument, 0, Bresolver },
     400                { "ctorinitfix", no_argument, 0, CtorInitFix },
     401                { "decl-stats", no_argument, 0, DeclStats },
     402                { "expr", no_argument, 0, Expr },
     403                { "expralt", no_argument, 0, ExprAlt },
     404                { "grammar", no_argument, 0, Grammar },
     405                { "libcfa", no_argument, 0, LibCFA },
     406                { "line-marks", no_argument, 0, Linemarks },
     407                { "no-line-marks", no_argument, 0, Nolinemarks },
     408                { "no-preamble", no_argument, 0, Nopreamble },
     409                { "parse", no_argument, 0, Parse },
     410                { "no-prototypes", no_argument, 0, Prototypes },
     411                { "resolver", no_argument, 0, Resolver },
     412                { "symbol", no_argument, 0, Symbol },
     413                { "tree", no_argument, 0, Tree },
     414                { "tuple-expansion", no_argument, 0, TupleExpansion },
     415                { "validate", no_argument, 0, Validate },
     416                { 0, 0, 0, 0 }
     417        }; // long_opts
     418        int long_index;
     419
    508420        opterr = 0;                                                                                     // (global) prevent getopt from printing error messages
    509421
    510422        bool Wsuppress = false, Werror = false;
    511423        int c;
    512         while ( (c = getopt_long( argc, argv, optstring, long_opts, nullptr )) != -1 ) {
     424        while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
    513425                switch ( c ) {
    514                   case 'h':                                                                             // help message
    515                         usage( argv );                                                          // no return
    516                         break;
     426                  case Ast:
     427                  case 'a':                                                                             // dump AST
     428                        astp = true;
     429                        break;
     430                  case Bresolver:
     431                  case 'b':                                                                             // print before resolver steps
     432                        bresolvep = true;
     433                        break;
     434                  case 'B':                                                                             // print before box steps
     435                        bboxp = true;
     436                        break;
     437                  case CtorInitFix:
     438                  case 'c':                                                                             // print after constructors and destructors are replaced
     439                        ctorinitp = true;
     440                        break;
     441                  case 'C':                                                                             // print before code generation
     442                        bcodegenp = true;
     443                        break;
     444                  case DeclStats:
     445                  case 'd':
     446                    declstatsp = true;
     447                        break;
     448                  case Expr:
     449                  case 'e':                                                                             // dump AST after expression analysis
     450                        exprp = true;
     451                        break;
     452                  case ExprAlt:
     453                  case 'f':                                                                             // print alternatives for expressions
     454                        expraltp = true;
     455                        break;
     456                  case Grammar:
     457                  case 'g':                                                                             // bison debugging info (grammar rules)
     458                        yydebug = true;
     459                        break;
     460                  case 'G':                                                                             // dump AST after instantiate generics
     461                        genericsp = true;
     462                        break;
     463                  case LibCFA:
    517464                  case 'l':                                                                             // generate libcfa.c
    518465                        libcfap = true;
    519466                        break;
    520                   case 'L':                                                                             // generate line marks
     467                  case Linemarks:
     468                  case 'L':                                                                             // print lines marks
    521469                        linemarks = true;
    522470                        break;
    523                   case 'm':                                                                             // do not replace main
    524                         nomainp = true;
    525                         break;
    526                   case 'N':                                                                             // do not generate line marks
     471                  case Nopreamble:
     472                  case 'n':                                                                             // do not read preamble
     473                        nopreludep = true;
     474                        break;
     475                  case Nolinemarks:
     476                  case 'N':                                                                             // suppress line marks
    527477                        linemarks = false;
    528478                        break;
    529                   case 'n':                                                                             // do not read prelude
    530                         nopreludep = true;
    531                         break;
    532                   case 'p':                                                                             // generate prototypes for prelude functions
    533                         genproto = true;
    534                         break;
    535                   case 'P':                                                                             // print options
    536                         for ( int i = 0;; i += 1 ) {
    537                                 if ( i == printoptsSize ) {
    538                                         cout << "Unknown --print option " << optarg << endl;
    539                                         goto Default;
    540                                 } // if
    541                                 if ( strcmp( optarg, printopts[i].name ) == 0 ) {
    542                                         printopts[i].flag = printopts[i].val;
    543                                         break;
    544                                 } // if
    545                         } // for
    546                         break;
    547                   case PreludeDir:                                                              // prelude directory for debug/nodebug, hidden
    548                         PreludeDirector = optarg;
    549                         break;
    550                   case 'S':                                                                             // enable profiling information, argument comma separated list of names
    551                         Stats::parse_params( optarg );
    552                         break;
    553                   case 't':                                                                             // building cfa stdlib
     479                  case Prototypes:
     480                  case 'p':                                                                             // generate prototypes for preamble functions
     481                        noprotop = true;
     482                        break;
     483                  case 'm':                                                                             // don't replace the main
     484                        nomainp = true;
     485                        break;
     486                  case Parse:
     487                  case 'q':                                                                             // dump parse tree
     488                        parsep = true;
     489                        break;
     490                  case Resolver:
     491                  case 'r':                                                                             // print resolver steps
     492                        resolvep = true;
     493                        break;
     494                  case Symbol:
     495                  case 's':                                                                             // print symbol table events
     496                        symtabp = true;
     497                        break;
     498                  case Tree:
     499                  case 't':                                                                             // build in tree
    554500                        treep = true;
    555501                        break;
    556                   case 'g':                                                                             // wait for gdb
    557                         waiting_for_gdb = true;
    558                         break;
    559                   case 'w':                                                                             // suppress all warnings, hidden
     502                  case TupleExpansion:
     503                  case 'T':                                                                             // print after tuple expansion
     504                        tuplep = true;
     505                        break;
     506                  case 'v':                                                                             // dump AST after decl validation pass
     507                        validp = true;
     508                        break;
     509                  case 'w':
    560510                        Wsuppress = true;
    561511                        break;
    562                   case 'W':                                                                             // coordinate gcc -W with CFA, hidden
     512                  case 'W':
    563513                        if ( strcmp( optarg, "all" ) == 0 ) {
    564514                                SemanticWarning_EnableAll();
     
    577527                        } // if
    578528                        break;
    579                   case 'D':                                                                             // ignore -Dxxx, forwarded by cpp, hidden
    580                         break;
    581                   case '?':                                                                             // unknown option
     529                  case 'y':                                                                             // dump AST on error
     530                        errorp = true;
     531                        break;
     532                  case 'z':                                                                             // dump as codegen rather than AST
     533                        codegenp = true;
     534                        break;
     535                        case 'Z':                                                                       // prettyprint during codegen (i.e. print unmangled names, etc.)
     536                        prettycodegenp = true;
     537                        break;
     538                  case 'D':                                                                             // ignore -Dxxx
     539                        break;
     540                  case 'F':                                                                             // source file-name without suffix
     541                        filename = optarg;
     542                        break;
     543                  case '?':
    582544                        if ( optopt ) {                                                         // short option ?
    583                                 cout << "Unknown option -" << (char)optopt << endl;
     545                                assertf( false, "Unknown option: -%c\n", (char)optopt );
    584546                        } else {
    585                                 cout << "Unknown option " << argv[optind - 1] << endl;
     547                                assertf( false, "Unknown option: %s\n", argv[optind - 1] );
    586548                        } // if
    587                         goto Default;
    588                   case ':':                                                                             // missing option
    589                         if ( optopt ) {                                                         // short option ?
    590                                 cout << "Missing option for -" << (char)optopt << endl;
    591                         } else {
    592                                 cout << "Missing option for " << argv[optind - 1] << endl;
    593                         } // if
    594                         goto Default;
    595                   Default:
     549                        #if defined(__GNUC__) && __GNUC__ >= 7
     550                                __attribute__((fallthrough));
     551                        #endif
    596552                  default:
    597                         usage( argv );                                                          // no return
     553                        abort();
    598554                } // switch
    599555        } // while
     
    633589        list< Declaration * > decls;
    634590
    635         if ( genproto ) {
     591        if ( noprotop ) {
    636592                filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude );
    637593        } else {
     
    641597        // depending on commandline options, either generate code or dump the AST
    642598        if ( codegenp ) {
    643                 CodeGen::generate( decls, out, ! genproto, prettycodegenp );
     599                CodeGen::generate( decls, out, ! noprotop, prettycodegenp );
    644600        } else {
    645601                printAll( decls, out );
    646         } // if
     602        }
    647603        deleteAll( translationUnit );
    648604} // dump
  • tools/Makefile.am

    rb067d9b r7951100  
    1515###############################################################################
    1616
    17 AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
    18 ACLOCAL_AMFLAGS  = -I automake
     17CC = @BACKEND_CC@
     18CFLAGS = -Wall -Wextra -O2 -g
    1919
    20 AM_CFLAGS = -Wall -Wextra -O2 -g
    21 
    22 noinst_PROGRAMS = busy catchsig repeat watchdog
     20noinst_PROGRAMS = busy catchsig repeat
    2321
    2422busy_SOURCES     = busy.c
     
    2624catchsig_SOURCES = catchsig.c
    2725repeat_SOURCES   = repeat.c
    28 watchdog_SOURCES = watchdog.c
  • tools/Makefile.in

    rb067d9b r7951100  
    9292build_triplet = @build@
    9393host_triplet = @host@
    94 noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT) \
    95         watchdog$(EXEEXT)
     94noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT)
    9695subdir = tools
    9796ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    98 am__aclocal_m4_deps = $(top_srcdir)/automake/libtool.m4 \
    99         $(top_srcdir)/automake/ltoptions.m4 \
    100         $(top_srcdir)/automake/ltsugar.m4 \
    101         $(top_srcdir)/automake/ltversion.m4 \
    102         $(top_srcdir)/automake/lt~obsolete.m4 \
    103         $(top_srcdir)/automake/cfa.m4 $(top_srcdir)/configure.ac
     97am__aclocal_m4_deps = $(top_srcdir)/configure.ac
    10498am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    10599        $(ACLOCAL_M4)
     
    113107busy_OBJECTS = $(am_busy_OBJECTS)
    114108busy_LDADD = $(LDADD)
    115 AM_V_lt = $(am__v_lt_@AM_V@)
    116 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
    117 am__v_lt_0 = --silent
    118 am__v_lt_1 =
    119 busy_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    120         $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
    121         $(busy_LDFLAGS) $(LDFLAGS) -o $@
     109busy_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(busy_LDFLAGS) $(LDFLAGS) \
     110        -o $@
    122111am_catchsig_OBJECTS = catchsig.$(OBJEXT)
    123112catchsig_OBJECTS = $(am_catchsig_OBJECTS)
     
    126115repeat_OBJECTS = $(am_repeat_OBJECTS)
    127116repeat_LDADD = $(LDADD)
    128 am_watchdog_OBJECTS = watchdog.$(OBJEXT)
    129 watchdog_OBJECTS = $(am_watchdog_OBJECTS)
    130 watchdog_LDADD = $(LDADD)
    131117AM_V_P = $(am__v_P_@AM_V@)
    132118am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    147133COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    148134        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    149 LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    150         $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
    151         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
    152         $(AM_CFLAGS) $(CFLAGS)
    153135AM_V_CC = $(am__v_CC_@AM_V@)
    154136am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
     
    156138am__v_CC_1 =
    157139CCLD = $(CC)
    158 LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    159         $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
    160         $(AM_LDFLAGS) $(LDFLAGS) -o $@
     140LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    161141AM_V_CCLD = $(am__v_CCLD_@AM_V@)
    162142am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
    163143am__v_CCLD_0 = @echo "  CCLD    " $@;
    164144am__v_CCLD_1 =
    165 SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
    166         $(watchdog_SOURCES)
    167 DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
    168         $(watchdog_SOURCES)
     145SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
     146DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
    169147am__can_run_installinfo = \
    170148  case $$AM_UPDATE_INFO_DIR in \
     
    194172DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    195173ACLOCAL = @ACLOCAL@
     174ALLOCA = @ALLOCA@
    196175AMTAR = @AMTAR@
    197176AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
    198 AR = @AR@
    199177AUTOCONF = @AUTOCONF@
    200178AUTOHEADER = @AUTOHEADER@
    201179AUTOMAKE = @AUTOMAKE@
    202180AWK = @AWK@
    203 BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
    204 CC = @CC@
     181BACKEND_CC = @BACKEND_CC@
     182CC = @BACKEND_CC@
    205183CCAS = @CCAS@
    206184CCASDEPMODE = @CCASDEPMODE@
    207185CCASFLAGS = @CCASFLAGS@
    208186CCDEPMODE = @CCDEPMODE@
    209 CFACC = @CFACC@
    210 CFACC_INSTALL = @CFACC_INSTALL@
    211 CFACPP = @CFACPP@
    212187CFA_BACKEND_CC = @CFA_BACKEND_CC@
    213188CFA_BINDIR = @CFA_BINDIR@
     
    217192CFA_NAME = @CFA_NAME@
    218193CFA_PREFIX = @CFA_PREFIX@
    219 CFLAGS = @CFLAGS@
     194CFLAGS = -Wall -Wextra -O2 -g
    220195CPP = @CPP@
    221196CPPFLAGS = @CPPFLAGS@
    222197CXX = @CXX@
    223 CXXCPP = @CXXCPP@
    224198CXXDEPMODE = @CXXDEPMODE@
    225199CXXFLAGS = @CXXFLAGS@
    226200CYGPATH_W = @CYGPATH_W@
    227201DEFS = @DEFS@
    228 DEMANGLER = @DEMANGLER@
    229202DEPDIR = @DEPDIR@
    230 DLLTOOL = @DLLTOOL@
    231 DRIVER_DIR = @DRIVER_DIR@
    232 DSYMUTIL = @DSYMUTIL@
    233 DUMPBIN = @DUMPBIN@
    234203ECHO_C = @ECHO_C@
    235204ECHO_N = @ECHO_N@
     
    237206EGREP = @EGREP@
    238207EXEEXT = @EXEEXT@
    239 FGREP = @FGREP@
    240208GREP = @GREP@
    241 HAS_DISTCC = @HAS_DISTCC@
    242 HOST_FLAGS = @HOST_FLAGS@
    243209INSTALL = @INSTALL@
    244210INSTALL_DATA = @INSTALL_DATA@
     
    246212INSTALL_SCRIPT = @INSTALL_SCRIPT@
    247213INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
    248 LD = @LD@
    249214LDFLAGS = @LDFLAGS@
    250215LEX = @LEX@
    251216LEXLIB = @LEXLIB@
    252217LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
    253 LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
    254 LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
    255 LIBDEMANGLE = @LIBDEMANGLE@
    256218LIBOBJS = @LIBOBJS@
    257219LIBS = @LIBS@
    258 LIBTOOL = @LIBTOOL@
    259 LIPO = @LIPO@
    260 LN_S = @LN_S@
    261220LTLIBOBJS = @LTLIBOBJS@
    262 LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
     221MACHINE_TYPE = @MACHINE_TYPE@
     222MAINT = @MAINT@
    263223MAKEINFO = @MAKEINFO@
    264 MANIFEST_TOOL = @MANIFEST_TOOL@
    265224MKDIR_P = @MKDIR_P@
    266 NM = @NM@
    267 NMEDIT = @NMEDIT@
    268 OBJDUMP = @OBJDUMP@
    269225OBJEXT = @OBJEXT@
    270 OTOOL = @OTOOL@
    271 OTOOL64 = @OTOOL64@
    272226PACKAGE = @PACKAGE@
    273227PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    279233PATH_SEPARATOR = @PATH_SEPARATOR@
    280234RANLIB = @RANLIB@
    281 SED = @SED@
    282235SET_MAKE = @SET_MAKE@
    283236SHELL = @SHELL@
    284237STRIP = @STRIP@
    285 TARGET_HOSTS = @TARGET_HOSTS@
    286238VERSION = @VERSION@
    287239YACC = @YACC@
     
    291243abs_top_builddir = @abs_top_builddir@
    292244abs_top_srcdir = @abs_top_srcdir@
    293 ac_ct_AR = @ac_ct_AR@
    294245ac_ct_CC = @ac_ct_CC@
    295246ac_ct_CXX = @ac_ct_CXX@
    296 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    297247am__include = @am__include@
    298248am__leading_dot = @am__leading_dot@
     
    341291top_builddir = @top_builddir@
    342292top_srcdir = @top_srcdir@
    343 AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
    344 ACLOCAL_AMFLAGS = -I automake
    345 AM_CFLAGS = -Wall -Wextra -O2 -g
    346293busy_SOURCES = busy.c
    347294busy_LDFLAGS = -pthread
    348295catchsig_SOURCES = catchsig.c
    349296repeat_SOURCES = repeat.c
    350 watchdog_SOURCES = watchdog.c
    351297all: all-am
    352298
    353299.SUFFIXES:
    354 .SUFFIXES: .c .lo .o .obj
    355 $(srcdir)/Makefile.in: $(srcdir)/Makefile.am  $(am__configure_deps)
     300.SUFFIXES: .c .o .obj
     301$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
    356302        @for dep in $?; do \
    357303          case '$(am__configure_deps)' in \
     
    377323        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    378324
    379 $(top_srcdir)/configure: $(am__configure_deps)
     325$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
    380326        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    381 $(ACLOCAL_M4): $(am__aclocal_m4_deps)
     327$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
    382328        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    383329$(am__aclocal_m4_deps):
    384330
    385331clean-noinstPROGRAMS:
    386         @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
    387         echo " rm -f" $$list; \
    388         rm -f $$list || exit $$?; \
    389         test -n "$(EXEEXT)" || exit 0; \
    390         list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
    391         echo " rm -f" $$list; \
    392         rm -f $$list
     332        -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
    393333
    394334busy$(EXEEXT): $(busy_OBJECTS) $(busy_DEPENDENCIES) $(EXTRA_busy_DEPENDENCIES)
     
    404344        $(AM_V_CCLD)$(LINK) $(repeat_OBJECTS) $(repeat_LDADD) $(LIBS)
    405345
    406 watchdog$(EXEEXT): $(watchdog_OBJECTS) $(watchdog_DEPENDENCIES) $(EXTRA_watchdog_DEPENDENCIES)
    407         @rm -f watchdog$(EXEEXT)
    408         $(AM_V_CCLD)$(LINK) $(watchdog_OBJECTS) $(watchdog_LDADD) $(LIBS)
    409 
    410346mostlyclean-compile:
    411347        -rm -f *.$(OBJEXT)
     
    417353@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/catchsig.Po@am__quote@
    418354@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repeat.Po@am__quote@
    419 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watchdog.Po@am__quote@
    420355
    421356.c.o:
     
    434369@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    435370@am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
    436 
    437 .c.lo:
    438 @am__fastdepCC_TRUE@    $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
    439 @am__fastdepCC_TRUE@    $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
    440 @am__fastdepCC_TRUE@    $(am__mv) $$depbase.Tpo $$depbase.Plo
    441 @AMDEP_TRUE@@am__fastdepCC_FALSE@       $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
    442 @AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    443 @am__fastdepCC_FALSE@   $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
    444 
    445 mostlyclean-libtool:
    446         -rm -f *.lo
    447 
    448 clean-libtool:
    449         -rm -rf .libs _libs
    450371
    451372ID: $(am__tagged_files)
     
    567488clean: clean-am
    568489
    569 clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
    570         mostlyclean-am
     490clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
    571491
    572492distclean: distclean-am
     
    623543mostlyclean: mostlyclean-am
    624544
    625 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
    626         mostlyclean-libtool
     545mostlyclean-am: mostlyclean-compile mostlyclean-generic
    627546
    628547pdf: pdf-am
     
    639558
    640559.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
    641         clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
    642         ctags-am distclean distclean-compile distclean-generic \
    643         distclean-libtool distclean-tags distdir dvi dvi-am html \
    644         html-am info info-am install install-am install-data \
    645         install-data-am install-dvi install-dvi-am install-exec \
    646         install-exec-am install-html install-html-am install-info \
    647         install-info-am install-man install-pdf install-pdf-am \
    648         install-ps install-ps-am install-strip installcheck \
    649         installcheck-am installdirs maintainer-clean \
     560        clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
     561        distclean-compile distclean-generic distclean-tags distdir dvi \
     562        dvi-am html html-am info info-am install install-am \
     563        install-data install-data-am install-dvi install-dvi-am \
     564        install-exec install-exec-am install-html install-html-am \
     565        install-info install-info-am install-man install-pdf \
     566        install-pdf-am install-ps install-ps-am install-strip \
     567        installcheck installcheck-am installdirs maintainer-clean \
    650568        maintainer-clean-generic mostlyclean mostlyclean-compile \
    651         mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
    652         tags tags-am uninstall uninstall-am
     569        mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
     570        uninstall-am
    653571
    654572.PRECIOUS: Makefile
  • tools/cfa.nanorc

    rb067d9b r7951100  
    22## WIP
    33
    4 syntax "cfa" "\.(c|h)fa"
     4syntax "cfa" "\.cfa"
    55
    66# Macros
     
    99# Types
    1010color green "\<(forall|trait|(o|d|f|t)type|mutex|_Bool|volatile|virtual)\>"
    11 color green "\<(float|double|bool|char|int|short|long|enum|void|auto)\>"
    12 color green "\<(static|const|extern|(un)?signed|inline)\>" "\<(sizeof)\>"
     11color green "\<(float|double|bool|char|int|short|long|sizeof|enum|void|auto)\>"
     12color green "\<(static|const|struct|union|typedef|extern|(un)?signed|inline)\>"
    1313color green "\<((s?size)|one|zero|((u_?)?int(8|16|32|64|ptr)))_t\>"
    1414
     
    1919# Control Flow Structures
    2020color brightyellow "\<(if|else|while|do|for|switch|choose|case|default)\>"
    21 color brightyellow "\<(disable|enable|waitfor|when|timeout)\>"
    2221color brightyellow "\<(try|catch(Resume)?|finally)\>"
    2322
    2423# Control Flow Statements
    2524color magenta "\<(goto|return|break|continue|fallthr(u|ough)|throw(Resume)?)\>"
    26 
    27 # Escaped Keywords, now Identifiers.
    28 color white "`\w+`"
    2925
    3026# Operator Names
  • tools/prettyprinter/Makefile.am

    rb067d9b r7951100  
    11######################## -*- Mode: Makefile-Automake -*- ######################
    2 ##
     2## 
    33## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
    44##
    55## The contents of this file are covered under the licence agreement in the
    66## file "LICENCE" distributed with Cforall.
    7 ##
    8 ## Makefile.am --
    9 ##
     7## 
     8## Makefile.am -- 
     9## 
    1010## Author           : Peter A. Buhr
    1111## Created On       : Wed Jun 28 12:07:10 2017
     
    1414## Update Count     : 20
    1515###############################################################################
    16 
    17 AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
    18 ACLOCAL_AMFLAGS  = -I automake
    1916
    2017BUILT_SOURCES = parser.hh
  • tools/prettyprinter/Makefile.in

    rb067d9b r7951100  
    9595subdir = tools/prettyprinter
    9696ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    97 am__aclocal_m4_deps = $(top_srcdir)/automake/libtool.m4 \
    98         $(top_srcdir)/automake/ltoptions.m4 \
    99         $(top_srcdir)/automake/ltsugar.m4 \
    100         $(top_srcdir)/automake/ltversion.m4 \
    101         $(top_srcdir)/automake/lt~obsolete.m4 \
    102         $(top_srcdir)/automake/cfa.m4 $(top_srcdir)/configure.ac
     97am__aclocal_m4_deps = $(top_srcdir)/configure.ac
    10398am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    10499        $(ACLOCAL_M4)
     
    117112am__DEPENDENCIES_1 =
    118113pretty_DEPENDENCIES = $(am__DEPENDENCIES_1)
    119 AM_V_lt = $(am__v_lt_@AM_V@)
    120 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
    121 am__v_lt_0 = --silent
    122 am__v_lt_1 =
    123 pretty_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
    124         $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(pretty_CXXFLAGS) \
    125         $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
     114pretty_LINK = $(CXXLD) $(pretty_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
     115        $(LDFLAGS) -o $@
    126116AM_V_P = $(am__v_P_@AM_V@)
    127117am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    140130am__depfiles_maybe = depfiles
    141131am__mv = mv -f
     132AM_V_lt = $(am__v_lt_@AM_V@)
     133am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
     134am__v_lt_0 = --silent
     135am__v_lt_1 =
    142136CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
    143137        $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
    144 LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
    145         $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
    146         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
    147         $(AM_CXXFLAGS) $(CXXFLAGS)
    148138AM_V_CXX = $(am__v_CXX_@AM_V@)
    149139am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
     
    151141am__v_CXX_1 =
    152142CXXLD = $(CXX)
    153 CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
    154         $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
    155         $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
     143CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
     144        -o $@
    156145AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
    157146am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
    158147am__v_CXXLD_0 = @echo "  CXXLD   " $@;
    159148am__v_CXXLD_1 =
     149@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
    160150LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
    161 LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
    162         $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
    163151AM_V_LEX = $(am__v_LEX_@AM_V@)
    164152am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
     
    166154am__v_LEX_1 =
    167155YLWRAP = $(top_srcdir)/automake/ylwrap
     156@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
    168157am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
    169158                   -e s/c++$$/h++/ -e s/c$$/h/
    170159YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
    171 LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
    172         $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
    173160AM_V_YACC = $(am__v_YACC_@AM_V@)
    174161am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
     
    177164COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    178165        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
    179 LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    180         $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
    181         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
    182         $(AM_CFLAGS) $(CFLAGS)
    183166AM_V_CC = $(am__v_CC_@AM_V@)
    184167am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
     
    186169am__v_CC_1 =
    187170CCLD = $(CC)
    188 LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    189         $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
    190         $(AM_LDFLAGS) $(LDFLAGS) -o $@
     171LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    191172AM_V_CCLD = $(am__v_CCLD_@AM_V@)
    192173am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
     
    223204DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    224205ACLOCAL = @ACLOCAL@
     206ALLOCA = @ALLOCA@
    225207AMTAR = @AMTAR@
    226208AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
    227 AR = @AR@
    228209AUTOCONF = @AUTOCONF@
    229210AUTOHEADER = @AUTOHEADER@
    230211AUTOMAKE = @AUTOMAKE@
    231212AWK = @AWK@
    232 BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
     213BACKEND_CC = @BACKEND_CC@
    233214CC = @CC@
    234215CCAS = @CCAS@
     
    236217CCASFLAGS = @CCASFLAGS@
    237218CCDEPMODE = @CCDEPMODE@
    238 CFACC = @CFACC@
    239 CFACC_INSTALL = @CFACC_INSTALL@
    240 CFACPP = @CFACPP@
    241219CFA_BACKEND_CC = @CFA_BACKEND_CC@
    242220CFA_BINDIR = @CFA_BINDIR@
     
    250228CPPFLAGS = @CPPFLAGS@
    251229CXX = @CXX@
    252 CXXCPP = @CXXCPP@
    253230CXXDEPMODE = @CXXDEPMODE@
    254231CXXFLAGS = @CXXFLAGS@
    255232CYGPATH_W = @CYGPATH_W@
    256233DEFS = @DEFS@
    257 DEMANGLER = @DEMANGLER@
    258234DEPDIR = @DEPDIR@
    259 DLLTOOL = @DLLTOOL@
    260 DRIVER_DIR = @DRIVER_DIR@
    261 DSYMUTIL = @DSYMUTIL@
    262 DUMPBIN = @DUMPBIN@
    263235ECHO_C = @ECHO_C@
    264236ECHO_N = @ECHO_N@
     
    266238EGREP = @EGREP@
    267239EXEEXT = @EXEEXT@
    268 FGREP = @FGREP@
    269240GREP = @GREP@
    270 HAS_DISTCC = @HAS_DISTCC@
    271 HOST_FLAGS = @HOST_FLAGS@
    272241INSTALL = @INSTALL@
    273242INSTALL_DATA = @INSTALL_DATA@
     
    275244INSTALL_SCRIPT = @INSTALL_SCRIPT@
    276245INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
    277 LD = @LD@
    278246LDFLAGS = @LDFLAGS@
    279247LEX = @LEX@
    280248LEXLIB = @LEXLIB@
    281249LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
    282 LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
    283 LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
    284 LIBDEMANGLE = @LIBDEMANGLE@
    285250LIBOBJS = @LIBOBJS@
    286251LIBS = @LIBS@
    287 LIBTOOL = @LIBTOOL@
    288 LIPO = @LIPO@
    289 LN_S = @LN_S@
    290252LTLIBOBJS = @LTLIBOBJS@
    291 LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
     253MACHINE_TYPE = @MACHINE_TYPE@
     254MAINT = @MAINT@
    292255MAKEINFO = @MAKEINFO@
    293 MANIFEST_TOOL = @MANIFEST_TOOL@
    294256MKDIR_P = @MKDIR_P@
    295 NM = @NM@
    296 NMEDIT = @NMEDIT@
    297 OBJDUMP = @OBJDUMP@
    298257OBJEXT = @OBJEXT@
    299 OTOOL = @OTOOL@
    300 OTOOL64 = @OTOOL64@
    301258PACKAGE = @PACKAGE@
    302259PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    308265PATH_SEPARATOR = @PATH_SEPARATOR@
    309266RANLIB = @RANLIB@
    310 SED = @SED@
    311267SET_MAKE = @SET_MAKE@
    312268SHELL = @SHELL@
    313269STRIP = @STRIP@
    314 TARGET_HOSTS = @TARGET_HOSTS@
    315270VERSION = @VERSION@
    316271YACC = @YACC@
     
    320275abs_top_builddir = @abs_top_builddir@
    321276abs_top_srcdir = @abs_top_srcdir@
    322 ac_ct_AR = @ac_ct_AR@
    323277ac_ct_CC = @ac_ct_CC@
    324278ac_ct_CXX = @ac_ct_CXX@
    325 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    326279am__include = @am__include@
    327280am__leading_dot = @am__leading_dot@
     
    370323top_builddir = @top_builddir@
    371324top_srcdir = @top_srcdir@
    372 AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
    373 ACLOCAL_AMFLAGS = -I automake
    374325BUILT_SOURCES = parser.hh
    375326AM_YFLAGS = -d -t -v
     
    389340
    390341.SUFFIXES:
    391 .SUFFIXES: .cc .ll .lo .o .obj .yy
    392 $(srcdir)/Makefile.in: $(srcdir)/Makefile.am  $(am__configure_deps)
     342.SUFFIXES: .cc .ll .o .obj .yy
     343$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
    393344        @for dep in $?; do \
    394345          case '$(am__configure_deps)' in \
     
    414365        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    415366
    416 $(top_srcdir)/configure: $(am__configure_deps)
     367$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
    417368        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    418 $(ACLOCAL_M4): $(am__aclocal_m4_deps)
     369$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
    419370        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    420371$(am__aclocal_m4_deps):
     
    429380        sed 's/$(EXEEXT)$$//' | \
    430381        while read p p1; do if test -f $$p \
    431          || test -f $$p1 \
    432382          ; then echo "$$p"; echo "$$p"; else :; fi; \
    433383        done | \
     
    444394            if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
    445395            test -z "$$files" || { \
    446             echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(tools_prettyprinterdir)$$dir'"; \
    447             $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(tools_prettyprinterdir)$$dir" || exit $$?; \
     396              echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(tools_prettyprinterdir)$$dir'"; \
     397              $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(tools_prettyprinterdir)$$dir" || exit $$?; \
    448398            } \
    449399        ; done
     
    461411
    462412clean-tools_prettyprinterPROGRAMS:
    463         @list='$(tools_prettyprinter_PROGRAMS)'; test -n "$$list" || exit 0; \
    464         echo " rm -f" $$list; \
    465         rm -f $$list || exit $$?; \
    466         test -n "$(EXEEXT)" || exit 0; \
    467         list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
    468         echo " rm -f" $$list; \
    469         rm -f $$list
     413        -test -z "$(tools_prettyprinter_PROGRAMS)" || rm -f $(tools_prettyprinter_PROGRAMS)
    470414parser.hh: parser.cc
    471415        @if test ! -f $@; then rm -f parser.cc; else :; fi
     
    504448@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
    505449
    506 .cc.lo:
    507 @am__fastdepCXX_TRUE@   $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
    508 @am__fastdepCXX_TRUE@   $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
    509 @am__fastdepCXX_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Plo
    510 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
    511 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    512 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
    513 
    514450pretty-lex.o: lex.cc
    515451@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pretty_CXXFLAGS) $(CXXFLAGS) -MT pretty-lex.o -MD -MP -MF $(DEPDIR)/pretty-lex.Tpo -c -o pretty-lex.o `test -f 'lex.cc' || echo '$(srcdir)/'`lex.cc
     
    587523.yy.cc:
    588524        $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
    589 
    590 mostlyclean-libtool:
    591         -rm -f *.lo
    592 
    593 clean-libtool:
    594         -rm -rf .libs _libs
    595525
    596526ID: $(am__tagged_files)
     
    722652clean: clean-am
    723653
    724 clean-am: clean-generic clean-libtool \
    725         clean-tools_prettyprinterPROGRAMS mostlyclean-am
     654clean-am: clean-generic clean-tools_prettyprinterPROGRAMS \
     655        mostlyclean-am
    726656
    727657distclean: distclean-am
     
    778708mostlyclean: mostlyclean-am
    779709
    780 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
    781         mostlyclean-libtool
     710mostlyclean-am: mostlyclean-compile mostlyclean-generic
    782711
    783712pdf: pdf-am
     
    794723
    795724.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
    796         clean-libtool clean-tools_prettyprinterPROGRAMS cscopelist-am \
    797         ctags ctags-am distclean distclean-compile distclean-generic \
    798         distclean-libtool distclean-tags distdir dvi dvi-am html \
    799         html-am info info-am install install-am install-data \
    800         install-data-am install-dvi install-dvi-am install-exec \
    801         install-exec-am install-html install-html-am install-info \
    802         install-info-am install-man install-pdf install-pdf-am \
    803         install-ps install-ps-am install-strip \
    804         install-tools_prettyprinterPROGRAMS installcheck \
     725        clean-tools_prettyprinterPROGRAMS cscopelist-am ctags ctags-am \
     726        distclean distclean-compile distclean-generic distclean-tags \
     727        distdir dvi dvi-am html html-am info info-am install \
     728        install-am install-data install-data-am install-dvi \
     729        install-dvi-am install-exec install-exec-am install-html \
     730        install-html-am install-info install-info-am install-man \
     731        install-pdf install-pdf-am install-ps install-ps-am \
     732        install-strip install-tools_prettyprinterPROGRAMS installcheck \
    805733        installcheck-am installdirs maintainer-clean \
    806734        maintainer-clean-generic mostlyclean mostlyclean-compile \
    807         mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
    808         tags tags-am uninstall uninstall-am \
    809         uninstall-tools_prettyprinterPROGRAMS
     735        mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
     736        uninstall-am uninstall-tools_prettyprinterPROGRAMS
    810737
    811738.PRECIOUS: Makefile
  • tools/stat.py

    rb067d9b r7951100  
    1111                content = f.readlines()
    1212                content = [x.strip() for x in content]
    13                 content = [float(x) for x in content]   # expect floating-point strings
    14                 content.remove(max(content))            # need at least 4 data values because
    15                 content.remove(min(content))            # the max and min values are removed
    16                 med = numpy.median(content)
    17                 avg = numpy.mean  (content)
    18                 std = numpy.std   (content)
    19                 print "median {0:.1f} avg {1:.1f} stddev {2:.2f}".format( med, avg, std )
     13                content = [int(x) for x in content]
     14                content.remove(max(content))
     15                content.remove(min(content))
     16                med = numpy.around( numpy.median(content), decimals=1)
     17                avg = numpy.around( numpy.mean  (content), decimals=2)
     18                std = numpy.around( numpy.std   (content), decimals=2)
     19                print "median {0} avg {1} stddev {2}".format( med, avg, std )
    2020
    2121
Note: See TracChangeset for help on using the changeset viewer.