Changes in / [7951100:b067d9b]


Ignore:
Files:
968 added
640 deleted
194 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    r7951100 rb067d9b  
    88config.status
    99config.log
     10config.py
    1011stamp-h1
     12libtool
    1113/Makefile
    12 src/**/Makefile
    13 tools/**/Makefile
     14**/Makefile
    1415/version
    1516
     
    2021.deps
    2122.dirstamp
    22 bin
    23 lib
    24 include
    25 share
     23/bin
     24/lib
     25/include
     26/share
     27/build
    2628*.class
    2729
    2830# src executables, for lib and bin
    29 src/driver/cc1
    30 src/driver/cfa
    31 src/driver/cfa-cpp
     31driver/as
     32driver/cfa
     33driver/cfa-cpp
     34driver/cc1
    3235
    33 src/prelude/builtins.cf
    34 src/prelude/gcc-builtins.cf
    35 src/prelude/gcc-builtins.c
    36 src/prelude/extras.cf
    37 src/prelude/bootloader.c
    38 src/libcfa/libcfa-prelude.c
     36libcfa/prelude/bootloader.c
     37libcfa/prelude/builtins.cf
     38libcfa/prelude/extras.cf
     39libcfa/prelude/gcc-builtins.cf
     40libcfa/prelude/gcc-builtins.c
     41libcfa/prelude/prelude.cfa
     42libcfa/x64-debug/
     43libcfa/x64-nodebug/
     44libcfa/x64-nolib/
     45libcfa/x86-debug/
     46libcfa/x86-nodebug/
     47libcfa/x86-nolib/
     48libcfa/arm-debug/
     49libcfa/arm-nodebug/
     50libcfa/arm-nolib/
    3951
    4052# generated by bison and lex from parser.yy and lex.ll
     
    4456src/Parser/parser.h
    4557src/Parser/parser.hh
     58src/demangler
    4659
    4760tools/prettyprinter/parser.output
  • INSTALL

    r7951100 rb067d9b  
    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 
    28 cfa-cc itself is built with the version of g++ specified by the environment
    29 variable CXX.  If CXX is unset, cfa-cc is built using the first command named
    30 'g++' in the current PATH.
  • Jenkins/FullBuild

    r7951100 rb067d9b  
    1717
    1818                                parallel (
    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 ) },
     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' ) },
    2725                                )
    2826                        }
     27                }
    2928
    30                         //Push latest changes to do-lang repo
    31                         push_build()
    32                 }
     29                promote_email(true)
    3330        }
    3431
     
    4542
    4643                //Send email to notify the failure
    47                 promote_failure_email()
     44                promote_email(false)
    4845        }
    4946
     
    5956//===========================================================================================================
    6057
    61 def trigger_build(String cc, String arch, Boolean publish) {
     58def trigger_build(String cc, String arch) {
    6259        def result = build job: 'Cforall/master',               \
    6360                parameters: [                                           \
    6461                        [$class: 'StringParameterValue',                \
    65                           name: 'pCompiler',                            \
     62                          name: 'Compiler',                             \
    6663                          value: cc],                                   \
    6764                        [$class: 'StringParameterValue',                \
    68                           name: 'pArchitecture',                        \
     65                          name: 'Architecture',                         \
    6966                          value: arch],                                 \
    7067                        [$class: 'BooleanParameterValue',               \
    71                           name: 'pRunAllTests',                         \
     68                          name: 'RunAllTests',                          \
    7269                          value: true],                                         \
    7370                        [$class: 'BooleanParameterValue',               \
    74                           name: 'pRunBenchmark',                        \
     71                          name: 'RunBenchmark',                         \
    7572                          value: true],                                         \
    7673                        [$class: 'BooleanParameterValue',               \
    77                           name: 'pBuildDocumentation',          \
     74                          name: 'BuildDocumentation',           \
    7875                          value: true],                                         \
    7976                        [$class: 'BooleanParameterValue',               \
    80                           name: 'pPublish',                             \
    81                           value: publish],                                      \
     77                          name: 'Publish',                              \
     78                          value: true],                                 \
    8279                        [$class: 'BooleanParameterValue',               \
    83                           name: 'pSilent',                              \
     80                          name: 'Silent',                               \
    8481                          value: true],                                         \
    8582                ],                                                              \
     
    8986
    9087        if(result.result != 'SUCCESS') {
    91                 sh("wget -q -O - ${result.absoluteUrl}/consoleText")
     88                sh("wget -q -O - http://localhost:8084/jenkins/job/Cforall/job/master/${result.number}/consoleText")
    9289                error(result.result)
    93         }
    94 }
    95 
    96 def 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')
    12190        }
    12291}
     
    143112
    144113//Email notification on a full build failure
    145 def promote_failure_email() {
     114def promote_email(boolean success) {
    146115        echo('notifying users')
     116
     117        def result = success ? "PROMOTE - SUCCESS" : "PROMOTE - FAILURE"
    147118
    148119        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
    149120        //Configurations for email format
    150         def email_subject = "[cforall git][PROMOTE - FAILURE]"
    151         def email_body = """This is an automated email from the Jenkins build machine. It was
    152 generated because of a git hooks/post-receive script following
    153 a ref change was pushed to the repository containing
    154 the project "UNNAMED PROJECT".
     121        def email_subject = "[cforall git][${result}]"
     122        def email_body = """<p>This is an automated email from the Jenkins build machine. It was
     123generated following the result of the C\u2200 nightly build.</p>
    155124
    156 Check console output at ${env.BUILD_URL} to view the results.
     125<p>Check console output at ${env.BUILD_URL} to view the results.</p>
    157126
    158 - Status --------------------------------------------------------------
     127<p>- Status --------------------------------------------------------------</p>
    159128
    160 PROMOTE FAILURE
     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>
    161137"""
    162138
     
    164140
    165141        //send email notification
    166         emailext body: email_body, subject: email_subject, to: email_to, attachLog: true
     142        emailext body: email_body, subject: email_subject, to: email_to, attachLog: !success
    167143}
  • Jenkins/TestRegen

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

    r7951100 rb067d9b  
    11#!groovy
    22
     3import groovy.transform.Field
     4
     5// For skipping stages
     6import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
     7
    38//===========================================================================================================
    49// Main loop of the compilation
    510//===========================================================================================================
    6 node ('master'){
    7 
    8         boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox"
     11
     12node('master') {
     13        // Globals
     14        BuildDir  = pwd tmp: true
     15        SrcDir    = pwd tmp: false
     16        Settings  = null
     17        StageName = ''
     18
     19        // Local variables
    920        def err = null
    1021        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
    2322
    2423        currentBuild.result = "SUCCESS"
     
    2827                wrap([$class: 'TimestamperBuildWrapper']) {
    2928
    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)
     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
    5153                }
    5254        }
     
    5860                err = caughtError
    5961
     62                echo err.toString()
     63
    6064                //An error has occured, the build log is relevent
    6165                log_needed = true
    6266
    6367                //Store the result of the build log
    64                 currentBuild.result = "${stage_name} FAILURE".trim()
     68                currentBuild.result = "${StageName} FAILURE".trim()
    6569        }
    6670
    6771        finally {
    6872                //Send email with final results if this is not a full build
    69                 if( do_sendemail && !bIsSandbox ) {
    70                         echo 'Notifying users of result'
    71                         email(currentBuild.result, log_needed)
    72                 }
     73                email(log_needed)
    7374
    7475                echo 'Build Completed'
     
    8081        }
    8182}
     83//===========================================================================================================
     84// Main compilation routines
     85//===========================================================================================================
     86def 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
     96def 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
     107def 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
     156def 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
     182def 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
     191def 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
     203def 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
     227def SplitLines(String text) {
     228        def list = []
     229
     230        text.eachLine {
     231                list += it
     232        }
     233
     234        return list
     235}
     236
     237def 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>
     265The 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>
     283Summary of changes:
     284${gitDiff}
     285</pre>
     286"""
     287}
     288
     289//Standard build email notification
     290def 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
     298generated because of a git hooks/post-receive script following
     299a 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}
    82313
    83314//===========================================================================================================
    84315// Helper classes/variables/routines
    85316//===========================================================================================================
    86 //Helper routine to collect information about the git history
    87 def 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]
     317//Description of a compiler (Must be serializable since pipelines are persistent)
     318class 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)
     331class 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
     343class 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 })
     398Architecture            : ${ this.Architecture.name }
     399Arc Flags               : ${ this.Architecture.flags }
     400Run All Tests           : ${ this.RunAllTests.toString() }
     401Run Benchmark           : ${ this.RunBenchmark.toString() }
     402Build Documentation     : ${ this.BuildDocumentation.toString() }
     403Publish                 : ${ this.Publish.toString() }
     404Silent                  : ${ this.Silent.toString() }
     405"""
     406
     407                this.GitNewRef = ''
     408                this.GitOldRef = ''
     409        }
     410}
     411
     412class 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        }
    101422}
    102423
    103424def prepare_build() {
     425        // prepare the properties
    104426        properties ([                                                                                                   \
    105427                [$class: 'ParametersDefinitionProperty',                                                                \
     
    107429                                [$class: 'ChoiceParameterDefinition',                                           \
    108430                                        description: 'Which compiler to use',                                   \
    109                                         name: 'pCompiler',                                                              \
     431                                        name: 'Compiler',                                                                       \
    110432                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
    111433                                        defaultValue: 'gcc-6',                                                          \
     
    113435                                [$class: 'ChoiceParameterDefinition',                                           \
    114436                                        description: 'The target architecture',                                 \
    115                                         name: 'pArchitecture',                                                          \
     437                                        name: 'Architecture',                                                           \
    116438                                        choices: 'x64\nx86',                                                            \
    117439                                        defaultValue: 'x64',                                                            \
     
    119441                                [$class: 'BooleanParameterDefinition',                                                  \
    120442                                        description: 'If false, only the quick test suite is ran',              \
    121                                         name: 'pRunAllTests',                                                           \
     443                                        name: 'RunAllTests',                                                            \
    122444                                        defaultValue: false,                                                            \
    123445                                ],                                                                                              \
    124446                                [$class: 'BooleanParameterDefinition',                                                  \
    125447                                        description: 'If true, jenkins also runs benchmarks',           \
    126                                         name: 'pRunBenchmark',                                                          \
    127                                         defaultValue: true,                                                             \
     448                                        name: 'RunBenchmark',                                                           \
     449                                        defaultValue: false,                                                            \
    128450                                ],                                                                                              \
    129451                                [$class: 'BooleanParameterDefinition',                                                  \
    130452                                        description: 'If true, jenkins also builds documentation',              \
    131                                         name: 'pBuildDocumentation',                                                    \
     453                                        name: 'BuildDocumentation',                                                     \
    132454                                        defaultValue: true,                                                             \
    133455                                ],                                                                                              \
    134456                                [$class: 'BooleanParameterDefinition',                                                  \
    135457                                        description: 'If true, jenkins also publishes results',                 \
    136                                         name: 'pPublish',                                                               \
     458                                        name: 'Publish',                                                                        \
    137459                                        defaultValue: false,                                                            \
    138460                                ],                                                                                              \
    139461                                [$class: 'BooleanParameterDefinition',                                                  \
    140462                                        description: 'If true, jenkins will not send emails',           \
    141                                         name: 'pSilent',                                                                        \
     463                                        name: 'Silent',                                                                         \
    142464                                        defaultValue: false,                                                            \
    143465                                ],                                                                                              \
     
    145467                ]])
    146468
    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})
    158 Architecture            : ${arch_name}
    159 Arc Flags               : ${architecture}
    160 Run All Tests           : ${ pRunAllTests.toString() }
    161 Run Benchmark           : ${ pRunBenchmark.toString() }
    162 Build Documentation     : ${ pBuildDocumentation.toString() }
    163 Publish                 : ${ pPublish.toString() }
    164 Silent                  : ${ pSilent.toString() }
    165 """
    166 
    167         collect_git_info()
    168 }
    169 
    170 def build_stage(String name, Closure block ) {
    171         stage_name = name
    172         stage(name, block)
    173 }
    174 
    175 def notify_server(int wait) {
    176         sh """curl --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
    177         return
     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
     480def 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        }
    178488}
    179489
     
    186496        catch (Exception caughtError) {
    187497                err = caughtError //rethrow error later
    188                 sh 'cat *.log'
     498                sh 'cat build/*.log'
    189499        }
    190500        finally {
     
    193503}
    194504
    195 //Description of a compiler (Must be serializable since pipelines are persistent)
    196 class 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 
    208 def 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 
    227 def 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
    244 def 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 
    257 def 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 
    278 def 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 
    292 def 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 
    302 def 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 
    310 def 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 
    325 def 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
    339 def 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
    359 generated because of a git hooks/post-receive script following
    360 a ref change was pushed to the repository containing
    361 the project "UNNAMED PROJECT".
    362 
    363 The branch ${env.BRANCH_NAME} has been updated.
    364    via  ${gitRefOldValue} (commit)
    365   from  ${gitRefNewValue} (commit)
    366 
    367 Check console output at ${env.BUILD_URL} to view the results.
    368 
    369 - Status --------------------------------------------------------------
    370 
    371 BUILD# ${env.BUILD_NUMBER} - ${status}
    372 
    373 - Log -----------------------------------------------------------------
    374 ${gitLog}
    375 -----------------------------------------------------------------------
    376 Summary 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 }
     505def 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}
  • Makefile.am

    r7951100 rb067d9b  
    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 : Wed Dec 14 14:20:48 2016
    14 ## Update Count     : 15
     13## Last Modified On : Sat Feb  2 16:54:42 2019
     14## Update Count     : 21
    1515###############################################################################
    1616
    17 AUTOMAKE_OPTIONS = foreign              # do not require all the GNU file names
    18 SUBDIRS = src/driver src src/prelude src/libcfa # order important, src before prelude because cfa-cpp used to build prelude
    19 EXTRA_DIST = Docs                       # non-source files
    20 BACKEND_CC = @BACKEND_CC@               # C compiler used to compile Cforall programs, versus C++ compiler used to build cfa command
     17AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
     18ACLOCAL_AMFLAGS  = -I automake
    2119
    22 MAINTAINERCLEANFILES = lib/* bin/* src/examples/.deps/* src/tests/.deps/* src/tests/.out/*
     20MAINTAINERCLEANFILES = lib/* bin/* tests/.deps/* tests/.out/* # order important
     21
     22SUBDIRS = 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
     31noinst_DATA = @LIBCFA_TARGET_MAKEFILES@
    2332
    2433man1_MANS = doc/man/cfa.1
     34
     35debug=yes
     36check:
     37        $(MAKE) -C tests all-tests installed=no debug=${debug}
     38
     39installcheck:
     40        $(MAKE) -C tests all-tests installed=yes debug=${debug}
     41
     42configure-libcfa: @LIBCFA_TARGET_MAKEFILES@
     43        @true
     44
     45status: @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

    r7951100 rb067d9b  
    1717######################## -*- Mode: Makefile-Automake -*- ######################
    1818###############################################################################
     19
    1920VPATH = @srcdir@
    2021am__is_gnu_make = { \
     
    9394subdir = .
    9495ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    95 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
     96am__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
    96102am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    97103        $(ACLOCAL_M4)
     
    162168NROFF = nroff
    163169MANS = $(man1_MANS)
     170DATA = $(noinst_DATA)
    164171RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
    165172  distclean-recursive maintainer-clean-recursive
     
    170177AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
    171178        cscope distdir dist dist-all distcheck
    172 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
    173         $(LISP)config.h.in
     179am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
    174180# Read a list of newline-separated strings from the standard input,
    175181# and print each of them once, without duplicates.  Input order is
     
    192198CSCOPE = cscope
    193199DIST_SUBDIRS = $(SUBDIRS)
    194 am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
    195         $(top_srcdir)/automake/compile \
     200am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/automake/compile \
    196201        $(top_srcdir)/automake/config.guess \
    197202        $(top_srcdir)/automake/config.sub \
    198203        $(top_srcdir)/automake/install-sh \
    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
     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
    202209DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    203210distdir = $(PACKAGE)-$(VERSION)
     
    243250distcleancheck_listfiles = find . -type f -print
    244251ACLOCAL = @ACLOCAL@
    245 ALLOCA = @ALLOCA@
    246252AMTAR = @AMTAR@
    247253AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
     254AR = @AR@
    248255AUTOCONF = @AUTOCONF@
    249256AUTOHEADER = @AUTOHEADER@
    250257AUTOMAKE = @AUTOMAKE@
    251258AWK = @AWK@
    252 BACKEND_CC = @BACKEND_CC@               # C compiler used to compile Cforall programs, versus C++ compiler used to build cfa command
     259BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
    253260CC = @CC@
    254261CCAS = @CCAS@
     
    256263CCASFLAGS = @CCASFLAGS@
    257264CCDEPMODE = @CCDEPMODE@
     265CFACC = @CFACC@
     266CFACC_INSTALL = @CFACC_INSTALL@
     267CFACPP = @CFACPP@
    258268CFA_BACKEND_CC = @CFA_BACKEND_CC@
    259269CFA_BINDIR = @CFA_BINDIR@
     
    267277CPPFLAGS = @CPPFLAGS@
    268278CXX = @CXX@
     279CXXCPP = @CXXCPP@
    269280CXXDEPMODE = @CXXDEPMODE@
    270281CXXFLAGS = @CXXFLAGS@
    271282CYGPATH_W = @CYGPATH_W@
    272283DEFS = @DEFS@
     284DEMANGLER = @DEMANGLER@
    273285DEPDIR = @DEPDIR@
     286DLLTOOL = @DLLTOOL@
     287DRIVER_DIR = @DRIVER_DIR@
     288DSYMUTIL = @DSYMUTIL@
     289DUMPBIN = @DUMPBIN@
    274290ECHO_C = @ECHO_C@
    275291ECHO_N = @ECHO_N@
     
    277293EGREP = @EGREP@
    278294EXEEXT = @EXEEXT@
     295FGREP = @FGREP@
    279296GREP = @GREP@
     297HAS_DISTCC = @HAS_DISTCC@
     298HOST_FLAGS = @HOST_FLAGS@
    280299INSTALL = @INSTALL@
    281300INSTALL_DATA = @INSTALL_DATA@
     
    283302INSTALL_SCRIPT = @INSTALL_SCRIPT@
    284303INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
     304LD = @LD@
    285305LDFLAGS = @LDFLAGS@
    286306LEX = @LEX@
    287307LEXLIB = @LEXLIB@
    288308LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
     309LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
     310LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
     311LIBDEMANGLE = @LIBDEMANGLE@
    289312LIBOBJS = @LIBOBJS@
    290313LIBS = @LIBS@
     314LIBTOOL = @LIBTOOL@
     315LIPO = @LIPO@
     316LN_S = @LN_S@
    291317LTLIBOBJS = @LTLIBOBJS@
    292 MACHINE_TYPE = @MACHINE_TYPE@
    293 MAINT = @MAINT@
     318LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
    294319MAKEINFO = @MAKEINFO@
     320MANIFEST_TOOL = @MANIFEST_TOOL@
    295321MKDIR_P = @MKDIR_P@
     322NM = @NM@
     323NMEDIT = @NMEDIT@
     324OBJDUMP = @OBJDUMP@
    296325OBJEXT = @OBJEXT@
     326OTOOL = @OTOOL@
     327OTOOL64 = @OTOOL64@
    297328PACKAGE = @PACKAGE@
    298329PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    304335PATH_SEPARATOR = @PATH_SEPARATOR@
    305336RANLIB = @RANLIB@
     337SED = @SED@
    306338SET_MAKE = @SET_MAKE@
    307339SHELL = @SHELL@
    308340STRIP = @STRIP@
     341TARGET_HOSTS = @TARGET_HOSTS@
    309342VERSION = @VERSION@
    310343YACC = @YACC@
     
    314347abs_top_builddir = @abs_top_builddir@
    315348abs_top_srcdir = @abs_top_srcdir@
     349ac_ct_AR = @ac_ct_AR@
    316350ac_ct_CC = @ac_ct_CC@
    317351ac_ct_CXX = @ac_ct_CXX@
     352ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    318353am__include = @am__include@
    319354am__leading_dot = @am__leading_dot@
     
    362397top_builddir = @top_builddir@
    363398top_srcdir = @top_srcdir@
    364 AUTOMAKE_OPTIONS = foreign              # do not require all the GNU file names
    365 SUBDIRS = src/driver src src/prelude src/libcfa # order important, src before prelude because cfa-cpp used to build prelude
    366 EXTRA_DIST = Docs                       # non-source files
    367 MAINTAINERCLEANFILES = lib/* bin/* src/examples/.deps/* src/tests/.deps/* src/tests/.out/*
     399AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
     400ACLOCAL_AMFLAGS = -I automake
     401MAINTAINERCLEANFILES = lib/* bin/* tests/.deps/* tests/.out/* # order important
     402SUBDIRS = driver src . @LIBCFA_TARGET_DIRS@
     403noinst_DATA = @LIBCFA_TARGET_MAKEFILES@
    368404man1_MANS = doc/man/cfa.1
     405debug = yes
    369406all: config.h
    370407        $(MAKE) $(AM_MAKEFLAGS) all-recursive
     
    373410am--refresh: Makefile
    374411        @:
    375 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
     412$(srcdir)/Makefile.in: $(srcdir)/Makefile.am  $(am__configure_deps)
    376413        @for dep in $?; do \
    377414          case '$(am__configure_deps)' in \
     
    399436        $(SHELL) ./config.status --recheck
    400437
    401 $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
     438$(top_srcdir)/configure: $(am__configure_deps)
    402439        $(am__cd) $(srcdir) && $(AUTOCONF)
    403 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
     440$(ACLOCAL_M4): $(am__aclocal_m4_deps)
    404441        $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
    405442$(am__aclocal_m4_deps):
     
    409446        @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
    410447
    411 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
     448stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
    412449        @rm -f stamp-h1
    413450        cd $(top_builddir) && $(SHELL) ./config.status config.h
    414 $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
     451$(top_srcdir)/src/config.h.in: $(am__configure_deps)
    415452        ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
    416453        rm -f stamp-h1
     
    419456distclean-hdr:
    420457        -rm -f config.h stamp-h1
     458
     459mostlyclean-libtool:
     460        -rm -f *.lo
     461
     462clean-libtool:
     463        -rm -rf .libs _libs
     464
     465distclean-libtool:
     466        -rm -f libtool config.lt
    421467install-man1: $(man1_MANS)
    422468        @$(NORMAL_INSTALL)
     
    757803check-am: all-am
    758804check: check-recursive
    759 all-am: Makefile $(MANS) config.h
     805all-am: Makefile $(MANS) $(DATA) config.h
    760806installdirs: installdirs-recursive
    761807installdirs-am:
     
    770816install-am: all-am
    771817        @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
    772 
    773 installcheck: installcheck-recursive
    774818install-strip:
    775819        if test -z '$(STRIP)'; then \
     
    796840clean: clean-recursive
    797841
    798 clean-am: clean-generic mostlyclean-am
     842clean-am: clean-generic clean-libtool mostlyclean-am
    799843
    800844distclean: distclean-recursive
    801845        -rm -f $(am__CONFIG_DISTCLEAN_FILES)
    802846        -rm -f Makefile
    803 distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
     847distclean-am: clean-am distclean-generic distclean-hdr \
     848        distclean-libtool distclean-tags
    804849
    805850dvi: dvi-recursive
     
    851896mostlyclean: mostlyclean-recursive
    852897
    853 mostlyclean-am: mostlyclean-generic
     898mostlyclean-am: mostlyclean-generic mostlyclean-libtool
    854899
    855900pdf: pdf-recursive
     
    869914.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
    870915        am--refresh check check-am clean clean-cscope clean-generic \
    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
     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
    884930
    885931.PRECIOUS: Makefile
    886932
     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)
     940check:
     941        $(MAKE) -C tests all-tests installed=no debug=${debug}
     942
     943installcheck:
     944        $(MAKE) -C tests all-tests installed=yes debug=${debug}
     945
     946configure-libcfa: @LIBCFA_TARGET_MAKEFILES@
     947        @true
     948
     949status: @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"
    887953
    888954# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • aclocal.m4

    r7951100 rb067d9b  
    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.
    144 m4_define([_AM_COND_IF])
    145 m4_define([_AM_COND_ELSE])
    146 m4_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).
    153 AC_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
    157 if test -z "$$1_TRUE"; then :
    158   m4_n([$2])[]dnl
    159 m4_ifval([$3],
    160 [_AM_COND_ELSE([$1])dnl
    161 else
    162   $3
    163 ])dnl
    164 _AM_COND_ENDIF([$1])dnl
    165 fi[]dnl
    166129])
    167130
     
    703666AC_SUBST([am__leading_dot])])
    704667
    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.
    720 AC_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])])
    726 AC_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 
    741668# Check to see how 'make' treats includes.                  -*- Autoconf -*-
    742669
     
    12441171]) # _AM_PROG_TAR
    12451172
     1173m4_include([automake/libtool.m4])
     1174m4_include([automake/ltoptions.m4])
     1175m4_include([automake/ltsugar.m4])
     1176m4_include([automake/ltversion.m4])
     1177m4_include([automake/lt~obsolete.m4])
  • automake/compile

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #! /bin/sh
    2 # Wrapper for compilers which do not understand '-c -o'.
    3 
    4 scriptversion=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 
    31 nl='
    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.
    36 IFS=" ""        $nl"
    37 
    38 file_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.
    45 func_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
    83 func_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
    96 func_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
    130 func_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 
    232 eat=
    233 
    234 case $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
    241 Usage: compile [--help] [--version] PROGRAM [ARGS]
    242 
    243 Wrapper for compilers which do not understand '-c -o'.
    244 Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
    245 arguments, and rename the output as expected.
    246 
    247 If you are trying to build a whole package this is not the
    248 right script to run: please start by reading the file 'INSTALL'.
    249 
    250 Report bugs to <bug-automake@gnu.org>.
    251 EOF
    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     ;;
    261 esac
    262 
    263 ofile=
    264 cfile=
    265 
    266 for arg
    267 do
    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
    298 done
    299 
    300 if 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 "$@"
    307 fi
    308 
    309 # Name of file we expect compiler to create.
    310 cofile=`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.
    316 lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
    317 while true; do
    318   if mkdir "$lockdir" >/dev/null 2>&1; then
    319     break
    320   fi
    321   sleep 1
    322 done
    323 # FIXME: race condition here if user kills between mkdir and trap.
    324 trap "rmdir '$lockdir'; exit 1" 1 2 15
    325 
    326 # Run the compile.
    327 "$@"
    328 ret=$?
    329 
    330 if test -f "$cofile"; then
    331   test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
    332 elif test -f "${cofile}bj"; then
    333   test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
    334 fi
    335 
    336 rmdir "$lockdir"
    337 exit $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:
     1/usr/share/automake-1.15/compile
  • automake/config.guess

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #! /bin/sh
    2 # Attempt to guess a canonical system name.
    3 #   Copyright 1992-2015 Free Software Foundation, Inc.
    4 
    5 timestamp='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 
    35 me=`echo "$0" | sed -e 's,.*/,,'`
    36 
    37 usage="\
    38 Usage: $0 [OPTION]
    39 
    40 Output the configuration name of the system \`$me' is run on.
    41 
    42 Operation 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 
    47 Report bugs and patches to <config-patches@gnu.org>."
    48 
    49 version="\
    50 GNU config.guess ($timestamp)
    51 
    52 Originally written by Per Bothner.
    53 Copyright 1992-2015 Free Software Foundation, Inc.
    54 
    55 This is free software; see the source for copying conditions.  There is NO
    56 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
    57 
    58 help="
    59 Try \`$me --help' for more information."
    60 
    61 # Parse command line
    62 while 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
    80 done
    81 
    82 if test $# != 0; then
    83   echo "$me: too many arguments$help" >&2
    84   exit 1
    85 fi
    86 
    87 trap '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 
    99 set_cc_for_build='
    100 trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
    101 trap "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 ; } ;
    107 dummy=$tmp/dummy ;
    108 tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
    109 case $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 ;;
    122 esac ; 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)
    126 if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
    127         PATH=$PATH:/.attbin ; export PATH
    128 fi
    129 
    130 UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
    131 UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
    132 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
    133 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
    134 
    135 case "${UNAME_SYSTEM}" in
    136 Linux|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         ;;
    154 esac
    155 
    156 # Note: order is significant - the case branches are not exclusive.
    157 
    158 case "${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         }
    492 EOF
    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                         }
    579 EOF
    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                 }
    682 EOF
    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         }
    740 EOF
    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
    989 EOF
    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 ;;
    1393 esac
    1394 
    1395 cat >&2 <<EOF
    1396 $0: unable to guess system type
    1397 
    1398 This script, last modified $timestamp, has failed to recognize
    1399 the operating system you are using. It is advised that you
    1400 download 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
    1403 and
    1404   http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
    1405 
    1406 If the version you run ($0) is already up to date, please
    1407 send the following data and any information you think might be
    1408 pertinent to <config-patches@gnu.org> in order to provide the needed
    1409 information to handle your system.
    1410 
    1411 config.guess timestamp = $timestamp
    1412 
    1413 uname -m = `(uname -m) 2>/dev/null || echo unknown`
    1414 uname -r = `(uname -r) 2>/dev/null || echo unknown`
    1415 uname -s = `(uname -s) 2>/dev/null || echo unknown`
    1416 uname -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 
    1421 hostinfo               = `(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 
    1428 UNAME_MACHINE = ${UNAME_MACHINE}
    1429 UNAME_RELEASE = ${UNAME_RELEASE}
    1430 UNAME_SYSTEM  = ${UNAME_SYSTEM}
    1431 UNAME_VERSION = ${UNAME_VERSION}
    1432 EOF
    1433 
    1434 exit 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:
     1/usr/share/automake-1.15/config.guess
  • automake/config.sub

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #! /bin/sh
    2 # Configuration validation subroutine script.
    3 #   Copyright 1992-2015 Free Software Foundation, Inc.
    4 
    5 timestamp='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 
    53 me=`echo "$0" | sed -e 's,.*/,,'`
    54 
    55 usage="\
    56 Usage: $0 [OPTION] CPU-MFR-OPSYS
    57        $0 [OPTION] ALIAS
    58 
    59 Canonicalize a configuration name.
    60 
    61 Operation 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 
    66 Report bugs and patches to <config-patches@gnu.org>."
    67 
    68 version="\
    69 GNU config.sub ($timestamp)
    70 
    71 Copyright 1992-2015 Free Software Foundation, Inc.
    72 
    73 This is free software; see the source for copying conditions.  There is NO
    74 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
    75 
    76 help="
    77 Try \`$me --help' for more information."
    78 
    79 # Parse command line
    80 while 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
    104 done
    105 
    106 case $# 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;;
    112 esac
    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.
    116 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
    117 case $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     ;;
    136 esac
    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.
    142 case $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                 ;;
    243 esac
    244 
    245 # Decode aliases for certain CPU-COMPANY combinations.
    246 case $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                 ;;
    1333 esac
    1334 
    1335 # Here we canonicalize certain aliases for manufacturers.
    1336 case $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                 ;;
    1345 esac
    1346 
    1347 # Decode manufacturer-specific aliases for certain operating systems.
    1348 
    1349 if [ x"$os" != x"" ]
    1350 then
    1351 case $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                 ;;
    1542 esac
    1543 else
    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 
    1555 case $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                 ;;
    1728 esac
    1729 fi
    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.
    1733 vendor=unknown
    1734 case $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                 ;;
    1803 esac
    1804 
    1805 echo $basic_machine$os
    1806 exit
    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:
     1/usr/share/automake-1.15/config.sub
  • automake/depcomp

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #! /bin/sh
    2 # depcomp - compile a program generating dependencies as side-effects
    3 
    4 scriptversion=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 
    28 case $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
    35 Usage: depcomp [--help] [--version] PROGRAM [ARGS]
    36 
    37 Run PROGRAMS ARGS to compile a file, generating dependencies
    38 as side-effects.
    39 
    40 Environment 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 
    49 Report bugs to <bug-automake@gnu.org>.
    50 EOF
    51     exit $?
    52     ;;
    53   -v | --v*)
    54     echo "depcomp $scriptversion"
    55     exit $?
    56     ;;
    57 esac
    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.
    62 set_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'.
    72 set_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.
    80 make_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.
    87 aix_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.
    108 tab='   '
    109 # A newline character.
    110 nl='
    111 '
    112 # Character ranges might be problematic outside the C locale.
    113 # These definitions help.
    114 upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
    115 lower=abcdefghijklmnopqrstuvwxyz
    116 digits=0123456789
    117 alpha=${upper}${lower}
    118 
    119 if 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
    122 fi
    123 
    124 # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
    125 depfile=${depfile-`echo "$object" |
    126   sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
    127 tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
    128 
    129 rm -f "$tmpdepfile"
    130 
    131 # Avoid interferences from the environment.
    132 gccflag= 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.
    138 if test "$depmode" = hp; then
    139   # HP compiler uses -M and no extra arg.
    140   gccflag=-M
    141   depmode=gcc
    142 fi
    143 
    144 if test "$depmode" = dashXmstdout; then
    145   # This is just like dashmstdout with a different argument.
    146   dashmflag=-xM
    147   depmode=dashmstdout
    148 fi
    149 
    150 cygpath_u="cygpath -u -f -"
    151 if 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
    157 fi
    158 
    159 if 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
    165 fi
    166 
    167 if 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
    171 fi
    172 
    173 case "$depmode" in
    174 gcc3)
    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 
    200 gcc)
    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 
    247 hp)
    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 
    254 sgi)
    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 
    289 xlc)
    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 
    296 aix)
    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 
    328 tcc)
    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.
    363 pgcc)
    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 
    435 hp2)
    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 
    478 tru64)
    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 
    520 msvc7)
    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 '
    546 s/ /\\ /g
    547 s/\(.*\)/'"$tab"'\1 \\/p
    548 s/.\(.*\) \\/\1:/
    549 H
    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 
    559 msvc7msys)
    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 
    570 dashmstdout)
    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 
    618 dashXmstdout)
    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 
    624 makedepend)
    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 
    676 cpp)
    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 
    719 msvisualcpp)
    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 
    764 msvcmsys)
    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 
    771 none)
    772   exec "$@"
    773   ;;
    774 
    775 *)
    776   echo "Unknown depmode $depmode" 1>&2
    777   exit 1
    778   ;;
    779 esac
    780 
    781 exit 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:
     1/usr/share/automake-1.15/depcomp
  • automake/install-sh

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #!/bin/sh
    2 # install - install a program, script, or datafile
    3 
    4 scriptversion=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 
    44 tab='   '
    45 nl='
    46 '
    47 IFS=" $tab$nl"
    48 
    49 # Set DOITPROG to "echo" to test this script.
    50 
    51 doit=${DOITPROG-}
    52 doit_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 
    57 chgrpprog=${CHGRPPROG-chgrp}
    58 chmodprog=${CHMODPROG-chmod}
    59 chownprog=${CHOWNPROG-chown}
    60 cmpprog=${CMPPROG-cmp}
    61 cpprog=${CPPROG-cp}
    62 mkdirprog=${MKDIRPROG-mkdir}
    63 mvprog=${MVPROG-mv}
    64 rmprog=${RMPROG-rm}
    65 stripprog=${STRIPPROG-strip}
    66 
    67 posix_mkdir=
    68 
    69 # Desired mode of installed file.
    70 mode=0755
    71 
    72 chgrpcmd=
    73 chmodcmd=$chmodprog
    74 chowncmd=
    75 mvcmd=$mvprog
    76 rmcmd="$rmprog -f"
    77 stripcmd=
    78 
    79 src=
    80 dst=
    81 dir_arg=
    82 dst_arg=
    83 
    84 copy_on_change=false
    85 is_target_a_directory=possibly
    86 
    87 usage="\
    88 Usage: $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 
    93 In the 1st form, copy SRCFILE to DSTFILE.
    94 In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
    95 In the 4th, create DIRECTORIES.
    96 
    97 Options:
    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 
    111 Environment variables override the default commands:
    112   CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
    113   RMPROG STRIPPROG
    114 "
    115 
    116 while 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
    164 done
    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 
    169 if 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
    174 fi
    175 
    176 if 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
    194 fi
    195 
    196 if 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
    204 fi
    205 
    206 if 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
    213 fi
    214 
    215 if 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
    244 fi
    245 
    246 for src
    247 do
    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
    500 done
    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:
     1/usr/share/automake-1.15/install-sh
  • automake/missing

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #! /bin/sh
    2 # Common wrapper for a few potentially missing GNU programs.
    3 
    4 scriptversion=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 
    27 if test $# -eq 0; then
    28   echo 1>&2 "Try '$0 --help' for more information"
    29   exit 1
    30 fi
    31 
    32 case $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 
    49 Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
    50 to PROGRAM being missing or too old.
    51 
    52 Options:
    53   -h, --help      display this help and exit
    54   -v, --version   output version information and exit
    55 
    56 Supported PROGRAM values:
    57   aclocal   autoconf  autoheader   autom4te  automake  makeinfo
    58   bison     yacc      flex         lex       help2man
    59 
    60 Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
    61 'g' are ignored when checking the name.
    62 
    63 Send 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 
    78 esac
    79 
    80 # Run the given program, remember its exit status.
    81 "$@"; st=$?
    82 
    83 # If it succeeded, we are done.
    84 test $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.
    89 case $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.
    94 if test $st -eq 63; then
    95   msg="probably too old"
    96 elif test $st -eq 127; then
    97   # Program was missing.
    98   msg="missing on your system"
    99 else
    100   # Program was found and executed, but failed.  Give up.
    101   exit $st
    102 fi
    103 
    104 perl_URL=http://www.perl.org/
    105 flex_URL=http://flex.sourceforge.net/
    106 gnu_software_URL=http://www.gnu.org/software
    107 
    108 program_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 
    129 give_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 
    202 give_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).
    207 exit $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:
     1/usr/share/automake-1.15/missing
  • automake/test-driver

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #! /bin/sh
    2 # test-driver - basic testsuite driver script.
    3 
    4 scriptversion=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.
    32 set -u
    33 
    34 usage_error ()
    35 {
    36   echo "$0: $*" >&2
    37   print_usage >&2
    38   exit 2
    39 }
    40 
    41 print_usage ()
    42 {
    43   cat <<END
    44 Usage:
    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]
    49 The '--test-name', '--log-file' and '--trs-file' options are mandatory.
    50 END
    51 }
    52 
    53 test_name= # Used for reporting.
    54 log_file=  # Where to save the output of the test script.
    55 trs_file=  # Where to save the metadata of the test run.
    56 expect_failure=no
    57 color_tests=no
    58 enable_hard_errors=yes
    59 while 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
    74 done
    75 
    76 missing_opts=
    77 test x"$test_name" = x && missing_opts="$missing_opts --test-name"
    78 test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
    79 test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
    80 if test x"$missing_opts" != x; then
    81   usage_error "the following mandatory options are missing:$missing_opts"
    82 fi
    83 
    84 if test $# -eq 0; then
    85   usage_error "missing argument"
    86 fi
    87 
    88 if 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.
    96 else
    97   red= grn= lgn= blu= mgn= std=
    98 fi
    99 
    100 do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
    101 trap "st=129; $do_exit" 1
    102 trap "st=130; $do_exit" 2
    103 trap "st=141; $do_exit" 13
    104 trap "st=143; $do_exit" 15
    105 
    106 # Test script is run here.
    107 "$@" >$log_file 2>&1
    108 estatus=$?
    109 
    110 if test $enable_hard_errors = no && test $estatus -eq 99; then
    111   tweaked_estatus=1
    112 else
    113   tweaked_estatus=$estatus
    114 fi
    115 
    116 case $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;;
    123 esac
    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).
    129 echo "$res $test_name (exit status: $estatus)" >>$log_file
    130 
    131 # Report outcome to console.
    132 echo "${col}${res}${std}: $test_name"
    133 
    134 # Register the test result, and other relevant metadata.
    135 echo ":test-result: $res" > $trs_file
    136 echo ":global-test-result: $res" >> $trs_file
    137 echo ":recheck: $recheck" >> $trs_file
    138 echo ":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:
     1/usr/share/automake-1.15/test-driver
  • automake/ylwrap

    • Property mode changed from 100755 to 120000
    r7951100 rb067d9b  
    1 #! /bin/sh
    2 # ylwrap - wrapper for lex/yacc invocations.
    3 
    4 scriptversion=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 
    32 get_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.
    43 guard ()
    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.
    55 quote_for_sed ()
    56 {
    57   case $# in
    58     0) cat;;
    59     1) printf '%s\n' "$1";;
    60   esac \
    61     | sed -e 's|[][\\.*]|\\&|g'
    62 }
    63 
    64 case "$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
    75 Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
    76 
    77 Wrapper 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 
    85 Any number of OUTPUT,DESIRED pairs may be used.
    86 
    87 Report bugs to <bug-automake@gnu.org>.
    88 EOF
    89     exit $?
    90     ;;
    91   -v|--v*)
    92     echo "ylwrap $scriptversion"
    93     exit $?
    94     ;;
    95 esac
    96 
    97 
    98 # The input.
    99 input=$1
    100 shift
    101 # We'll later need for a correct munging of "#line" directives.
    102 input_sub_rx=`get_dirname "$input" | quote_for_sed`
    103 case $input in
    104   [\\/]* | ?:[\\/]*)
    105     # Absolute path; do nothing.
    106     ;;
    107   *)
    108     # Relative path.  Make it absolute.
    109     input=`pwd`/$input
    110     ;;
    111 esac
    112 input_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.
    117 y_tab_nodot=false
    118 if test -f y_tab.c || test -f y_tab.h; then
    119   y_tab_nodot=true
    120 fi
    121 
    122 # The parser itself, the first file, is the destination of the .y.c
    123 # rule in the Makefile.
    124 parser=$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.
    129 sed_fix_filenames=
    130 
    131 # Also rename header guards, as Bison 2.7 for instance uses its header
    132 # guard in its implementation file.
    133 sed_fix_header_guards=
    134 
    135 while 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;"
    153 done
    154 
    155 # The program to run.
    156 prog=$1
    157 shift
    158 # Make any relative path in $prog absolute.
    159 case $prog in
    160   [\\/]* | ?:[\\/]*) ;;
    161   *[\\/]*) prog=`pwd`/$prog ;;
    162 esac
    163 
    164 dirname=ylwrap$$
    165 do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
    166 trap "ret=129; $do_exit" 1
    167 trap "ret=130; $do_exit" 2
    168 trap "ret=141; $do_exit" 13
    169 trap "ret=143; $do_exit" 15
    170 mkdir $dirname || exit 1
    171 
    172 cd $dirname
    173 
    174 case $# in
    175   0) "$prog" "$input" ;;
    176   *) "$prog" "$@" "$input" ;;
    177 esac
    178 ret=$?
    179 
    180 if 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
    231 fi
    232 
    233 # Remove the directory.
    234 cd ..
    235 rm -rf $dirname
    236 
    237 exit $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:
     1/usr/share/automake-1.15/ylwrap
  • configure

    r7951100 rb067d9b  
    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
    201209test \$(( 1 + 1 )) = 2 || exit 1"
    202210  if (eval "$as_required") 2>/dev/null; then :
     
    557565as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
    558566
     567SHELL=${CONFIG_SHELL-/bin/sh}
     568
    559569
    560570test -n "$DJDIR" || exec 7<&0 </dev/null
     
    626636LTLIBOBJS
    627637LIBOBJS
    628 ALLOCA
     638CFA_BACKEND_CC
     639DEMANGLER
     640LIBDEMANGLE
     641WITH_LIBTCMALLOC_FALSE
     642WITH_LIBTCMALLOC_TRUE
     643WITH_LIBPROFILER_FALSE
     644WITH_LIBPROFILER_TRUE
     645WITH_LIBFIBRE_FALSE
     646WITH_LIBFIBRE_TRUE
     647CXXCPP
     648CPP
     649LT_SYS_LIBRARY_PATH
     650OTOOL64
     651OTOOL
     652LIPO
     653NMEDIT
     654DSYMUTIL
     655MANIFEST_TOOL
     656RANLIB
     657ac_ct_AR
     658AR
     659DLLTOOL
     660OBJDUMP
     661LN_S
     662NM
     663ac_ct_DUMPBIN
     664DUMPBIN
     665FGREP
    629666EGREP
    630667GREP
    631 CPP
    632 RANLIB
     668SED
     669LIBTOOL
    633670LEXLIB
    634671LEX_OUTPUT_ROOT
     
    663700LDFLAGS
    664701CXXFLAGS
    665 CXX
    666702CFA_FLAGS
    667 MACHINE_TYPE
     703LIBCFA_TARGET_MAKEFILES
     704LIBCFA_TARGET_DIRS
     705TARGET_HOSTS
     706HOST_FLAGS
    668707host_os
    669708host_vendor
     
    674713build_cpu
    675714build
     715BUILD_IN_TREE_FLAGS
     716CFACPP
     717CFACC_INSTALL
     718CFACC
     719DRIVER_DIR
    676720CFA_LIBDIR
    677721CFA_BINDIR
    678722CFA_INCDIR
    679723CFA_PREFIX
     724HAS_DISTCC
     725LD
     726CXX
     727ENABLE_DISTCC_FALSE
     728ENABLE_DISTCC_TRUE
    680729DOendif
    681730DOifskipcompile
    682 BUILD_CONCURRENCY_FALSE
    683 BUILD_CONCURRENCY_TRUE
    684 BUILD_NO_LIB_FALSE
    685 BUILD_NO_LIB_TRUE
    686 BUILD_DEBUG_FALSE
    687 BUILD_DEBUG_TRUE
    688 BUILD_RELEASE_FALSE
    689 BUILD_RELEASE_TRUE
    690 CFA_BACKEND_CC
    691 BACKEND_CC
    692731CFA_NAME
    693 MAINT
    694 MAINTAINER_MODE_FALSE
    695 MAINTAINER_MODE_TRUE
    696732am__untar
    697733am__tar
     
    764800enable_option_checking
    765801enable_silent_rules
    766 enable_maintainer_mode
    767802with_cfa_name
    768 with_backend_compiler
    769 enable_target_release
    770 enable_target_debug
    771 enable_threading
     803enable_distcc
     804with_target_hosts
     805enable_gprofiler
     806enable_demangler
    772807enable_dependency_tracking
     808enable_shared
     809enable_static
     810with_pic
     811enable_fast_install
     812with_aix_soname
     813with_gnu_ld
     814with_sysroot
     815enable_libtool_lock
    773816'
    774817      ac_precious_vars='build_alias
     
    787830YACC
    788831YFLAGS
    789 CPP'
     832LT_SYS_LIBRARY_PATH
     833CPP
     834CXXCPP'
    790835
    791836
     
    14191464  --enable-silent-rules   less verbose build output (undo: "make V=1")
    14201465  --disable-silent-rules  verbose build output (undo: "make V=0")
    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)
     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)
    14281469  --enable-dependency-tracking
    14291470                          do not reject slow dependency extractors
    14301471  --disable-dependency-tracking
    14311472                          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)
    14321478
    14331479Optional Packages:
     
    14351481  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
    14361482  --with-cfa-name=NAME     NAME too which cfa will be installed
    1437   --with-backend-compiler=PROGRAM     PROGRAM that performs the final code compilation (must be gcc-compatible)
     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).
    14381492
    14391493Some influential environment variables:
     
    14551509              This script will default YFLAGS to the empty string to avoid a
    14561510              default value of `-d' given by some make applications.
     1511  LT_SYS_LIBRARY_PATH
     1512              User-defined run-time library search path.
    14571513  CPP         C preprocessor
     1514  CXXCPP      C++ preprocessor
    14581515
    14591516Use these variables to override the choices made by `configure' or to help
     
    16591716} # ac_fn_c_try_link
    16601717
    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.
    1665 ac_fn_c_check_type ()
     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.
     1722ac_fn_c_check_header_compile ()
    16661723{
    16671724  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
     
    16711728  $as_echo_n "(cached) " >&6
    16721729else
    1673   eval "$3=no"
    16741730  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    16751731/* end confdefs.h.  */
    16761732$4
    1677 int
    1678 main ()
    1679 {
    1680 if (sizeof ($2))
    1681          return 0;
    1682   ;
    1683   return 0;
    1684 }
     1733#include <$2>
    16851734_ACEOF
    16861735if ac_fn_c_try_compile "$LINENO"; then :
    1687   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    1688 /* end confdefs.h.  */
    1689 $4
    1690 int
    1691 main ()
    1692 {
    1693 if (sizeof (($2)))
    1694             return 0;
    1695   ;
    1696   return 0;
    1697 }
    1698 _ACEOF
    1699 if ac_fn_c_try_compile "$LINENO"; then :
    1700 
    1701 else
    17021736  eval "$3=yes"
    1703 fi
    1704 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     1737else
     1738  eval "$3=no"
    17051739fi
    17061740rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     
    17111745  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
    17121746
    1713 } # ac_fn_c_check_type
     1747} # ac_fn_c_check_header_compile
    17141748
    17151749# ac_fn_c_try_cpp LINENO
     
    17921826} # ac_fn_c_try_run
    17931827
    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.
    1798 ac_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; }
    1803 if eval \${$3+:} false; then :
    1804   $as_echo_n "(cached) " >&6
    1805 else
    1806   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    1807 /* end confdefs.h.  */
    1808 $4
    1809 #include <$2>
    1810 _ACEOF
    1811 if ac_fn_c_try_compile "$LINENO"; then :
    1812   eval "$3=yes"
    1813 else
    1814   eval "$3=no"
    1815 fi
    1816 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    1817 fi
    1818 eval 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 
    18251828# ac_fn_c_check_func LINENO FUNC VAR
    18261829# ----------------------------------
     
    18891892
    18901893} # 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.
     1898ac_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"
     1902case "(($ac_try" in
     1903  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
     1904  *) ac_try_echo=$ac_try;;
     1905esac
     1906eval 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
     1921else
     1922  $as_echo "$as_me: failed program was:" >&5
     1923sed 's/^/| /' conftest.$ac_ext >&5
     1924
     1925    ac_retval=1
     1926fi
     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.
     1935ac_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"
     1940case "(($ac_try" in
     1941  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
     1942  *) ac_try_echo=$ac_try;;
     1943esac
     1944eval 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
     1962else
     1963  $as_echo "$as_me: failed program was:" >&5
     1964sed 's/^/| /' conftest.$ac_ext >&5
     1965
     1966        ac_retval=1
     1967fi
     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
    18911977
    18921978# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
     
    19812067} # ac_fn_c_check_header_mongrel
    19822068
    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.
    1987 ac_fn_c_find_intX_t ()
     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.
     2073ac_fn_c_check_type ()
    19882074{
    19892075  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
    1990   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
    1991 $as_echo_n "checking for int$2_t... " >&6; }
     2076  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
     2077$as_echo_n "checking for $2... " >&6; }
    19922078if eval \${$3+:} false; then :
    19932079  $as_echo_n "(cached) " >&6
    19942080else
    19952081  eval "$3=no"
    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
     2082  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    20012083/* end confdefs.h.  */
    2002 $ac_includes_default
    2003              enum { N = $2 / 2 - 1 };
     2084$4
    20042085int
    20052086main ()
    20062087{
    2007 static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
    2008 test_array [0] = 0;
    2009 return test_array [0];
    2010 
     2088if (sizeof ($2))
     2089         return 0;
    20112090  ;
    20122091  return 0;
     
    20162095  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    20172096/* end confdefs.h.  */
    2018 $ac_includes_default
    2019                 enum { N = $2 / 2 - 1 };
     2097$4
    20202098int
    20212099main ()
    20222100{
    2023 static 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))];
    2025 test_array [0] = 0;
    2026 return test_array [0];
    2027 
     2101if (sizeof (($2)))
     2102            return 0;
    20282103  ;
    20292104  return 0;
     
    20332108
    20342109else
    2035   case $ac_type in #(
    2036   int$2_t) :
    2037     eval "$3=yes" ;; #(
    2038   *) :
    2039     eval "$3=\$ac_type" ;;
    2040 esac
     2110  eval "$3=yes"
    20412111fi
    20422112rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    20432113fi
    20442114rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    2045        if eval test \"x\$"$3"\" = x"no"; then :
    2046 
    2047 else
    2048   break
    2049 fi
    2050      done
    20512115fi
    20522116eval ac_res=\$$3
     
    20552119  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
    20562120
    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.
    2063 ac_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; }
    2068 if eval \${$3+:} false; then :
    2069   $as_echo_n "(cached) " >&6
    2070 else
    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
    2079 int
    2080 main ()
    2081 {
    2082 static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
    2083 test_array [0] = 0;
    2084 return test_array [0];
    2085 
    2086   ;
    2087   return 0;
    2088 }
    2089 _ACEOF
    2090 if 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" ;;
    2096 esac
    2097 fi
    2098 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    2099        if eval test \"x\$"$3"\" = x"no"; then :
    2100 
    2101 else
    2102   break
    2103 fi
    2104      done
    2105 fi
    2106 eval 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
     2121} # ac_fn_c_check_type
    21122122cat >config.log <<_ACEOF
    21132123This file contains any messages produced by compilers while
     
    24912501
    24922502
     2503
    24932504#AC_CONFIG_SRCDIR([src/main.cc])
    2494 ac_config_headers="$ac_config_headers config.h"
     2505ac_config_headers="$ac_config_headers config.h:src/config.h.in"
    24952506
    24962507# Check whether --enable-silent-rules was given.
     
    25022513  yes) AM_DEFAULT_VERBOSITY=0;;
    25032514   no) AM_DEFAULT_VERBOSITY=1;;
    2504     *) AM_DEFAULT_VERBOSITY=1;;
     2515    *) AM_DEFAULT_VERBOSITY=0;;
    25052516esac
    25062517am_make=${MAKE-make}
     
    25332544AM_BACKSLASH='\'
    25342545
     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=""}
    25352559
    25362560am__api_version='1.15'
     
    30753099
    30763100
    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.
    3080 if test "${enable_maintainer_mode+set}" = set; then :
    3081   enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
    3082 else
    3083   USE_MAINTAINER_MODE=yes
    3084 fi
    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='#'
    3091 else
    3092   MAINTAINER_MODE_TRUE='#'
    3093   MAINTAINER_MODE_FALSE=
    3094 fi
    3095 
    3096   MAINT=$MAINTAINER_MODE_TRUE
    3097 
    3098                         # may require auto* software to be installed
    3099 
    31003101# Allow program name tansformation
    31013102# will fill program_transform_name with appropriate sed regex
    31023103
    31033104
     3105#==============================================================================
    31043106#Trasforming cc1 will break compilation
    3105 if test "${program_transform_name}" = ""; then
    3106     as_fn_error $? "Program transform not supported.
    3107                 Use --with-cfa-name='[Desired name here]' instead" "$LINENO" 5
    3108 fi
    3109 
     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
    31103114
    31113115# Check whether --with-cfa-name was given.
     
    31173121
    31183122
    3119 #Define the new name of the installed command
    3120 CFA_NAME=${cfa_name}
    3121 
     3123        CFA_NAME=${cfa_name}
     3124
     3125
     3126
     3127#==============================================================================
     3128# version information
    31223129
    31233130rm -f version
     
    31713178
    31723179
    3173 # Installation paths
    3174 
    3175 
    3176 # Check whether --with-backend-compiler was given.
    3177 if test "${with_backend_compiler+set}" = set; then :
    3178   withval=$with_backend_compiler; backendcompiler=$withval
    3179 else
    3180   backendcompiler=""
    3181 fi
    3182 
    3183 if test "x$backendcompiler" != "x"; then
    3184         BACKEND_CC=${backendcompiler}
    3185 else
    3186         # Extract the first word of "gcc", so it can be a program name with args.
    3187 set 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; }
    3190 if ${ac_cv_path_BACKEND_CC+:} false; then :
    3191   $as_echo_n "(cached) " >&6
    3192 else
    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
    3199 for as_dir in $PATH
    3200 do
    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
    3209 done
    3210   done
    3211 IFS=$as_save_IFS
    3212 
    3213   ;;
    3214 esac
    3215 fi
    3216 BACKEND_CC=$ac_cv_path_BACKEND_CC
    3217 if test -n "$BACKEND_CC"; then
    3218   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BACKEND_CC" >&5
    3219 $as_echo "$BACKEND_CC" >&6; }
    3220 else
    3221   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    3222 $as_echo "no" >&6; }
    3223 fi
    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
    3230 fi
    3231 
    3232 cat >>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.
    3241 if test "${enable_target_release+set}" = set; then :
    3242   enableval=$enable_target_release;
    3243 fi
    3244 
    3245 # Check whether --enable-target-debug was given.
    3246 if test "${enable_target_debug+set}" = set; then :
    3247   enableval=$enable_target_debug;
    3248 fi
    3249 
    3250 # Check whether --enable-threading was given.
    3251 if 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 ;;
    3256 esac
    3257 else
    3258   build_threading="yes"
    3259 fi
    3260 
    3261 
    3262 case "$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                 ;;
    3311 esac
    3312 
    3313  if test "x$build_release" = "xyes"; then
    3314   BUILD_RELEASE_TRUE=
    3315   BUILD_RELEASE_FALSE='#'
    3316 else
    3317   BUILD_RELEASE_TRUE='#'
    3318   BUILD_RELEASE_FALSE=
    3319 fi
    3320 
    3321  if test "x$build_debug" = "xyes"; then
    3322   BUILD_DEBUG_TRUE=
    3323   BUILD_DEBUG_FALSE='#'
    3324 else
    3325   BUILD_DEBUG_TRUE='#'
    3326   BUILD_DEBUG_FALSE=
    3327 fi
    3328 
    3329  if test "x$build_release$build_debug" = "xnono"; then
    3330   BUILD_NO_LIB_TRUE=
    3331   BUILD_NO_LIB_FALSE='#'
    3332 else
    3333   BUILD_NO_LIB_TRUE='#'
    3334   BUILD_NO_LIB_FALSE=
    3335 fi
    3336 
    3337  if test "x$build_threading" = "xyes"; then
    3338   BUILD_CONCURRENCY_TRUE=
    3339   BUILD_CONCURRENCY_FALSE='#'
    3340 else
    3341   BUILD_CONCURRENCY_TRUE='#'
    3342   BUILD_CONCURRENCY_FALSE=
    3343 fi
    3344 
    3345 
     3180#==============================================================================
     3181# HACK to be able to use conditionnals inside makefiles
    33463182DOifskipcompile='ifeq ($(skipcompile),yes)
    33473183else'
     
    33533189
    33543190
    3355 if test "x$prefix" = "xNONE"; then
    3356         cfa_prefix=${ac_default_prefix}
    3357 else
    3358         cfa_prefix=${prefix}
    3359 fi
     3191#==============================================================================
     3192# distcc support
     3193
     3194# Check whether --enable-distcc was given.
     3195if test "${enable_distcc+set}" = set; then :
     3196  enableval=$enable_distcc; enable_distcc=$enableval
     3197else
     3198  enable_distcc=no
     3199fi
     3200
     3201
     3202 if test x$enable_distcc = xyes; then
     3203  ENABLE_DISTCC_TRUE=
     3204  ENABLE_DISTCC_FALSE='#'
     3205else
     3206  ENABLE_DISTCC_TRUE='#'
     3207  ENABLE_DISTCC_FALSE=
     3208fi
     3209
     3210HAS_DISTCC="False"
     3211
     3212if test x$enable_distcc = xyes; then
     3213        CXX="distcc ${CXX}"
     3214        LD="distcc ${LD} -lstdc++"
     3215        HAS_DISTCC="True"
     3216        echo "Enabling distributed builds"
     3217fi
     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})/"
    33603232
    33613233cat >>confdefs.h <<_ACEOF
     
    33633235_ACEOF
    33643236
    3365 CFA_PREFIX=${cfa_prefix}
    3366 
    3367 
    3368 if test "$includedir" = '${prefix}/include'; then
    3369         cfa_incdir="${cfa_prefix}/include/${cfa_name}"
    3370 else
    3371         cfa_incdir=${includedir}
    3372 fi
     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})/"
    33733246
    33743247cat >>confdefs.h <<_ACEOF
     
    33763249_ACEOF
    33773250
    3378 CFA_INCDIR=${cfa_incdir}
    3379 
    3380 
    3381 if test "$bindir" = '${exec_prefix}/bin'; then
    3382         cfa_bindir="${cfa_prefix}/bin"
    3383 else
    3384         cfa_bindir=${bindir}
    3385 fi
     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})/"
    33863260
    33873261cat >>confdefs.h <<_ACEOF
     
    33893263_ACEOF
    33903264
    3391 CFA_BINDIR=${cfa_bindir}
    3392 
    3393 
    3394 if test "$libdir" = '${exec_prefix}/lib'; then
    3395         cfa_libdir="${cfa_prefix}/lib/${cfa_name}"
    3396 else
    3397         cfa_libdir=${libdir}
    3398 fi
     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})/"
    33993278
    34003279cat >>confdefs.h <<_ACEOF
     
    34023281_ACEOF
    34033282
    3404 CFA_LIBDIR=${cfa_libdir}
    3405 
    3406 
     3283        CFA_LIBDIR=${cfa_libdir}
     3284
     3285
     3286
     3287#==============================================================================
     3288# Create variables for commonly used targets
     3289
     3290TOP_SRCDIR="$(readlink -m $ac_confdir/)/"
     3291TOP_BUILDDIR="$(readlink -m $ac_pwd/)/"
     3292
     3293
     3294cat >>confdefs.h <<_ACEOF
     3295#define TOP_SRCDIR "$TOP_SRCDIR"
     3296_ACEOF
     3297
     3298
     3299cat >>confdefs.h <<_ACEOF
     3300#define TOP_BUILDDIR "$TOP_BUILDDIR"
     3301_ACEOF
     3302
     3303
     3304DRIVER_DIR=${TOP_BUILDDIR}driver/
     3305CFACC=${DRIVER_DIR}cfa
     3306CFACC_INSTALL=${CFA_BINDIR}${CFA_NAME}
     3307CFACPP=${DRIVER_DIR}cfa-cpp
     3308
     3309
     3310
     3311
     3312
     3313#==============================================================================
     3314# Flag variables needed to build in tree
     3315LIBCFA_SRC='${TOP_SRCDIR}/libcfa/src'
     3316BUILD_IN_TREE_FLAGS="-XCFA -t -B${DRIVER_DIR}"
     3317
     3318
     3319#==============================================================================
     3320# handle the list of hosts to build for
     3321for var in $ac_configure_args
     3322do
     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
     3338done
     3339
     3340#==============================================================================
     3341# handle the list of hosts to build for
    34073342# Make sure we can run config.sub.
    34083343$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
     
    34763411
    34773412
    3478 MACHINE_TYPE=$host_cpu
    3479 
    34803413
    34813414if ! test "$host_cpu" = "$build_cpu"; then
    34823415        case $host_cpu in
    34833416                i386)
    3484                         CFLAGS+=" -m32 "
    3485                         CXXFLAGS+=" -m32 "
    3486                         CFAFLAGS+=" -m32 "
    3487                         LDFLAGS+=" -m32 "
     3417                        HOST_FLAGS="-m32"
    34883418                        ;;
    34893419                i686)
    3490                         CFLAGS+=" -m32 "
    3491                   CXXFLAGS+=" -m32 "
    3492                   CFAFLAGS+=" -m32 "
    3493                   LDFLAGS+=" -m32 "
     3420                        HOST_FLAGS="-m32"
    34943421                        ;;
    34953422                x86_64)
    3496                         CFLAGS+=" -m64 "
    3497                         CXXFLAGS+=" -m64 "
    3498                         CFAFLAGS+=" -m64 "
    3499                         LDFLAGS+=" -m64 "
     3423                        HOST_FLAGS="-m64"
    35003424                        ;;
    35013425        esac
    35023426fi
    35033427
     3428
     3429default_target="${host_cpu}:debug, ${host_cpu}:nodebug"
     3430
     3431# Check whether --with-target-hosts was given.
     3432if test "${with_target_hosts+set}" = set; then :
     3433  withval=$with_target_hosts; target_hosts=$withval
     3434else
     3435  target_hosts=${default_target}
     3436fi
     3437
     3438
     3439# Check whether --enable-gprofiler was given.
     3440if test "${enable_gprofiler+set}" = set; then :
     3441  enableval=$enable_gprofiler; enable_gprofiler=$enableval
     3442else
     3443  enable_gprofiler=yes
     3444fi
     3445
     3446
     3447# Check whether --enable-demangler was given.
     3448if test "${enable_demangler+set}" = set; then :
     3449  enableval=$enable_demangler; enable_demangler=$enableval
     3450else
     3451  enable_demangler=yes
     3452fi
     3453
     3454
     3455TARGET_HOSTS=${target_hosts}
     3456
     3457
     3458LIBCFA_PATHS="DRIVER_DIR=${DRIVER_DIR}"
     3459
     3460for i in $(echo $target_hosts | sed "s/,/ /g")
     3461do
     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
     3514done
     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
     3545cat >>confdefs.h <<_ACEOF
     3546#define CFA_DEFAULT_CPU "$cannon_arch_name"
     3547_ACEOF
     3548
     3549
     3550cat >>confdefs.h <<_ACEOF
     3551#define CFA_64_CPU "x64"
     3552_ACEOF
     3553
     3554
     3555cat >>confdefs.h <<_ACEOF
     3556#define CFA_32_CPU "x86"
     3557_ACEOF
     3558
     3559
     3560#==============================================================================
     3561# CAFLAGS
    35043562
    35053563cat >>confdefs.h <<_ACEOF
     
    35103568
    35113569
     3570#==============================================================================
    35123571# Checks for programs.
    35133572ac_ext=cpp
     
    50685127
    50695128
    5070         # deprecated
    50715129# These are often not installed and people miss seeing the "no", so stop the configure.
    50725130for ac_prog in 'bison -y' byacc
     
    52755333fi
    52765334if test "${LEX}" = "lex" ; then echo "Error: flex required." ; exit 1 ; fi
    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; }
    5280 set x ${MAKE-make}
    5281 ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
    5282 if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
     5335case `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;} ;;
     5339esac
     5340
     5341
     5342
     5343macro_version='2.4.6'
     5344macro_revision='2.4.6'
     5345
     5346
     5347
     5348
     5349
     5350
     5351
     5352
     5353
     5354
     5355
     5356
     5357
     5358ltmain=$ac_aux_dir/ltmain.sh
     5359
     5360# Backslashify metacharacters that are still active within
     5361# double-quoted strings.
     5362sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
     5363
     5364# Same as above, but do not quote variable references.
     5365double_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.
     5369delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
     5370
     5371# Sed substitution to delay expansion of an escaped single quote.
     5372delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
     5373
     5374# Sed substitution to avoid accidental globbing in evaled expressions
     5375no_glob_subst='s/\*/\\\*/g'
     5376
     5377ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
     5378ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
     5379ECHO=$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.
     5384if 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 --'
     5387elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
     5388  ECHO='printf %s\n'
     5389else
     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'
     5398fi
     5399
     5400# func_echo_all arg...
     5401# Invoke $ECHO with all args, space-separated.
     5402func_echo_all ()
     5403{
     5404    $ECHO ""
     5405}
     5406
     5407case $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; } ;;
     5414esac
     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; }
     5431if ${ac_cv_path_SED+:} false; then :
    52835432  $as_echo_n "(cached) " >&6
    52845433else
    5285   cat >conftest.make <<\_ACEOF
    5286 SHELL = /bin/sh
    5287 all:
    5288         @echo '@@@%%%=$(MAKE)=@@@%%%'
    5289 _ACEOF
    5290 # GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
    5291 case `${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;;
    5296 esac
    5297 rm -f conftest.make
    5298 fi
    5299 if 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=
    5303 else
    5304   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    5305 $as_echo "no" >&6; }
    5306   SET_MAKE="MAKE=${MAKE-make}"
    5307 fi
    5308 
    5309 if 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.
    5311 set 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; }
    5314 if ${ac_cv_prog_RANLIB+:} false; then :
    5315   $as_echo_n "(cached) " >&6
    5316 else
    5317   if test -n "$RANLIB"; then
    5318   ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
    5319 else
    5320 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     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
    53215444for as_dir in $PATH
    53225445do
    53235446  IFS=$as_save_IFS
    53245447  test -z "$as_dir" && as_dir=.
     5448    for ac_prog in sed gsed; do
    53255449    for ac_exec_ext in '' $ac_executable_extensions; do
    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
    5331 done
     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
     5454case `"$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;;
     5478esac
     5479
     5480      $ac_path_SED_found && break 3
     5481    done
     5482  done
    53325483  done
    53335484IFS=$as_save_IFS
    5334 
    5335 fi
    5336 fi
    5337 RANLIB=$ac_cv_prog_RANLIB
    5338 if test -n "$RANLIB"; then
    5339   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
    5340 $as_echo "$RANLIB" >&6; }
    5341 else
    5342   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    5343 $as_echo "no" >&6; }
    5344 fi
    5345 
    5346 
    5347 fi
    5348 if 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.
    5351 set 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; }
    5354 if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
    5355   $as_echo_n "(cached) " >&6
    5356 else
    5357   if test -n "$ac_ct_RANLIB"; then
    5358   ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
    5359 else
    5360 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
    5361 for as_dir in $PATH
    5362 do
    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
     5485  if test -z "$ac_cv_path_SED"; then
     5486    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
    53705487  fi
    5371 done
    5372   done
    5373 IFS=$as_save_IFS
    5374 
    5375 fi
    5376 fi
    5377 ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
    5378 if 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; }
    5381 else
    5382   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
    5383 $as_echo "no" >&6; }
    5384 fi
    5385 
    5386   if test "x$ac_ct_RANLIB" = x; then
    5387     RANLIB=":"
    5388   else
    5389     case $cross_compiling:$ac_tool_warned in
    5390 yes:)
    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;}
    5393 ac_tool_warned=yes ;;
    5394 esac
    5395     RANLIB=$ac_ct_RANLIB
    5396   fi
    5397 else
    5398   RANLIB="$ac_cv_prog_RANLIB"
    5399 fi
    5400 
    5401 
    5402 # Checks for libraries.
    5403 
    5404 # Checks for header files.
    5405 ac_ext=c
    5406 ac_cpp='$CPP $CPPFLAGS'
    5407 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    5408 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    5409 ac_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.
    5413 if test -n "$CPP" && test -d "$CPP"; then
    5414   CPP=
    5415 fi
    5416 if test -z "$CPP"; then
    5417   if ${ac_cv_prog_CPP+:} false; then :
    5418   $as_echo_n "(cached) " >&6
    5419 else
    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
    5424 for ac_c_preproc_warn_flag in '' yes
    5425 do
    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
    5441 if ac_fn_c_try_cpp "$LINENO"; then :
    5442 
    5443 else
    5444   # Broken: fails on valid input.
    5445 continue
    5446 fi
    5447 rm -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
    5455 if ac_fn_c_try_cpp "$LINENO"; then :
    5456   # Broken: success on invalid input.
    5457 continue
    5458 else
    5459   # Passes both tests.
    5460 ac_preproc_ok=:
    5461 break
    5462 fi
    5463 rm -f conftest.err conftest.i conftest.$ac_ext
    5464 
    5465 done
    5466 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
    5467 rm -f conftest.i conftest.err conftest.$ac_ext
    5468 if $ac_preproc_ok; then :
    5469   break
    5470 fi
    5471 
    5472     done
    5473     ac_cv_prog_CPP=$CPP
    5474 
    5475 fi
    5476   CPP=$ac_cv_prog_CPP
    5477 else
    5478   ac_cv_prog_CPP=$CPP
    5479 fi
    5480 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
    5481 $as_echo "$CPP" >&6; }
    5482 ac_preproc_ok=false
    5483 for ac_c_preproc_warn_flag in '' yes
    5484 do
    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
    5500 if ac_fn_c_try_cpp "$LINENO"; then :
    5501 
    5502 else
    5503   # Broken: fails on valid input.
    5504 continue
    5505 fi
    5506 rm -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
    5514 if ac_fn_c_try_cpp "$LINENO"; then :
    5515   # Broken: success on invalid input.
    5516 continue
    5517 else
    5518   # Passes both tests.
    5519 ac_preproc_ok=:
    5520 break
    5521 fi
    5522 rm -f conftest.err conftest.i conftest.$ac_ext
    5523 
    5524 done
    5525 # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
    5526 rm -f conftest.i conftest.err conftest.$ac_ext
    5527 if $ac_preproc_ok; then :
    5528 
    5529 else
    5530   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
    5531 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
    5532 as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
    5533 See \`config.log' for more details" "$LINENO" 5; }
    5534 fi
    5535 
    5536 ac_ext=c
    5537 ac_cpp='$CPP $CPPFLAGS'
    5538 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
    5539 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
    5540 ac_compiler_gnu=$ac_cv_c_compiler_gnu
     5488else
     5489  ac_cv_path_SED=$SED
     5490fi
     5491
     5492fi
     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
     5498test -z "$SED" && SED=sed
     5499Xsed="$SED -e 1s/^X//"
     5500
     5501
     5502
     5503
     5504
     5505
     5506
     5507
     5508
    55415509
    55425510
     
    56715639
    56725640
     5641{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
     5642$as_echo_n "checking for fgrep... " >&6; }
     5643if ${ac_cv_path_FGREP+:} false; then :
     5644  $as_echo_n "(cached) " >&6
     5645else
     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
     5653for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
     5654do
     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
     5663case `"$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;;
     5687esac
     5688
     5689      $ac_path_FGREP_found && break 3
     5690    done
     5691  done
     5692  done
     5693IFS=$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
     5697else
     5698  ac_cv_path_FGREP=$FGREP
     5699fi
     5700
     5701   fi
     5702fi
     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
     5708test -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.
     5729if test "${with_gnu_ld+set}" = set; then :
     5730  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
     5731else
     5732  with_gnu_ld=no
     5733fi
     5734
     5735ac_prog=ld
     5736if 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
     5767elif 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; }
     5770else
     5771  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
     5772$as_echo_n "checking for non-GNU ld... " >&6; }
     5773fi
     5774if ${lt_cv_path_LD+:} false; then :
     5775  $as_echo_n "(cached) " >&6
     5776else
     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
     5798else
     5799  lt_cv_path_LD=$LD # Let the user override the test with a path.
     5800fi
     5801fi
     5802
     5803LD=$lt_cv_path_LD
     5804if test -n "$LD"; then
     5805  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
     5806$as_echo "$LD" >&6; }
     5807else
     5808  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5809$as_echo "no" >&6; }
     5810fi
     5811test -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; }
     5814if ${lt_cv_prog_gnu_ld+:} false; then :
     5815  $as_echo_n "(cached) " >&6
     5816else
     5817  # I'd rather use --version here, but apparently some GNU lds only accept -v.
     5818case `$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  ;;
     5825esac
     5826fi
     5827{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
     5828$as_echo "$lt_cv_prog_gnu_ld" >&6; }
     5829with_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; }
     5841if ${lt_cv_path_NM+:} false; then :
     5842  $as_echo_n "(cached) " >&6
     5843else
     5844  if test -n "$NM"; then
     5845  # Let the user override the test.
     5846  lt_cv_path_NM=$NM
     5847else
     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}
     5891fi
     5892fi
     5893{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
     5894$as_echo "$lt_cv_path_NM" >&6; }
     5895if test no != "$lt_cv_path_NM"; then
     5896  NM=$lt_cv_path_NM
     5897else
     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.
     5906set 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; }
     5909if ${ac_cv_prog_DUMPBIN+:} false; then :
     5910  $as_echo_n "(cached) " >&6
     5911else
     5912  if test -n "$DUMPBIN"; then
     5913  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
     5914else
     5915as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     5916for as_dir in $PATH
     5917do
     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
     5926done
     5927  done
     5928IFS=$as_save_IFS
     5929
     5930fi
     5931fi
     5932DUMPBIN=$ac_cv_prog_DUMPBIN
     5933if test -n "$DUMPBIN"; then
     5934  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
     5935$as_echo "$DUMPBIN" >&6; }
     5936else
     5937  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5938$as_echo "no" >&6; }
     5939fi
     5940
     5941
     5942    test -n "$DUMPBIN" && break
     5943  done
     5944fi
     5945if test -z "$DUMPBIN"; then
     5946  ac_ct_DUMPBIN=$DUMPBIN
     5947  for ac_prog in dumpbin "link -dump"
     5948do
     5949  # Extract the first word of "$ac_prog", so it can be a program name with args.
     5950set 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; }
     5953if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
     5954  $as_echo_n "(cached) " >&6
     5955else
     5956  if test -n "$ac_ct_DUMPBIN"; then
     5957  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
     5958else
     5959as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     5960for as_dir in $PATH
     5961do
     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
     5970done
     5971  done
     5972IFS=$as_save_IFS
     5973
     5974fi
     5975fi
     5976ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
     5977if 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; }
     5980else
     5981  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     5982$as_echo "no" >&6; }
     5983fi
     5984
     5985
     5986  test -n "$ac_ct_DUMPBIN" && break
     5987done
     5988
     5989  if test "x$ac_ct_DUMPBIN" = x; then
     5990    DUMPBIN=":"
     5991  else
     5992    case $cross_compiling:$ac_tool_warned in
     5993yes:)
     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;}
     5996ac_tool_warned=yes ;;
     5997esac
     5998    DUMPBIN=$ac_ct_DUMPBIN
     5999  fi
     6000fi
     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
     6015fi
     6016test -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; }
     6025if ${lt_cv_nm_interface+:} false; then :
     6026  $as_echo_n "(cached) " >&6
     6027else
     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*
     6042fi
     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; }
     6048LN_S=$as_ln_s
     6049if test "$LN_S" = "ln -s"; then
     6050  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
     6051$as_echo "yes" >&6; }
     6052else
     6053  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
     6054$as_echo "no, using $LN_S" >&6; }
     6055fi
     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; }
     6060if ${lt_cv_sys_max_cmd_len+:} false; then :
     6061  $as_echo_n "(cached) " >&6
     6062else
     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
     6186fi
     6187
     6188if 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; }
     6191else
     6192  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
     6193$as_echo "none" >&6; }
     6194fi
     6195max_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
     6206if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
     6207  lt_unset=unset
     6208else
     6209  lt_unset=false
     6210fi
     6211
     6212
     6213
     6214
     6215
     6216# test EBCDIC or ASCII
     6217case `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  ;;
     6227esac
     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; }
     6239if ${lt_cv_to_host_file_cmd+:} false; then :
     6240  $as_echo_n "(cached) " >&6
     6241else
     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    ;;
     6272esac
     6273
     6274fi
     6275
     6276to_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; }
     6286if ${lt_cv_to_tool_file_cmd+:} false; then :
     6287  $as_echo_n "(cached) " >&6
     6288else
     6289  #assume ordinary cross tools, or native build.
     6290lt_cv_to_tool_file_cmd=func_convert_file_noop
     6291case $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    ;;
     6299esac
     6300
     6301fi
     6302
     6303to_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; }
     6313if ${lt_cv_ld_reload_flag+:} false; then :
     6314  $as_echo_n "(cached) " >&6
     6315else
     6316  lt_cv_ld_reload_flag='-r'
     6317fi
     6318{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
     6319$as_echo "$lt_cv_ld_reload_flag" >&6; }
     6320reload_flag=$lt_cv_ld_reload_flag
     6321case $reload_flag in
     6322"" | " "*) ;;
     6323*) reload_flag=" $reload_flag" ;;
     6324esac
     6325reload_cmds='$LD$reload_flag -o $output$reload_objs'
     6326case $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    ;;
     6339esac
     6340
     6341
     6342
     6343
     6344
     6345
     6346
     6347
     6348
     6349if 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.
     6351set 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; }
     6354if ${ac_cv_prog_OBJDUMP+:} false; then :
     6355  $as_echo_n "(cached) " >&6
     6356else
     6357  if test -n "$OBJDUMP"; then
     6358  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
     6359else
     6360as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     6361for as_dir in $PATH
     6362do
     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
     6371done
     6372  done
     6373IFS=$as_save_IFS
     6374
     6375fi
     6376fi
     6377OBJDUMP=$ac_cv_prog_OBJDUMP
     6378if test -n "$OBJDUMP"; then
     6379  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
     6380$as_echo "$OBJDUMP" >&6; }
     6381else
     6382  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     6383$as_echo "no" >&6; }
     6384fi
     6385
     6386
     6387fi
     6388if 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.
     6391set 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; }
     6394if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
     6395  $as_echo_n "(cached) " >&6
     6396else
     6397  if test -n "$ac_ct_OBJDUMP"; then
     6398  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
     6399else
     6400as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     6401for as_dir in $PATH
     6402do
     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
     6411done
     6412  done
     6413IFS=$as_save_IFS
     6414
     6415fi
     6416fi
     6417ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
     6418if 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; }
     6421else
     6422  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     6423$as_echo "no" >&6; }
     6424fi
     6425
     6426  if test "x$ac_ct_OBJDUMP" = x; then
     6427    OBJDUMP="false"
     6428  else
     6429    case $cross_compiling:$ac_tool_warned in
     6430yes:)
     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;}
     6433ac_tool_warned=yes ;;
     6434esac
     6435    OBJDUMP=$ac_ct_OBJDUMP
     6436  fi
     6437else
     6438  OBJDUMP="$ac_cv_prog_OBJDUMP"
     6439fi
     6440
     6441test -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; }
     6453if ${lt_cv_deplibs_check_method+:} false; then :
     6454  $as_echo_n "(cached) " >&6
     6455else
     6456  lt_cv_file_magic_cmd='$MAGIC_CMD'
     6457lt_cv_file_magic_test_file=
     6458lt_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
     6470case $host_os in
     6471aix[4-9]*)
     6472  lt_cv_deplibs_check_method=pass_all
     6473  ;;
     6474
     6475beos*)
     6476  lt_cv_deplibs_check_method=pass_all
     6477  ;;
     6478
     6479bsdi[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
     6485cygwin*)
     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
     6491mingw* | 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
     6505cegcc*)
     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
     6511darwin* | rhapsody*)
     6512  lt_cv_deplibs_check_method=pass_all
     6513  ;;
     6514
     6515freebsd* | 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
     6531haiku*)
     6532  lt_cv_deplibs_check_method=pass_all
     6533  ;;
     6534
     6535hpux10.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
     6553interix[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
     6558irix5* | 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.
     6569linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
     6570  lt_cv_deplibs_check_method=pass_all
     6571  ;;
     6572
     6573netbsd* | 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
     6581newos6*)
     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
     6591openbsd* | 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
     6599osf3* | osf4* | osf5*)
     6600  lt_cv_deplibs_check_method=pass_all
     6601  ;;
     6602
     6603rdos*)
     6604  lt_cv_deplibs_check_method=pass_all
     6605  ;;
     6606
     6607solaris*)
     6608  lt_cv_deplibs_check_method=pass_all
     6609  ;;
     6610
     6611sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
     6612  lt_cv_deplibs_check_method=pass_all
     6613  ;;
     6614
     6615sysv4 | 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
     6642tpf*)
     6643  lt_cv_deplibs_check_method=pass_all
     6644  ;;
     6645os2*)
     6646  lt_cv_deplibs_check_method=pass_all
     6647  ;;
     6648esac
     6649
     6650fi
     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
     6654file_magic_glob=
     6655want_nocaseglob=no
     6656if 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
     6666fi
     6667
     6668file_magic_cmd=$lt_cv_file_magic_cmd
     6669deplibs_check_method=$lt_cv_deplibs_check_method
     6670test -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
     6693if 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.
     6695set 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; }
     6698if ${ac_cv_prog_DLLTOOL+:} false; then :
     6699  $as_echo_n "(cached) " >&6
     6700else
     6701  if test -n "$DLLTOOL"; then
     6702  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
     6703else
     6704as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     6705for as_dir in $PATH
     6706do
     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
     6715done
     6716  done
     6717IFS=$as_save_IFS
     6718
     6719fi
     6720fi
     6721DLLTOOL=$ac_cv_prog_DLLTOOL
     6722if test -n "$DLLTOOL"; then
     6723  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
     6724$as_echo "$DLLTOOL" >&6; }
     6725else
     6726  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     6727$as_echo "no" >&6; }
     6728fi
     6729
     6730
     6731fi
     6732if 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.
     6735set 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; }
     6738if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
     6739  $as_echo_n "(cached) " >&6
     6740else
     6741  if test -n "$ac_ct_DLLTOOL"; then
     6742  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
     6743else
     6744as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     6745for as_dir in $PATH
     6746do
     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
     6755done
     6756  done
     6757IFS=$as_save_IFS
     6758
     6759fi
     6760fi
     6761ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
     6762if 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; }
     6765else
     6766  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     6767$as_echo "no" >&6; }
     6768fi
     6769
     6770  if test "x$ac_ct_DLLTOOL" = x; then
     6771    DLLTOOL="false"
     6772  else
     6773    case $cross_compiling:$ac_tool_warned in
     6774yes:)
     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;}
     6777ac_tool_warned=yes ;;
     6778esac
     6779    DLLTOOL=$ac_ct_DLLTOOL
     6780  fi
     6781else
     6782  DLLTOOL="$ac_cv_prog_DLLTOOL"
     6783fi
     6784
     6785test -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; }
     6798if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
     6799  $as_echo_n "(cached) " >&6
     6800else
     6801  lt_cv_sharedlib_from_linklib_cmd='unknown'
     6802
     6803case $host_os in
     6804cygwin* | 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  ;;
     6820esac
     6821
     6822fi
     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; }
     6825sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
     6826test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
     6827
     6828
     6829
     6830
     6831
     6832
     6833
     6834if 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.
     6838set 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; }
     6841if ${ac_cv_prog_AR+:} false; then :
     6842  $as_echo_n "(cached) " >&6
     6843else
     6844  if test -n "$AR"; then
     6845  ac_cv_prog_AR="$AR" # Let the user override the test.
     6846else
     6847as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     6848for as_dir in $PATH
     6849do
     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
     6858done
     6859  done
     6860IFS=$as_save_IFS
     6861
     6862fi
     6863fi
     6864AR=$ac_cv_prog_AR
     6865if test -n "$AR"; then
     6866  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
     6867$as_echo "$AR" >&6; }
     6868else
     6869  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     6870$as_echo "no" >&6; }
     6871fi
     6872
     6873
     6874    test -n "$AR" && break
     6875  done
     6876fi
     6877if test -z "$AR"; then
     6878  ac_ct_AR=$AR
     6879  for ac_prog in ar
     6880do
     6881  # Extract the first word of "$ac_prog", so it can be a program name with args.
     6882set 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; }
     6885if ${ac_cv_prog_ac_ct_AR+:} false; then :
     6886  $as_echo_n "(cached) " >&6
     6887else
     6888  if test -n "$ac_ct_AR"; then
     6889  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
     6890else
     6891as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     6892for as_dir in $PATH
     6893do
     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
     6902done
     6903  done
     6904IFS=$as_save_IFS
     6905
     6906fi
     6907fi
     6908ac_ct_AR=$ac_cv_prog_ac_ct_AR
     6909if 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; }
     6912else
     6913  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     6914$as_echo "no" >&6; }
     6915fi
     6916
     6917
     6918  test -n "$ac_ct_AR" && break
     6919done
     6920
     6921  if test "x$ac_ct_AR" = x; then
     6922    AR="false"
     6923  else
     6924    case $cross_compiling:$ac_tool_warned in
     6925yes:)
     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;}
     6928ac_tool_warned=yes ;;
     6929esac
     6930    AR=$ac_ct_AR
     6931  fi
     6932fi
     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; }
     6949if ${lt_cv_ar_at_file+:} false; then :
     6950  $as_echo_n "(cached) " >&6
     6951else
     6952  lt_cv_ar_at_file=no
     6953   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     6954/* end confdefs.h.  */
     6955
     6956int
     6957main ()
     6958{
     6959
     6960  ;
     6961  return 0;
     6962}
     6963_ACEOF
     6964if 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
     6986fi
     6987rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     6988
     6989fi
     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
     6993if test no = "$lt_cv_ar_at_file"; then
     6994  archiver_list_spec=
     6995else
     6996  archiver_list_spec=$lt_cv_ar_at_file
     6997fi
     6998
     6999
     7000
     7001
     7002
     7003
     7004
     7005if 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.
     7007set 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; }
     7010if ${ac_cv_prog_STRIP+:} false; then :
     7011  $as_echo_n "(cached) " >&6
     7012else
     7013  if test -n "$STRIP"; then
     7014  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
     7015else
     7016as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     7017for as_dir in $PATH
     7018do
     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
     7027done
     7028  done
     7029IFS=$as_save_IFS
     7030
     7031fi
     7032fi
     7033STRIP=$ac_cv_prog_STRIP
     7034if test -n "$STRIP"; then
     7035  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
     7036$as_echo "$STRIP" >&6; }
     7037else
     7038  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     7039$as_echo "no" >&6; }
     7040fi
     7041
     7042
     7043fi
     7044if 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.
     7047set 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; }
     7050if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
     7051  $as_echo_n "(cached) " >&6
     7052else
     7053  if test -n "$ac_ct_STRIP"; then
     7054  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
     7055else
     7056as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     7057for as_dir in $PATH
     7058do
     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
     7067done
     7068  done
     7069IFS=$as_save_IFS
     7070
     7071fi
     7072fi
     7073ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
     7074if 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; }
     7077else
     7078  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     7079$as_echo "no" >&6; }
     7080fi
     7081
     7082  if test "x$ac_ct_STRIP" = x; then
     7083    STRIP=":"
     7084  else
     7085    case $cross_compiling:$ac_tool_warned in
     7086yes:)
     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;}
     7089ac_tool_warned=yes ;;
     7090esac
     7091    STRIP=$ac_ct_STRIP
     7092  fi
     7093else
     7094  STRIP="$ac_cv_prog_STRIP"
     7095fi
     7096
     7097test -z "$STRIP" && STRIP=:
     7098
     7099
     7100
     7101
     7102
     7103
     7104if 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.
     7106set 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; }
     7109if ${ac_cv_prog_RANLIB+:} false; then :
     7110  $as_echo_n "(cached) " >&6
     7111else
     7112  if test -n "$RANLIB"; then
     7113  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
     7114else
     7115as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     7116for as_dir in $PATH
     7117do
     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
     7126done
     7127  done
     7128IFS=$as_save_IFS
     7129
     7130fi
     7131fi
     7132RANLIB=$ac_cv_prog_RANLIB
     7133if test -n "$RANLIB"; then
     7134  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
     7135$as_echo "$RANLIB" >&6; }
     7136else
     7137  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     7138$as_echo "no" >&6; }
     7139fi
     7140
     7141
     7142fi
     7143if 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.
     7146set 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; }
     7149if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
     7150  $as_echo_n "(cached) " >&6
     7151else
     7152  if test -n "$ac_ct_RANLIB"; then
     7153  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
     7154else
     7155as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     7156for as_dir in $PATH
     7157do
     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
     7166done
     7167  done
     7168IFS=$as_save_IFS
     7169
     7170fi
     7171fi
     7172ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
     7173if 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; }
     7176else
     7177  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     7178$as_echo "no" >&6; }
     7179fi
     7180
     7181  if test "x$ac_ct_RANLIB" = x; then
     7182    RANLIB=":"
     7183  else
     7184    case $cross_compiling:$ac_tool_warned in
     7185yes:)
     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;}
     7188ac_tool_warned=yes ;;
     7189esac
     7190    RANLIB=$ac_ct_RANLIB
     7191  fi
     7192else
     7193  RANLIB="$ac_cv_prog_RANLIB"
     7194fi
     7195
     7196test -z "$RANLIB" && RANLIB=:
     7197
     7198
     7199
     7200
     7201
     7202
     7203# Determine commands to create old-style static archives.
     7204old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
     7205old_postinstall_cmds='chmod 644 $oldlib'
     7206old_postuninstall_cmds=
     7207
     7208if 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"
     7218fi
     7219
     7220case $host_os in
     7221  darwin*)
     7222    lock_old_archive_extraction=yes ;;
     7223  *)
     7224    lock_old_archive_extraction=no ;;
     7225esac
     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.
     7266LTCC=${LTCC-"$CC"}
     7267
     7268# If no C compiler flags were specified, use CFLAGS.
     7269LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
     7270
     7271# Allow CC to be a program name with arguments.
     7272compiler=$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; }
     7278if ${lt_cv_sys_global_symbol_pipe+:} false; then :
     7279  $as_echo_n "(cached) " >&6
     7280else
     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.
     7286symcode='[BCDEGRST]'
     7287
     7288# Regexp to match symbols that can be accessed directly from C.
     7289sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
     7290
     7291# Define system-specific variables.
     7292case $host_os in
     7293aix*)
     7294  symcode='[BCDT]'
     7295  ;;
     7296cygwin* | mingw* | pw32* | cegcc*)
     7297  symcode='[ABCDGISTW]'
     7298  ;;
     7299hpux*)
     7300  if test ia64 = "$host_cpu"; then
     7301    symcode='[ABCDEGRST]'
     7302  fi
     7303  ;;
     7304irix* | nonstopux*)
     7305  symcode='[BCDEGRST]'
     7306  ;;
     7307osf*)
     7308  symcode='[BCDEGQRST]'
     7309  ;;
     7310solaris*)
     7311  symcode='[BDRT]'
     7312  ;;
     7313sco3.2v5*)
     7314  symcode='[DT]'
     7315  ;;
     7316sysv4.2uw2*)
     7317  symcode='[DT]'
     7318  ;;
     7319sysv5* | sco5v6* | unixware* | OpenUNIX*)
     7320  symcode='[ABDT]'
     7321  ;;
     7322sysv4)
     7323  symcode='[DFNSTU]'
     7324  ;;
     7325esac
     7326
     7327# If we're using GNU nm, then use its standard symbol codes.
     7328case `$NM -V 2>&1` in
     7329*GNU* | *'with BFD'*)
     7330  symcode='[ABCDGIRSTW]' ;;
     7331esac
     7332
     7333if 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'"
     7342else
     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=
     7348fi
     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.
     7353lt_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
     7359lt_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.
     7366lt_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
     7373opt_cr=
     7374case $build_os in
     7375mingw*)
     7376  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
     7377  ;;
     7378esac
     7379
     7380# Try without a prefix underscore, then with it.
     7381for 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
     7418extern "C" {
     7419#endif
     7420char nm_test_var;
     7421void nm_test_func(void);
     7422void nm_test_func(void){}
     7423#ifdef __cplusplus
     7424}
     7425#endif
     7426int 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
     7465extern "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.  */
     7475LT_DLSYM_CONST struct {
     7476  const char *name;
     7477  void       *address;
     7478}
     7479lt__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
     7490static 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
     7535done
     7536
     7537fi
     7538
     7539if test -z "$lt_cv_sys_global_symbol_pipe"; then
     7540  lt_cv_sys_global_symbol_to_cdecl=
     7541fi
     7542if 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; }
     7545else
     7546  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
     7547$as_echo "ok" >&6; }
     7548fi
     7549
     7550# Response file support.
     7551if test "$lt_cv_nm_interface" = "MS dumpbin"; then
     7552  nm_file_list_spec='@'
     7553elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
     7554  nm_file_list_spec='@'
     7555fi
     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.
     7597if test "${with_sysroot+set}" = set; then :
     7598  withval=$with_sysroot;
     7599else
     7600  with_sysroot=no
     7601fi
     7602
     7603
     7604lt_sysroot=
     7605case $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   ;;
     7621esac
     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; }
     7632if ${ac_cv_path_lt_DD+:} false; then :
     7633  $as_echo_n "(cached) " >&6
     7634else
     7635  printf 0123456789abcdef0123456789abcdef >conftest.i
     7636cat conftest.i conftest.i >conftest2.i
     7637: ${lt_DD:=$DD}
     7638if 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
     7642for as_dir in $PATH
     7643do
     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
     7650if "$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=:
     7653fi
     7654      $ac_path_lt_DD_found && break 3
     7655    done
     7656  done
     7657  done
     7658IFS=$as_save_IFS
     7659  if test -z "$ac_cv_path_lt_DD"; then
     7660    :
     7661  fi
     7662else
     7663  ac_cv_path_lt_DD=$lt_DD
     7664fi
     7665
     7666rm -f conftest.i conftest2.i conftest.out
     7667fi
     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; }
     7674if ${lt_cv_truncate_bin+:} false; then :
     7675  $as_echo_n "(cached) " >&6
     7676else
     7677  printf 0123456789abcdef0123456789abcdef >conftest.i
     7678cat conftest.i conftest.i >conftest2.i
     7679lt_cv_truncate_bin=
     7680if "$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"
     7683fi
     7684rm -f conftest.i conftest2.i conftest.out
     7685test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
     7686fi
     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.
     7697func_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.
     7711if test "${enable_libtool_lock+set}" = set; then :
     7712  enableval=$enable_libtool_lock;
     7713fi
     7714
     7715test 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.
     7719case $host in
     7720ia64-*-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
     7778mips64*-*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
     7814x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
     7815s390*-*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; }
     7891if ${lt_cv_cc_needs_belf+:} false; then :
     7892  $as_echo_n "(cached) " >&6
     7893else
     7894  ac_ext=c
     7895ac_cpp='$CPP $CPPFLAGS'
     7896ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     7897ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     7898ac_compiler_gnu=$ac_cv_c_compiler_gnu
     7899
     7900     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     7901/* end confdefs.h.  */
     7902
     7903int
     7904main ()
     7905{
     7906
     7907  ;
     7908  return 0;
     7909}
     7910_ACEOF
     7911if ac_fn_c_try_link "$LINENO"; then :
     7912  lt_cv_cc_needs_belf=yes
     7913else
     7914  lt_cv_cc_needs_belf=no
     7915fi
     7916rm -f core conftest.err conftest.$ac_objext \
     7917    conftest$ac_exeext conftest.$ac_ext
     7918     ac_ext=c
     7919ac_cpp='$CPP $CPPFLAGS'
     7920ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     7921ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     7922ac_compiler_gnu=$ac_cv_c_compiler_gnu
     7923
     7924fi
     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  ;;
     7969esac
     7970
     7971need_locks=$enable_libtool_lock
     7972
     7973if 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.
     7975set 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; }
     7978if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
     7979  $as_echo_n "(cached) " >&6
     7980else
     7981  if test -n "$MANIFEST_TOOL"; then
     7982  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
     7983else
     7984as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     7985for as_dir in $PATH
     7986do
     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
     7995done
     7996  done
     7997IFS=$as_save_IFS
     7998
     7999fi
     8000fi
     8001MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
     8002if test -n "$MANIFEST_TOOL"; then
     8003  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
     8004$as_echo "$MANIFEST_TOOL" >&6; }
     8005else
     8006  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8007$as_echo "no" >&6; }
     8008fi
     8009
     8010
     8011fi
     8012if 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.
     8015set 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; }
     8018if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
     8019  $as_echo_n "(cached) " >&6
     8020else
     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.
     8023else
     8024as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8025for as_dir in $PATH
     8026do
     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
     8035done
     8036  done
     8037IFS=$as_save_IFS
     8038
     8039fi
     8040fi
     8041ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
     8042if 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; }
     8045else
     8046  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8047$as_echo "no" >&6; }
     8048fi
     8049
     8050  if test "x$ac_ct_MANIFEST_TOOL" = x; then
     8051    MANIFEST_TOOL=":"
     8052  else
     8053    case $cross_compiling:$ac_tool_warned in
     8054yes:)
     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;}
     8057ac_tool_warned=yes ;;
     8058esac
     8059    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
     8060  fi
     8061else
     8062  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
     8063fi
     8064
     8065test -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; }
     8068if ${lt_cv_path_mainfest_tool+:} false; then :
     8069  $as_echo_n "(cached) " >&6
     8070else
     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*
     8079fi
     8080{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
     8081$as_echo "$lt_cv_path_mainfest_tool" >&6; }
     8082if test yes != "$lt_cv_path_mainfest_tool"; then
     8083  MANIFEST_TOOL=:
     8084fi
     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.
     8095set 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; }
     8098if ${ac_cv_prog_DSYMUTIL+:} false; then :
     8099  $as_echo_n "(cached) " >&6
     8100else
     8101  if test -n "$DSYMUTIL"; then
     8102  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
     8103else
     8104as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8105for as_dir in $PATH
     8106do
     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
     8115done
     8116  done
     8117IFS=$as_save_IFS
     8118
     8119fi
     8120fi
     8121DSYMUTIL=$ac_cv_prog_DSYMUTIL
     8122if test -n "$DSYMUTIL"; then
     8123  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
     8124$as_echo "$DSYMUTIL" >&6; }
     8125else
     8126  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8127$as_echo "no" >&6; }
     8128fi
     8129
     8130
     8131fi
     8132if 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.
     8135set 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; }
     8138if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
     8139  $as_echo_n "(cached) " >&6
     8140else
     8141  if test -n "$ac_ct_DSYMUTIL"; then
     8142  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
     8143else
     8144as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8145for as_dir in $PATH
     8146do
     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
     8155done
     8156  done
     8157IFS=$as_save_IFS
     8158
     8159fi
     8160fi
     8161ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
     8162if 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; }
     8165else
     8166  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8167$as_echo "no" >&6; }
     8168fi
     8169
     8170  if test "x$ac_ct_DSYMUTIL" = x; then
     8171    DSYMUTIL=":"
     8172  else
     8173    case $cross_compiling:$ac_tool_warned in
     8174yes:)
     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;}
     8177ac_tool_warned=yes ;;
     8178esac
     8179    DSYMUTIL=$ac_ct_DSYMUTIL
     8180  fi
     8181else
     8182  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
     8183fi
     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.
     8187set 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; }
     8190if ${ac_cv_prog_NMEDIT+:} false; then :
     8191  $as_echo_n "(cached) " >&6
     8192else
     8193  if test -n "$NMEDIT"; then
     8194  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
     8195else
     8196as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8197for as_dir in $PATH
     8198do
     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
     8207done
     8208  done
     8209IFS=$as_save_IFS
     8210
     8211fi
     8212fi
     8213NMEDIT=$ac_cv_prog_NMEDIT
     8214if test -n "$NMEDIT"; then
     8215  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
     8216$as_echo "$NMEDIT" >&6; }
     8217else
     8218  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8219$as_echo "no" >&6; }
     8220fi
     8221
     8222
     8223fi
     8224if 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.
     8227set 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; }
     8230if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
     8231  $as_echo_n "(cached) " >&6
     8232else
     8233  if test -n "$ac_ct_NMEDIT"; then
     8234  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
     8235else
     8236as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8237for as_dir in $PATH
     8238do
     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
     8247done
     8248  done
     8249IFS=$as_save_IFS
     8250
     8251fi
     8252fi
     8253ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
     8254if 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; }
     8257else
     8258  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8259$as_echo "no" >&6; }
     8260fi
     8261
     8262  if test "x$ac_ct_NMEDIT" = x; then
     8263    NMEDIT=":"
     8264  else
     8265    case $cross_compiling:$ac_tool_warned in
     8266yes:)
     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;}
     8269ac_tool_warned=yes ;;
     8270esac
     8271    NMEDIT=$ac_ct_NMEDIT
     8272  fi
     8273else
     8274  NMEDIT="$ac_cv_prog_NMEDIT"
     8275fi
     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.
     8279set 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; }
     8282if ${ac_cv_prog_LIPO+:} false; then :
     8283  $as_echo_n "(cached) " >&6
     8284else
     8285  if test -n "$LIPO"; then
     8286  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
     8287else
     8288as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8289for as_dir in $PATH
     8290do
     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
     8299done
     8300  done
     8301IFS=$as_save_IFS
     8302
     8303fi
     8304fi
     8305LIPO=$ac_cv_prog_LIPO
     8306if test -n "$LIPO"; then
     8307  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
     8308$as_echo "$LIPO" >&6; }
     8309else
     8310  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8311$as_echo "no" >&6; }
     8312fi
     8313
     8314
     8315fi
     8316if 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.
     8319set 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; }
     8322if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
     8323  $as_echo_n "(cached) " >&6
     8324else
     8325  if test -n "$ac_ct_LIPO"; then
     8326  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
     8327else
     8328as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8329for as_dir in $PATH
     8330do
     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
     8339done
     8340  done
     8341IFS=$as_save_IFS
     8342
     8343fi
     8344fi
     8345ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
     8346if 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; }
     8349else
     8350  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8351$as_echo "no" >&6; }
     8352fi
     8353
     8354  if test "x$ac_ct_LIPO" = x; then
     8355    LIPO=":"
     8356  else
     8357    case $cross_compiling:$ac_tool_warned in
     8358yes:)
     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;}
     8361ac_tool_warned=yes ;;
     8362esac
     8363    LIPO=$ac_ct_LIPO
     8364  fi
     8365else
     8366  LIPO="$ac_cv_prog_LIPO"
     8367fi
     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.
     8371set 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; }
     8374if ${ac_cv_prog_OTOOL+:} false; then :
     8375  $as_echo_n "(cached) " >&6
     8376else
     8377  if test -n "$OTOOL"; then
     8378  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
     8379else
     8380as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8381for as_dir in $PATH
     8382do
     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
     8391done
     8392  done
     8393IFS=$as_save_IFS
     8394
     8395fi
     8396fi
     8397OTOOL=$ac_cv_prog_OTOOL
     8398if test -n "$OTOOL"; then
     8399  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
     8400$as_echo "$OTOOL" >&6; }
     8401else
     8402  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8403$as_echo "no" >&6; }
     8404fi
     8405
     8406
     8407fi
     8408if 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.
     8411set 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; }
     8414if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
     8415  $as_echo_n "(cached) " >&6
     8416else
     8417  if test -n "$ac_ct_OTOOL"; then
     8418  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
     8419else
     8420as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8421for as_dir in $PATH
     8422do
     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
     8431done
     8432  done
     8433IFS=$as_save_IFS
     8434
     8435fi
     8436fi
     8437ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
     8438if 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; }
     8441else
     8442  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8443$as_echo "no" >&6; }
     8444fi
     8445
     8446  if test "x$ac_ct_OTOOL" = x; then
     8447    OTOOL=":"
     8448  else
     8449    case $cross_compiling:$ac_tool_warned in
     8450yes:)
     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;}
     8453ac_tool_warned=yes ;;
     8454esac
     8455    OTOOL=$ac_ct_OTOOL
     8456  fi
     8457else
     8458  OTOOL="$ac_cv_prog_OTOOL"
     8459fi
     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.
     8463set 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; }
     8466if ${ac_cv_prog_OTOOL64+:} false; then :
     8467  $as_echo_n "(cached) " >&6
     8468else
     8469  if test -n "$OTOOL64"; then
     8470  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
     8471else
     8472as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8473for as_dir in $PATH
     8474do
     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
     8483done
     8484  done
     8485IFS=$as_save_IFS
     8486
     8487fi
     8488fi
     8489OTOOL64=$ac_cv_prog_OTOOL64
     8490if test -n "$OTOOL64"; then
     8491  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
     8492$as_echo "$OTOOL64" >&6; }
     8493else
     8494  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8495$as_echo "no" >&6; }
     8496fi
     8497
     8498
     8499fi
     8500if 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.
     8503set 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; }
     8506if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
     8507  $as_echo_n "(cached) " >&6
     8508else
     8509  if test -n "$ac_ct_OTOOL64"; then
     8510  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
     8511else
     8512as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
     8513for as_dir in $PATH
     8514do
     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
     8523done
     8524  done
     8525IFS=$as_save_IFS
     8526
     8527fi
     8528fi
     8529ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
     8530if 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; }
     8533else
     8534  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     8535$as_echo "no" >&6; }
     8536fi
     8537
     8538  if test "x$ac_ct_OTOOL64" = x; then
     8539    OTOOL64=":"
     8540  else
     8541    case $cross_compiling:$ac_tool_warned in
     8542yes:)
     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;}
     8545ac_tool_warned=yes ;;
     8546esac
     8547    OTOOL64=$ac_ct_OTOOL64
     8548  fi
     8549else
     8550  OTOOL64="$ac_cv_prog_OTOOL64"
     8551fi
     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; }
     8581if ${lt_cv_apple_cc_single_mod+:} false; then :
     8582  $as_echo_n "(cached) " >&6
     8583else
     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
     8611fi
     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; }
     8617if ${lt_cv_ld_exported_symbols_list+:} false; then :
     8618  $as_echo_n "(cached) " >&6
     8619else
     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
     8627int
     8628main ()
     8629{
     8630
     8631  ;
     8632  return 0;
     8633}
     8634_ACEOF
     8635if ac_fn_c_try_link "$LINENO"; then :
     8636  lt_cv_ld_exported_symbols_list=yes
     8637else
     8638  lt_cv_ld_exported_symbols_list=no
     8639fi
     8640rm -f core conftest.err conftest.$ac_objext \
     8641    conftest$ac_exeext conftest.$ac_ext
     8642        LDFLAGS=$save_LDFLAGS
     8643
     8644fi
     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; }
     8650if ${lt_cv_ld_force_load+:} false; then :
     8651  $as_echo_n "(cached) " >&6
     8652else
     8653  lt_cv_ld_force_load=no
     8654      cat > conftest.c << _LT_EOF
     8655int 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
     8664int 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
     8679fi
     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]"
     8731func_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
     8752ac_ext=c
     8753ac_cpp='$CPP $CPPFLAGS'
     8754ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     8755ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     8756ac_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.
     8760if test -n "$CPP" && test -d "$CPP"; then
     8761  CPP=
     8762fi
     8763if test -z "$CPP"; then
     8764  if ${ac_cv_prog_CPP+:} false; then :
     8765  $as_echo_n "(cached) " >&6
     8766else
     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
     8771for ac_c_preproc_warn_flag in '' yes
     8772do
     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
     8788if ac_fn_c_try_cpp "$LINENO"; then :
     8789
     8790else
     8791  # Broken: fails on valid input.
     8792continue
     8793fi
     8794rm -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
     8802if ac_fn_c_try_cpp "$LINENO"; then :
     8803  # Broken: success on invalid input.
     8804continue
     8805else
     8806  # Passes both tests.
     8807ac_preproc_ok=:
     8808break
     8809fi
     8810rm -f conftest.err conftest.i conftest.$ac_ext
     8811
     8812done
     8813# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
     8814rm -f conftest.i conftest.err conftest.$ac_ext
     8815if $ac_preproc_ok; then :
     8816  break
     8817fi
     8818
     8819    done
     8820    ac_cv_prog_CPP=$CPP
     8821
     8822fi
     8823  CPP=$ac_cv_prog_CPP
     8824else
     8825  ac_cv_prog_CPP=$CPP
     8826fi
     8827{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
     8828$as_echo "$CPP" >&6; }
     8829ac_preproc_ok=false
     8830for ac_c_preproc_warn_flag in '' yes
     8831do
     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
     8847if ac_fn_c_try_cpp "$LINENO"; then :
     8848
     8849else
     8850  # Broken: fails on valid input.
     8851continue
     8852fi
     8853rm -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
     8861if ac_fn_c_try_cpp "$LINENO"; then :
     8862  # Broken: success on invalid input.
     8863continue
     8864else
     8865  # Passes both tests.
     8866ac_preproc_ok=:
     8867break
     8868fi
     8869rm -f conftest.err conftest.i conftest.$ac_ext
     8870
     8871done
     8872# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
     8873rm -f conftest.i conftest.err conftest.$ac_ext
     8874if $ac_preproc_ok; then :
     8875
     8876else
     8877  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
     8878$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
     8879as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
     8880See \`config.log' for more details" "$LINENO" 5; }
     8881fi
     8882
     8883ac_ext=c
     8884ac_cpp='$CPP $CPPFLAGS'
     8885ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     8886ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     8887ac_compiler_gnu=$ac_cv_c_compiler_gnu
     8888
     8889
    56738890{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
    56748891$as_echo_n "checking for ANSI C header files... " >&6; }
     
    58009017
    58019018
    5802 ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
    5803 if test "x$ac_cv_type_size_t" = xyes; then :
    5804 
    5805 else
     9019for ac_header in dlfcn.h
     9020do :
     9021  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
     9022"
     9023if test "x$ac_cv_header_dlfcn_h" = xyes; then :
     9024  cat >>confdefs.h <<_ACEOF
     9025#define HAVE_DLFCN_H 1
     9026_ACEOF
     9027
     9028fi
     9029
     9030done
     9031
     9032
     9033
     9034
     9035func_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.
     9058if 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
     9076else
     9077  enable_shared=yes
     9078fi
     9079
     9080
     9081
     9082
     9083
     9084
     9085
     9086
     9087
     9088  # Check whether --enable-static was given.
     9089if 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
     9107else
     9108  enable_static=yes
     9109fi
     9110
     9111
     9112
     9113
     9114
     9115
     9116
     9117
     9118
     9119
     9120# Check whether --with-pic was given.
     9121if 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
     9138else
     9139  pic_mode=default
     9140fi
     9141
     9142
     9143
     9144
     9145
     9146
     9147
     9148
     9149  # Check whether --enable-fast-install was given.
     9150if 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
     9168else
     9169  enable_fast_install=yes
     9170fi
     9171
     9172
     9173
     9174
     9175
     9176
     9177
     9178
     9179  shared_archive_member_spec=
     9180case $host,$enable_shared in
     9181power*-*-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.
     9186if 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
     9195else
     9196  if ${lt_cv_with_aix_soname+:} false; then :
     9197  $as_echo_n "(cached) " >&6
     9198else
     9199  lt_cv_with_aix_soname=aix
     9200fi
     9201
     9202    with_aix_soname=$lt_cv_with_aix_soname
     9203fi
     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  ;;
     9223esac
     9224
     9225
     9226
     9227
     9228
     9229
     9230
     9231
     9232
     9233
     9234# This can be used to rebuild libtool when needed
     9235LIBTOOL_DEPS=$ltmain
     9236
     9237# Always use our own libtool.
     9238LIBTOOL='$(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
     9269test -z "$LN_S" && LN_S="ln -s"
     9270
     9271
     9272
     9273
     9274
     9275
     9276
     9277
     9278
     9279
     9280
     9281
     9282
     9283
     9284if test -n "${ZSH_VERSION+set}"; then
     9285   setopt NO_GLOB_SUBST
     9286fi
     9287
     9288{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
     9289$as_echo_n "checking for objdir... " >&6; }
     9290if ${lt_cv_objdir+:} false; then :
     9291  $as_echo_n "(cached) " >&6
     9292else
     9293  rm -f .libs 2>/dev/null
     9294mkdir .libs 2>/dev/null
     9295if test -d .libs; then
     9296  lt_cv_objdir=.libs
     9297else
     9298  # MS-DOS does not allow filenames that begin with a dot.
     9299  lt_cv_objdir=_libs
     9300fi
     9301rmdir .libs 2>/dev/null
     9302fi
     9303{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
     9304$as_echo "$lt_cv_objdir" >&6; }
     9305objdir=$lt_cv_objdir
     9306
     9307
     9308
     9309
    58069310
    58079311cat >>confdefs.h <<_ACEOF
    5808 #define size_t unsigned int
     9312#define LT_OBJDIR "$lt_cv_objdir/"
    58099313_ACEOF
    58109314
    5811 fi
    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; }
    5817 if ${ac_cv_working_alloca_h+:} false; then :
     9315
     9316
     9317
     9318case $host_os in
     9319aix3*)
     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  ;;
     9328esac
     9329
     9330# Global variables:
     9331ofile=libtool
     9332can_build_shared=yes
     9333
     9334# All known linkers require a '.a' archive for static linking (except MSVC,
     9335# which needs '.lib').
     9336libext=a
     9337
     9338with_gnu_ld=$lt_cv_prog_gnu_ld
     9339
     9340old_CC=$CC
     9341old_CFLAGS=$CFLAGS
     9342
     9343# Set sane defaults for various variables
     9344test -z "$CC" && CC=cc
     9345test -z "$LTCC" && LTCC=$CC
     9346test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
     9347test -z "$LD" && LD=ld
     9348test -z "$ac_objext" && ac_objext=o
     9349
     9350func_cc_basename $compiler
     9351cc_basename=$func_cc_basename_result
     9352
     9353
     9354# Only perform the check for file, if the check method requires it
     9355test -z "$MAGIC_CMD" && MAGIC_CMD=file
     9356case $deplibs_check_method in
     9357file_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; }
     9361if ${lt_cv_path_MAGIC_CMD+:} false; then :
     9362  $as_echo_n "(cached) " >&6
     9363else
     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  ;;
     9407esac
     9408fi
     9409
     9410MAGIC_CMD=$lt_cv_path_MAGIC_CMD
     9411if test -n "$MAGIC_CMD"; then
     9412  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
     9413$as_echo "$MAGIC_CMD" >&6; }
     9414else
     9415  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     9416$as_echo "no" >&6; }
     9417fi
     9418
     9419
     9420
     9421
     9422
     9423if 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; }
     9427if ${lt_cv_path_MAGIC_CMD+:} false; then :
     9428  $as_echo_n "(cached) " >&6
     9429else
     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  ;;
     9473esac
     9474fi
     9475
     9476MAGIC_CMD=$lt_cv_path_MAGIC_CMD
     9477if test -n "$MAGIC_CMD"; then
     9478  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
     9479$as_echo "$MAGIC_CMD" >&6; }
     9480else
     9481  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     9482$as_echo "no" >&6; }
     9483fi
     9484
     9485
     9486  else
     9487    MAGIC_CMD=:
     9488  fi
     9489fi
     9490
     9491  fi
     9492  ;;
     9493esac
     9494
     9495# Use C for the default configuration in the libtool script
     9496
     9497lt_save_CC=$CC
     9498ac_ext=c
     9499ac_cpp='$CPP $CPPFLAGS'
     9500ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     9501ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     9502ac_compiler_gnu=$ac_cv_c_compiler_gnu
     9503
     9504
     9505# Source file extension for C test sources.
     9506ac_ext=c
     9507
     9508# Object file extension for compiled C test sources.
     9509objext=o
     9510objext=$objext
     9511
     9512# Code to be used in simple compile tests
     9513lt_simple_compile_test_code="int some_variable = 0;"
     9514
     9515# Code to be used in simple link tests
     9516lt_simple_link_test_code='int main(){return(0);}'
     9517
     9518
     9519
     9520
     9521
     9522
     9523
     9524# If no C compiler was specified, use CC.
     9525LTCC=${LTCC-"$CC"}
     9526
     9527# If no C compiler flags were specified, use CFLAGS.
     9528LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
     9529
     9530# Allow CC to be a program name with arguments.
     9531compiler=$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.
     9535compiler_DEFAULT=$CC
     9536
     9537# save warnings/boilerplate of simple test code
     9538ac_outfile=conftest.$ac_objext
     9539echo "$lt_simple_compile_test_code" >conftest.$ac_ext
     9540eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
     9541_lt_compiler_boilerplate=`cat conftest.err`
     9542$RM conftest*
     9543
     9544ac_outfile=conftest.$ac_objext
     9545echo "$lt_simple_link_test_code" >conftest.$ac_ext
     9546eval "$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...
     9555if test -n "$compiler"; then
     9556
     9557lt_prog_compiler_no_builtin_flag=
     9558
     9559if 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; }
     9569if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
     9570  $as_echo_n "(cached) " >&6
     9571else
     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
     9601fi
     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
     9605if 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"
     9607else
     9608    :
     9609fi
     9610
     9611fi
     9612
     9613
     9614
     9615
     9616
     9617
     9618  lt_prog_compiler_wl=
     9619lt_prog_compiler_pic=
     9620lt_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
     9950case $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    ;;
     9958esac
     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; }
     9962if ${lt_cv_prog_compiler_pic+:} false; then :
     9963  $as_echo_n "(cached) " >&6
     9964else
     9965  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
     9966fi
     9967{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
     9968$as_echo "$lt_cv_prog_compiler_pic" >&6; }
     9969lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
     9970
     9971#
     9972# Check to make sure the PIC flag actually works.
     9973#
     9974if 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; }
     9977if ${lt_cv_prog_compiler_pic_works+:} false; then :
     9978  $as_echo_n "(cached) " >&6
     9979else
     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
     10009fi
     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
     10013if 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
     10018else
     10019    lt_prog_compiler_pic=
     10020     lt_prog_compiler_can_build_shared=no
     10021fi
     10022
     10023fi
     10024
     10025
     10026
     10027
     10028
     10029
     10030
     10031
     10032
     10033
     10034
     10035#
     10036# Check to make sure the static flag actually works.
     10037#
     10038wl=$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; }
     10041if ${lt_cv_prog_compiler_static_works+:} false; then :
     10042  $as_echo_n "(cached) " >&6
     10043else
     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
     10066fi
     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
     10070if test yes = "$lt_cv_prog_compiler_static_works"; then
     10071    :
     10072else
     10073    lt_prog_compiler_static=
     10074fi
     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; }
     10084if ${lt_cv_prog_compiler_c_o+:} false; then :
     10085  $as_echo_n "(cached) " >&6
     10086else
     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
     10128fi
     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; }
     10139if ${lt_cv_prog_compiler_c_o+:} false; then :
     10140  $as_echo_n "(cached) " >&6
     10141else
     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
     10183fi
     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
     10190hard_links=nottested
     10191if 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
     10208else
     10209  need_locks=no
     10210fi
     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
     10775else
     10776  if ${lt_cv_aix_libpath_+:} false; then :
    581810777  $as_echo_n "(cached) " >&6
    581910778else
    582010779  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    582110780/* end confdefs.h.  */
    5822 #include <alloca.h>
     10781
    582310782int
    582410783main ()
    582510784{
    5826 char *p = (char *) alloca (2 * sizeof (int));
    5827                           if (p) return 0;
     10785
    582810786  ;
    582910787  return 0;
     
    583110789_ACEOF
    583210790if ac_fn_c_try_link "$LINENO"; then :
    5833   ac_cv_working_alloca_h=yes
    5834 else
    5835   ac_cv_working_alloca_h=no
     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
    583610804fi
    583710805rm -f core conftest.err conftest.$ac_objext \
    583810806    conftest$ac_exeext conftest.$ac_ext
    5839 fi
    5840 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
    5841 $as_echo "$ac_cv_working_alloca_h" >&6; }
    5842 if test $ac_cv_working_alloca_h = yes; then
    5843 
    5844 $as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h
    5845 
    5846 fi
    5847 
    5848 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
    5849 $as_echo_n "checking for alloca... " >&6; }
    5850 if ${ac_cv_func_alloca_works+:} false; then :
     10807  if test -z "$lt_cv_aix_libpath_"; then
     10808    lt_cv_aix_libpath_=/usr/lib:/lib
     10809  fi
     10810
     10811fi
     10812
     10813  aix_libpath=$lt_cv_aix_libpath_
     10814fi
     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
     10828else
     10829  if ${lt_cv_aix_libpath_+:} false; then :
    585110830  $as_echo_n "(cached) " >&6
    585210831else
    585310832  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    585410833/* 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 */
    5869 void *alloca (size_t);
    5870 #    endif
    5871 #   endif
    5872 #  endif
    5873 # endif
    5874 #endif
    587510834
    587610835int
    587710836main ()
    587810837{
    5879 char *p = (char *) alloca (1);
    5880                                     if (p) return 0;
     10838
    588110839  ;
    588210840  return 0;
     
    588410842_ACEOF
    588510843if ac_fn_c_try_link "$LINENO"; then :
    5886   ac_cv_func_alloca_works=yes
    5887 else
    5888   ac_cv_func_alloca_works=no
     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
    588910857fi
    589010858rm -f core conftest.err conftest.$ac_objext \
    589110859    conftest$ac_exeext conftest.$ac_ext
    5892 fi
    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 
    5896 if test $ac_cv_func_alloca_works = yes; then
    5897 
    5898 $as_echo "#define HAVE_ALLOCA 1" >>confdefs.h
    5899 
    5900 else
    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 
    5906 ALLOCA=\${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; }
    5913 if ${ac_cv_os_cray+:} false; then :
     10860  if test -z "$lt_cv_aix_libpath_"; then
     10861    lt_cv_aix_libpath_=/usr/lib:/lib
     10862  fi
     10863
     10864fi
     10865
     10866  aix_libpath=$lt_cv_aix_libpath_
     10867fi
     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; }
     11111if ${lt_cv_prog_compiler__b+:} false; then :
    591411112  $as_echo_n "(cached) " >&6
    591511113else
     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
     11136fi
     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
     11140if 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'
     11142else
     11143    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
     11144fi
     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; }
     11180if ${lt_cv_irix_exported_symbol+:} false; then :
     11181  $as_echo_n "(cached) " >&6
     11182else
     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.  */
     11187int foo (void) { return 0; }
     11188_ACEOF
     11189if ac_fn_c_try_link "$LINENO"; then :
     11190  lt_cv_irix_exported_symbol=yes
     11191else
     11192  lt_cv_irix_exported_symbol=no
     11193fi
     11194rm -f core conftest.err conftest.$ac_objext \
     11195    conftest$ac_exeext conftest.$ac_ext
     11196           LDFLAGS=$save_LDFLAGS
     11197fi
     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; }
     11482test no = "$ld_shlibs" && can_build_shared=no
     11483
     11484with_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#
     11503case "x$archive_cmds_need_lc" in
     11504x|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; }
     11519if ${lt_cv_archive_cmds_need_lc+:} false; then :
     11520  $as_echo_n "(cached) " >&6
     11521else
     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
     11559fi
     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  ;;
     11567esac
     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
     11723if 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 '
     11765BEGIN {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`
     11791else
     11792  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
     11793fi
     11794library_names_spec=
     11795libname_spec='lib$name'
     11796soname_spec=
     11797shrext_cmds=.so
     11798postinstall_cmds=
     11799postuninstall_cmds=
     11800finish_cmds=
     11801finish_eval=
     11802shlibpath_var=
     11803shlibpath_overrides_runpath=unknown
     11804version_type=none
     11805dynamic_linker="$host_os ld.so"
     11806sys_lib_dlsearch_path_spec="/lib /usr/lib"
     11807need_lib_prefix=unknown
     11808hardcode_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
     11812need_version=unknown
     11813
     11814
     11815
     11816case $host_os in
     11817aix3*)
     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
     11826aix[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
     11920amigaos*)
     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
     11935beos*)
     11936  library_names_spec='$libname$shared_ext'
     11937  dynamic_linker="$host_os ld.so"
     11938  shlibpath_var=LIBRARY_PATH
     11939  ;;
     11940
     11941bsdi[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
     11955cygwin* | 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
     12065darwin* | 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
     12080dgux*)
     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
     12089freebsd* | 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
     12134haiku*)
     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
     12147hpux9* | 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
     12196interix[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
     12208irix5* | 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.
     12246linux*oldld* | linux*aout* | linux*coff*)
     12247  dynamic_linker=no
     12248  ;;
     12249
     12250linux*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.
     12271linux* | 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
     12284else
     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
     12293int
     12294main ()
     12295{
     12296
     12297  ;
     12298  return 0;
     12299}
     12300_ACEOF
     12301if 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
     12304fi
     12305fi
     12306rm -f core conftest.err conftest.$ac_objext \
     12307    conftest$ac_exeext conftest.$ac_ext
     12308    LDFLAGS=$save_LDFLAGS
     12309    libdir=$save_libdir
     12310
     12311fi
     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
     12340netbsdelf*-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
     12352netbsd*)
     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
     12370newsos6)
     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
     12389openbsd* | 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
     12404os2*)
     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
     12434osf3* | 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
     12445rdos*)
     12446  dynamic_linker=no
     12447  ;;
     12448
     12449solaris*)
     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
     12462sunos4*)
     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
     12474sysv4 | 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
     12497sysv4*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
     12506sysv5* | 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
     12528tpf*)
     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
     12539uts4*)
     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  ;;
     12549esac
     12550{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
     12551$as_echo "$dynamic_linker" >&6; }
     12552test no = "$dynamic_linker" && can_build_shared=no
     12553
     12554variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
     12555if test yes = "$GCC"; then
     12556  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
     12557fi
     12558
     12559if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
     12560  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
     12561fi
     12562
     12563if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
     12564  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
     12565fi
     12566
     12567# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
     12568configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
     12569
     12570# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
     12571func_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
     12574configure_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; }
     12674hardcode_action=
     12675if 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
     12692else
     12693  # We cannot hardcode anything, or else we can only hardcode existing
     12694  # directories.
     12695  hardcode_action=unsupported
     12696fi
     12697{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
     12698$as_echo "$hardcode_action" >&6; }
     12699
     12700if test relink = "$hardcode_action" ||
     12701   test yes = "$inherit_rpath"; then
     12702  # Fast installation is not supported
     12703  enable_fast_install=no
     12704elif test yes = "$shlibpath_overrides_runpath" ||
     12705     test no = "$enable_shared"; then
     12706  # Fast installation is not necessary
     12707  enable_fast_install=needless
     12708fi
     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
     12719else
     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; }
     12744if ${ac_cv_lib_dl_dlopen+:} false; then :
     12745  $as_echo_n "(cached) " >&6
     12746else
     12747  ac_check_lib_save_LIBS=$LIBS
     12748LIBS="-ldl  $LIBS"
     12749cat 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
     12756extern "C"
     12757#endif
     12758char dlopen ();
     12759int
     12760main ()
     12761{
     12762return dlopen ();
     12763  ;
     12764  return 0;
     12765}
     12766_ACEOF
     12767if ac_fn_c_try_link "$LINENO"; then :
     12768  ac_cv_lib_dl_dlopen=yes
     12769else
     12770  ac_cv_lib_dl_dlopen=no
     12771fi
     12772rm -f core conftest.err conftest.$ac_objext \
     12773    conftest$ac_exeext conftest.$ac_ext
     12774LIBS=$ac_check_lib_save_LIBS
     12775fi
     12776{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
     12777$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
     12778if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
     12779  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
     12780else
     12781
     12782    lt_cv_dlopen=dyld
     12783    lt_cv_dlopen_libs=
     12784    lt_cv_dlopen_self=yes
     12785
     12786fi
     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"
     12800if test "x$ac_cv_func_shl_load" = xyes; then :
     12801  lt_cv_dlopen=shl_load
     12802else
     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; }
     12805if ${ac_cv_lib_dld_shl_load+:} false; then :
     12806  $as_echo_n "(cached) " >&6
     12807else
     12808  ac_check_lib_save_LIBS=$LIBS
     12809LIBS="-ldld  $LIBS"
     12810cat 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
     12817extern "C"
     12818#endif
     12819char shl_load ();
     12820int
     12821main ()
     12822{
     12823return shl_load ();
     12824  ;
     12825  return 0;
     12826}
     12827_ACEOF
     12828if ac_fn_c_try_link "$LINENO"; then :
     12829  ac_cv_lib_dld_shl_load=yes
     12830else
     12831  ac_cv_lib_dld_shl_load=no
     12832fi
     12833rm -f core conftest.err conftest.$ac_objext \
     12834    conftest$ac_exeext conftest.$ac_ext
     12835LIBS=$ac_check_lib_save_LIBS
     12836fi
     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; }
     12839if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
     12840  lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
     12841else
     12842  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
     12843if test "x$ac_cv_func_dlopen" = xyes; then :
     12844  lt_cv_dlopen=dlopen
     12845else
     12846  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
     12847$as_echo_n "checking for dlopen in -ldl... " >&6; }
     12848if ${ac_cv_lib_dl_dlopen+:} false; then :
     12849  $as_echo_n "(cached) " >&6
     12850else
     12851  ac_check_lib_save_LIBS=$LIBS
     12852LIBS="-ldl  $LIBS"
     12853cat 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
     12860extern "C"
     12861#endif
     12862char dlopen ();
     12863int
     12864main ()
     12865{
     12866return dlopen ();
     12867  ;
     12868  return 0;
     12869}
     12870_ACEOF
     12871if ac_fn_c_try_link "$LINENO"; then :
     12872  ac_cv_lib_dl_dlopen=yes
     12873else
     12874  ac_cv_lib_dl_dlopen=no
     12875fi
     12876rm -f core conftest.err conftest.$ac_objext \
     12877    conftest$ac_exeext conftest.$ac_ext
     12878LIBS=$ac_check_lib_save_LIBS
     12879fi
     12880{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
     12881$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
     12882if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
     12883  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
     12884else
     12885  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
     12886$as_echo_n "checking for dlopen in -lsvld... " >&6; }
     12887if ${ac_cv_lib_svld_dlopen+:} false; then :
     12888  $as_echo_n "(cached) " >&6
     12889else
     12890  ac_check_lib_save_LIBS=$LIBS
     12891LIBS="-lsvld  $LIBS"
     12892cat 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
     12899extern "C"
     12900#endif
     12901char dlopen ();
     12902int
     12903main ()
     12904{
     12905return dlopen ();
     12906  ;
     12907  return 0;
     12908}
     12909_ACEOF
     12910if ac_fn_c_try_link "$LINENO"; then :
     12911  ac_cv_lib_svld_dlopen=yes
     12912else
     12913  ac_cv_lib_svld_dlopen=no
     12914fi
     12915rm -f core conftest.err conftest.$ac_objext \
     12916    conftest$ac_exeext conftest.$ac_ext
     12917LIBS=$ac_check_lib_save_LIBS
     12918fi
     12919{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
     12920$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
     12921if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
     12922  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
     12923else
     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; }
     12926if ${ac_cv_lib_dld_dld_link+:} false; then :
     12927  $as_echo_n "(cached) " >&6
     12928else
     12929  ac_check_lib_save_LIBS=$LIBS
     12930LIBS="-ldld  $LIBS"
     12931cat 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
     12938extern "C"
     12939#endif
     12940char dld_link ();
     12941int
     12942main ()
     12943{
     12944return dld_link ();
     12945  ;
     12946  return 0;
     12947}
     12948_ACEOF
     12949if ac_fn_c_try_link "$LINENO"; then :
     12950  ac_cv_lib_dld_dld_link=yes
     12951else
     12952  ac_cv_lib_dld_dld_link=no
     12953fi
     12954rm -f core conftest.err conftest.$ac_objext \
     12955    conftest$ac_exeext conftest.$ac_ext
     12956LIBS=$ac_check_lib_save_LIBS
     12957fi
     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; }
     12960if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
     12961  lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
     12962fi
     12963
     12964
     12965fi
     12966
     12967
     12968fi
     12969
     12970
     12971fi
     12972
     12973
     12974fi
     12975
     12976
     12977fi
     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; }
     13001if ${lt_cv_dlopen_self+:} false; then :
     13002  $as_echo_n "(cached) " >&6
     13003else
     13004          if test yes = "$cross_compiling"; then :
     13005  lt_cv_dlopen_self=cross
     13006else
     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))
     13054int fnord () __attribute__((visibility("default")));
     13055#endif
     13056
     13057int fnord () { return 42; }
     13058int 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
     13095fi
     13096rm -fr conftest*
     13097
     13098
     13099fi
     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; }
     13107if ${lt_cv_dlopen_self_static+:} false; then :
     13108  $as_echo_n "(cached) " >&6
     13109else
     13110          if test yes = "$cross_compiling"; then :
     13111  lt_cv_dlopen_self_static=cross
     13112else
     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))
     13160int fnord () __attribute__((visibility("default")));
     13161#endif
     13162
     13163int fnord () { return 42; }
     13164int 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
     13201fi
     13202rm -fr conftest*
     13203
     13204
     13205fi
     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
     13225fi
     13226
     13227
     13228
     13229
     13230
     13231
     13232
     13233
     13234
     13235
     13236
     13237
     13238
     13239
     13240
     13241
     13242
     13243striplib=
     13244old_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; }
     13247if 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; }
     13252else
     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
     13271fi
     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
     13328fi
     13329ac_ext=c
     13330ac_cpp='$CPP $CPPFLAGS'
     13331ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     13332ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     13333ac_compiler_gnu=$ac_cv_c_compiler_gnu
     13334
     13335CC=$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
     13341ac_cpp='$CXXCPP $CPPFLAGS'
     13342ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     13343ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     13344ac_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; }
     13347if test -z "$CXXCPP"; then
     13348  if ${ac_cv_prog_CXXCPP+:} false; then :
     13349  $as_echo_n "(cached) " >&6
     13350else
     13351      # Double quotes because CXXCPP needs to be expanded
     13352    for CXXCPP in "$CXX -E" "/lib/cpp"
     13353    do
     13354      ac_preproc_ok=false
     13355for ac_cxx_preproc_warn_flag in '' yes
     13356do
     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.
    591613363  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    591713364/* end confdefs.h.  */
    5918 #if defined CRAY && ! defined CRAY2
    5919 webecray
     13365#ifdef __STDC__
     13366# include <limits.h>
    592013367#else
    5921 wenotbecray
     13368# include <assert.h>
    592213369#endif
    5923 
     13370                     Syntax error
    592413371_ACEOF
    5925 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
    5926   $EGREP "webecray" >/dev/null 2>&1; then :
    5927   ac_cv_os_cray=yes
    5928 else
    5929   ac_cv_os_cray=no
    5930 fi
    5931 rm -f conftest*
    5932 
    5933 fi
    5934 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
    5935 $as_echo "$ac_cv_os_cray" >&6; }
    5936 if 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`
    5939 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
    5940 if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
    5941 
    5942 cat >>confdefs.h <<_ACEOF
    5943 #define CRAY_STACKSEG_END $ac_func
    5944 _ACEOF
    5945 
    5946     break
    5947 fi
    5948 
    5949   done
    5950 fi
    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; }
    5954 if ${ac_cv_c_stack_direction+:} false; then :
    5955   $as_echo_n "(cached) " >&6
    5956 else
    5957   if test "$cross_compiling" = yes; then :
    5958   ac_cv_c_stack_direction=0
    5959 else
     13372if ac_fn_cxx_try_cpp "$LINENO"; then :
     13373
     13374else
     13375  # Broken: fails on valid input.
     13376continue
     13377fi
     13378rm -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.
    596013382  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    596113383/* end confdefs.h.  */
    5962 $ac_includes_default
     13384#include <ac_nonexistent.h>
     13385_ACEOF
     13386if ac_fn_cxx_try_cpp "$LINENO"; then :
     13387  # Broken: success on invalid input.
     13388continue
     13389else
     13390  # Passes both tests.
     13391ac_preproc_ok=:
     13392break
     13393fi
     13394rm -f conftest.err conftest.i conftest.$ac_ext
     13395
     13396done
     13397# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
     13398rm -f conftest.i conftest.err conftest.$ac_ext
     13399if $ac_preproc_ok; then :
     13400  break
     13401fi
     13402
     13403    done
     13404    ac_cv_prog_CXXCPP=$CXXCPP
     13405
     13406fi
     13407  CXXCPP=$ac_cv_prog_CXXCPP
     13408else
     13409  ac_cv_prog_CXXCPP=$CXXCPP
     13410fi
     13411{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
     13412$as_echo "$CXXCPP" >&6; }
     13413ac_preproc_ok=false
     13414for ac_cxx_preproc_warn_flag in '' yes
     13415do
     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
     13431if ac_fn_cxx_try_cpp "$LINENO"; then :
     13432
     13433else
     13434  # Broken: fails on valid input.
     13435continue
     13436fi
     13437rm -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
     13445if ac_fn_cxx_try_cpp "$LINENO"; then :
     13446  # Broken: success on invalid input.
     13447continue
     13448else
     13449  # Passes both tests.
     13450ac_preproc_ok=:
     13451break
     13452fi
     13453rm -f conftest.err conftest.i conftest.$ac_ext
     13454
     13455done
     13456# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
     13457rm -f conftest.i conftest.err conftest.$ac_ext
     13458if $ac_preproc_ok; then :
     13459
     13460else
     13461  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
     13462$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
     13463as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
     13464See \`config.log' for more details" "$LINENO" 5; }
     13465fi
     13466
     13467ac_ext=c
     13468ac_cpp='$CPP $CPPFLAGS'
     13469ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     13470ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     13471ac_compiler_gnu=$ac_cv_c_compiler_gnu
     13472
     13473else
     13474  _lt_caught_CXX_error=yes
     13475fi
     13476
     13477ac_ext=cpp
     13478ac_cpp='$CXXCPP $CPPFLAGS'
     13479ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     13480ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     13481ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
     13482
     13483archive_cmds_need_lc_CXX=no
     13484allow_undefined_flag_CXX=
     13485always_export_symbols_CXX=no
     13486archive_expsym_cmds_CXX=
     13487compiler_needs_object_CXX=no
     13488export_dynamic_flag_spec_CXX=
     13489hardcode_direct_CXX=no
     13490hardcode_direct_absolute_CXX=no
     13491hardcode_libdir_flag_spec_CXX=
     13492hardcode_libdir_separator_CXX=
     13493hardcode_minus_L_CXX=no
     13494hardcode_shlibpath_var_CXX=unsupported
     13495hardcode_automatic_CXX=no
     13496inherit_rpath_CXX=no
     13497module_cmds_CXX=
     13498module_expsym_cmds_CXX=
     13499link_all_deplibs_CXX=unknown
     13500old_archive_cmds_CXX=$old_archive_cmds
     13501reload_flag_CXX=$reload_flag
     13502reload_cmds_CXX=$reload_cmds
     13503no_undefined_flag_CXX=
     13504whole_archive_flag_spec_CXX=
     13505enable_shared_with_static_runtimes_CXX=no
     13506
     13507# Source file extension for C++ test sources.
     13508ac_ext=cpp
     13509
     13510# Object file extension for compiled C++ test sources.
     13511objext=o
     13512objext_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.
     13518if 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.
     13533LTCC=${LTCC-"$CC"}
     13534
     13535# If no C compiler flags were specified, use CFLAGS.
     13536LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
     13537
     13538# Allow CC to be a program name with arguments.
     13539compiler=$CC
     13540
     13541
     13542  # save warnings/boilerplate of simple test code
     13543  ac_outfile=conftest.$ac_objext
     13544echo "$lt_simple_compile_test_code" >conftest.$ac_ext
     13545eval "$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
     13550echo "$lt_simple_link_test_code" >conftest.$ac_ext
     13551eval "$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
     13580cc_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.
     13598if test "${with_gnu_ld+set}" = set; then :
     13599  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
     13600else
     13601  with_gnu_ld=no
     13602fi
     13603
     13604ac_prog=ld
     13605if 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
     13636elif 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; }
     13639else
     13640  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
     13641$as_echo_n "checking for non-GNU ld... " >&6; }
     13642fi
     13643if ${lt_cv_path_LD+:} false; then :
     13644  $as_echo_n "(cached) " >&6
     13645else
     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
     13667else
     13668  lt_cv_path_LD=$LD # Let the user override the test with a path.
     13669fi
     13670fi
     13671
     13672LD=$lt_cv_path_LD
     13673if test -n "$LD"; then
     13674  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
     13675$as_echo "$LD" >&6; }
     13676else
     13677  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
     13678$as_echo "no" >&6; }
     13679fi
     13680test -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; }
     13683if ${lt_cv_prog_gnu_ld+:} false; then :
     13684  $as_echo_n "(cached) " >&6
     13685else
     13686  # I'd rather use --version here, but apparently some GNU lds only accept -v.
     13687case `$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  ;;
     13694esac
     13695fi
     13696{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
     13697$as_echo "$lt_cv_prog_gnu_ld" >&6; }
     13698with_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
     13889else
     13890  if ${lt_cv_aix_libpath__CXX+:} false; then :
     13891  $as_echo_n "(cached) " >&6
     13892else
     13893  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     13894/* end confdefs.h.  */
     13895
    596313896int
    5964 find_stack_direction (int *addr, int depth)
     13897main ()
    596513898{
    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;
    5972 }
    5973 
    5974 int
    5975 main (int argc, char **argv)
    5976 {
    5977   return find_stack_direction (0, argc + !argv + 20) < 0;
     13899
     13900  ;
     13901  return 0;
    597813902}
    597913903_ACEOF
    5980 if ac_fn_c_try_run "$LINENO"; then :
    5981   ac_cv_c_stack_direction=1
    5982 else
    5983   ac_cv_c_stack_direction=-1
    5984 fi
    5985 rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
    5986   conftest.$ac_objext conftest.beam conftest.$ac_ext
    5987 fi
    5988 
    5989 fi
    5990 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
    5991 $as_echo "$ac_cv_c_stack_direction" >&6; }
    5992 cat >>confdefs.h <<_ACEOF
    5993 #define STACK_DIRECTION $ac_cv_c_stack_direction
     13904if 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
     13918fi
     13919rm -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
     13925fi
     13926
     13927  aix_libpath=$lt_cv_aix_libpath__CXX
     13928fi
     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
     13943else
     13944  if ${lt_cv_aix_libpath__CXX+:} false; then :
     13945  $as_echo_n "(cached) " >&6
     13946else
     13947  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     13948/* end confdefs.h.  */
     13949
     13950int
     13951main ()
     13952{
     13953
     13954  ;
     13955  return 0;
     13956}
    599413957_ACEOF
    5995 
    5996 
    5997 fi
    5998 
    5999 for ac_header in fenv.h float.h inttypes.h libintl.h limits.h malloc.h stddef.h stdlib.h string.h unistd.h
     13958if 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
     13972fi
     13973rm -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
     13979fi
     13980
     13981  aix_libpath=$lt_cv_aix_libpath__CXX
     13982fi
     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:
     14836predep_objects_CXX=
     14837postdep_objects_CXX=
     14838predeps_CXX=
     14839postdeps_CXX=
     14840compiler_lib_search_path_CXX=
     14841
     14842cat > conftest.$ac_ext <<_LT_EOF
     14843class Foo
     14844{
     14845public:
     14846  Foo (void) { a = 0; }
     14847private:
     14848  int a;
     14849};
     14850_LT_EOF
     14851
     14852
     14853_lt_libdeps_save_CFLAGS=$CFLAGS
     14854case "$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" ;;
     14858esac
     14859
     14860if { { 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
     14951else
     14952  echo "libtool.m4: error: problem compiling CXX test program"
     14953fi
     14954
     14955$RM -f confest.$objext
     14956CFLAGS=$_lt_libdeps_save_CFLAGS
     14957
     14958# PORTME: override above test on systems where it is broken
     14959case $host_os in
     14960interix[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  ;;
     14967esac
     14968
     14969
     14970case " $postdeps_CXX " in
     14971*" -lc "*) archive_cmds_need_lc_CXX=no ;;
     14972esac
     14973 compiler_lib_search_dirs_CXX=
     14974if 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!^ !!'`
     14976fi
     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=
     15009lt_prog_compiler_pic_CXX=
     15010lt_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
     15334case $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    ;;
     15342esac
     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; }
     15346if ${lt_cv_prog_compiler_pic_CXX+:} false; then :
     15347  $as_echo_n "(cached) " >&6
     15348else
     15349  lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX
     15350fi
     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; }
     15353lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX
     15354
     15355#
     15356# Check to make sure the PIC flag actually works.
     15357#
     15358if 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; }
     15361if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then :
     15362  $as_echo_n "(cached) " >&6
     15363else
     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
     15393fi
     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
     15397if 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
     15402else
     15403    lt_prog_compiler_pic_CXX=
     15404     lt_prog_compiler_can_build_shared_CXX=no
     15405fi
     15406
     15407fi
     15408
     15409
     15410
     15411
     15412
     15413#
     15414# Check to make sure the static flag actually works.
     15415#
     15416wl=$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; }
     15419if ${lt_cv_prog_compiler_static_works_CXX+:} false; then :
     15420  $as_echo_n "(cached) " >&6
     15421else
     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
     15444fi
     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
     15448if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then
     15449    :
     15450else
     15451    lt_prog_compiler_static_CXX=
     15452fi
     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; }
     15459if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
     15460  $as_echo_n "(cached) " >&6
     15461else
     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
     15503fi
     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; }
     15511if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
     15512  $as_echo_n "(cached) " >&6
     15513else
     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
     15555fi
     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
     15562hard_links=nottested
     15563if 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
     15580else
     15581  need_locks=no
     15582fi
     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; }
     15631test no = "$ld_shlibs_CXX" && can_build_shared=no
     15632
     15633with_gnu_ld_CXX=$with_gnu_ld
     15634
     15635
     15636
     15637
     15638
     15639
     15640#
     15641# Do we need to explicitly link libc?
     15642#
     15643case "x$archive_cmds_need_lc_CXX" in
     15644x|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; }
     15659if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then :
     15660  $as_echo_n "(cached) " >&6
     15661else
     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
     15699fi
     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  ;;
     15707esac
     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
     15773library_names_spec=
     15774libname_spec='lib$name'
     15775soname_spec=
     15776shrext_cmds=.so
     15777postinstall_cmds=
     15778postuninstall_cmds=
     15779finish_cmds=
     15780finish_eval=
     15781shlibpath_var=
     15782shlibpath_overrides_runpath=unknown
     15783version_type=none
     15784dynamic_linker="$host_os ld.so"
     15785sys_lib_dlsearch_path_spec="/lib /usr/lib"
     15786need_lib_prefix=unknown
     15787hardcode_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
     15791need_version=unknown
     15792
     15793
     15794
     15795case $host_os in
     15796aix3*)
     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
     15805aix[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
     15899amigaos*)
     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
     15914beos*)
     15915  library_names_spec='$libname$shared_ext'
     15916  dynamic_linker="$host_os ld.so"
     15917  shlibpath_var=LIBRARY_PATH
     15918  ;;
     15919
     15920bsdi[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
     15934cygwin* | 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
     16043darwin* | 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
     16057dgux*)
     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
     16066freebsd* | 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
     16111haiku*)
     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
     16124hpux9* | 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
     16173interix[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
     16185irix5* | 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.
     16223linux*oldld* | linux*aout* | linux*coff*)
     16224  dynamic_linker=no
     16225  ;;
     16226
     16227linux*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.
     16248linux* | 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
     16261else
     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
     16270int
     16271main ()
     16272{
     16273
     16274  ;
     16275  return 0;
     16276}
     16277_ACEOF
     16278if 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
     16281fi
     16282fi
     16283rm -f core conftest.err conftest.$ac_objext \
     16284    conftest$ac_exeext conftest.$ac_ext
     16285    LDFLAGS=$save_LDFLAGS
     16286    libdir=$save_libdir
     16287
     16288fi
     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
     16317netbsdelf*-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
     16329netbsd*)
     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
     16347newsos6)
     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
     16366openbsd* | 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
     16381os2*)
     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
     16411osf3* | 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
     16422rdos*)
     16423  dynamic_linker=no
     16424  ;;
     16425
     16426solaris*)
     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
     16439sunos4*)
     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
     16451sysv4 | 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
     16474sysv4*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
     16483sysv5* | 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
     16505tpf*)
     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
     16516uts4*)
     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  ;;
     16526esac
     16527{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
     16528$as_echo "$dynamic_linker" >&6; }
     16529test no = "$dynamic_linker" && can_build_shared=no
     16530
     16531variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
     16532if test yes = "$GCC"; then
     16533  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
     16534fi
     16535
     16536if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
     16537  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
     16538fi
     16539
     16540if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
     16541  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
     16542fi
     16543
     16544# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
     16545configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
     16546
     16547# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
     16548func_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
     16551configure_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; }
     16594hardcode_action_CXX=
     16595if 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
     16612else
     16613  # We cannot hardcode anything, or else we can only hardcode existing
     16614  # directories.
     16615  hardcode_action_CXX=unsupported
     16616fi
     16617{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
     16618$as_echo "$hardcode_action_CXX" >&6; }
     16619
     16620if test relink = "$hardcode_action_CXX" ||
     16621   test yes = "$inherit_rpath_CXX"; then
     16622  # Fast installation is not supported
     16623  enable_fast_install=no
     16624elif test yes = "$shlibpath_overrides_runpath" ||
     16625     test no = "$enable_shared"; then
     16626  # Fast installation is not necessary
     16627  enable_fast_install=needless
     16628fi
     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
     16648fi # test yes != "$_lt_caught_CXX_error"
     16649
     16650ac_ext=c
     16651ac_cpp='$CPP $CPPFLAGS'
     16652ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
     16653ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
     16654ac_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; }
     16683if ${ac_cv_lib_fibre_Fibre__yield+:} false; then :
     16684  $as_echo_n "(cached) " >&6
     16685else
     16686  ac_check_lib_save_LIBS=$LIBS
     16687LIBS="-lfibre  $LIBS"
     16688cat 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
     16695extern "C"
     16696#endif
     16697char Fibre::yield ();
     16698int
     16699main ()
     16700{
     16701return Fibre::yield ();
     16702  ;
     16703  return 0;
     16704}
     16705_ACEOF
     16706if ac_fn_c_try_link "$LINENO"; then :
     16707  ac_cv_lib_fibre_Fibre__yield=yes
     16708else
     16709  ac_cv_lib_fibre_Fibre__yield=no
     16710fi
     16711rm -f core conftest.err conftest.$ac_objext \
     16712    conftest$ac_exeext conftest.$ac_ext
     16713LIBS=$ac_check_lib_save_LIBS
     16714fi
     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; }
     16717if test "x$ac_cv_lib_fibre_Fibre__yield" = xyes; then :
     16718  HAVE_LIBFIBRE=1
     16719else
     16720  HAVE_LIBFIBRE=0
     16721fi
     16722
     16723 if test "$HAVE_LIBFIBRE" -eq 1; then
     16724  WITH_LIBFIBRE_TRUE=
     16725  WITH_LIBFIBRE_FALSE='#'
     16726else
     16727  WITH_LIBFIBRE_TRUE='#'
     16728  WITH_LIBFIBRE_FALSE=
     16729fi
     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; }
     16734if ${ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads+:} false; then :
     16735  $as_echo_n "(cached) " >&6
     16736else
     16737  ac_check_lib_save_LIBS=$LIBS
     16738LIBS="-lprofiler  $LIBS"
     16739cat 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
     16746extern "C"
     16747#endif
     16748char ProfilingIsEnabledForAllThreads ();
     16749int
     16750main ()
     16751{
     16752return ProfilingIsEnabledForAllThreads ();
     16753  ;
     16754  return 0;
     16755}
     16756_ACEOF
     16757if ac_fn_c_try_link "$LINENO"; then :
     16758  ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads=yes
     16759else
     16760  ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads=no
     16761fi
     16762rm -f core conftest.err conftest.$ac_objext \
     16763    conftest$ac_exeext conftest.$ac_ext
     16764LIBS=$ac_check_lib_save_LIBS
     16765fi
     16766{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads" >&5
     16767$as_echo "$ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads" >&6; }
     16768if test "x$ac_cv_lib_profiler_ProfilingIsEnabledForAllThreads" = xyes; then :
     16769  HAVE_LIBPROFILER=1
     16770else
     16771  HAVE_LIBPROFILER=0
     16772fi
     16773
     16774 if test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBPROFILER" -eq 1; then
     16775  WITH_LIBPROFILER_TRUE=
     16776  WITH_LIBPROFILER_FALSE='#'
     16777else
     16778  WITH_LIBPROFILER_TRUE='#'
     16779  WITH_LIBPROFILER_FALSE=
     16780fi
     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; }
     16785if ${ac_cv_lib_tcmalloc_malloc+:} false; then :
     16786  $as_echo_n "(cached) " >&6
     16787else
     16788  ac_check_lib_save_LIBS=$LIBS
     16789LIBS="-ltcmalloc  $LIBS"
     16790cat 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
     16797extern "C"
     16798#endif
     16799char malloc ();
     16800int
     16801main ()
     16802{
     16803return malloc ();
     16804  ;
     16805  return 0;
     16806}
     16807_ACEOF
     16808if ac_fn_c_try_link "$LINENO"; then :
     16809  ac_cv_lib_tcmalloc_malloc=yes
     16810else
     16811  ac_cv_lib_tcmalloc_malloc=no
     16812fi
     16813rm -f core conftest.err conftest.$ac_objext \
     16814    conftest$ac_exeext conftest.$ac_ext
     16815LIBS=$ac_check_lib_save_LIBS
     16816fi
     16817{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tcmalloc_malloc" >&5
     16818$as_echo "$ac_cv_lib_tcmalloc_malloc" >&6; }
     16819if test "x$ac_cv_lib_tcmalloc_malloc" = xyes; then :
     16820  HAVE_LIBTCMALLOC=1
     16821else
     16822  HAVE_LIBTCMALLOC=0
     16823fi
     16824
     16825 if test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBTCMALLOC" -eq 1; then
     16826  WITH_LIBTCMALLOC_TRUE=
     16827  WITH_LIBTCMALLOC_FALSE='#'
     16828else
     16829  WITH_LIBTCMALLOC_TRUE='#'
     16830  WITH_LIBTCMALLOC_FALSE=
     16831fi
     16832
     16833
     16834# conditionnally build the demangler
     16835if test "x$enable_demangler" == xyes; then
     16836        LIBDEMANGLE="libdemangle.a"
     16837        DEMANGLER="demangler"
     16838else
     16839        LIBDEMANGLE=""
     16840        DEMANGLER=""
     16841fi
     16842
     16843
     16844
     16845# Checks for header files.
     16846for ac_header in libintl.h malloc.h unistd.h
    600016847do :
    600116848  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
     
    600616853_ACEOF
    600716854
     16855else
     16856  echo "Error: Missing required header"; exit 1
    600816857fi
    600916858
     
    601216861
    601316862# Checks for typedefs, structures, and compiler characteristics.
    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; }
    6016 if ${ac_cv_header_stdbool_h+:} false; then :
     16863ac_fn_c_check_type "$LINENO" "_Float32" "ac_cv_type__Float32" "
     16864"
     16865if test "x$ac_cv_type__Float32" = xyes; then :
     16866
     16867cat >>confdefs.h <<_ACEOF
     16868#define HAVE__FLOAT32 1
     16869_ACEOF
     16870
     16871
     16872$as_echo "#define HAVE_KEYWORDS_FLOATXX /**/" >>confdefs.h
     16873
     16874fi
     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; }
     16880if ${m4cfa_cv_check_cflags___Wcast_function_type+:} false; then :
    601716881  $as_echo_n "(cached) " >&6
    601816882else
    6019   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     16883
     16884        m4cfa_check_save_flags=$CFLAGS
     16885        CFLAGS="$CFLAGS  -Wcast-function-type"
     16886        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    602016887/* 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;
    606516888
    606616889int
    606716890main ()
    606816891{
    6069 
    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);
    607616892
    607716893  ;
     
    608016896_ACEOF
    608116897if ac_fn_c_try_compile "$LINENO"; then :
    6082   ac_cv_header_stdbool_h=yes
    6083 else
    6084   ac_cv_header_stdbool_h=no
     16898  m4cfa_cv_check_cflags___Wcast_function_type=yes
     16899else
     16900  m4cfa_cv_check_cflags___Wcast_function_type=no
    608516901fi
    608616902rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    6087 fi
    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"
    6091 if test "x$ac_cv_type__Bool" = xyes; then :
     16903        CFLAGS=$m4cfa_check_save_flags
     16904fi
     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; }
     16907if test "x$m4cfa_cv_check_cflags___Wcast_function_type" = xyes; then :
     16908
     16909$as_echo "#define HAVE_CAST_FUNCTION_TYPE /**/" >>confdefs.h
     16910
     16911else
     16912  :
     16913fi
     16914
     16915
     16916#==============================================================================
     16917# backend compiler implementation
    609216918
    609316919cat >>confdefs.h <<_ACEOF
    6094 #define HAVE__BOOL 1
     16920#define CFA_BACKEND_CC "${CC}"
    609516921_ACEOF
    609616922
    609716923
    6098 fi
    6099 
    6100 
    6101 if test $ac_cv_header_stdbool_h = yes; then
    6102 
    6103 $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
    6104 
    6105 fi
    6106 
    6107 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
    6108 $as_echo_n "checking for inline... " >&6; }
    6109 if ${ac_cv_c_inline+:} false; then :
    6110   $as_echo_n "(cached) " >&6
    6111 else
    6112   ac_cv_c_inline=no
    6113 for ac_kw in inline __inline__ __inline; do
    6114   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    6115 /* end confdefs.h.  */
    6116 #ifndef __cplusplus
    6117 typedef int foo_t;
    6118 static $ac_kw foo_t static_foo () {return 0; }
    6119 $ac_kw foo_t foo () {return 0; }
    6120 #endif
    6121 
    6122 _ACEOF
    6123 if ac_fn_c_try_compile "$LINENO"; then :
    6124   ac_cv_c_inline=$ac_kw
    6125 fi
    6126 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    6127   test "$ac_cv_c_inline" != no && break
    6128 done
    6129 
    6130 fi
    6131 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
    6132 $as_echo "$ac_cv_c_inline" >&6; }
    6133 
    6134 case $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     ;;
    6147 esac
    6148 
    6149 ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t"
    6150 case $ac_cv_c_int16_t in #(
    6151   no|yes) ;; #(
    6152   *)
    6153 
    6154 cat >>confdefs.h <<_ACEOF
    6155 #define int16_t $ac_cv_c_int16_t
    6156 _ACEOF
    6157 ;;
    6158 esac
    6159 
    6160 ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t"
    6161 case $ac_cv_c_int32_t in #(
    6162   no|yes) ;; #(
    6163   *)
    6164 
    6165 cat >>confdefs.h <<_ACEOF
    6166 #define int32_t $ac_cv_c_int32_t
    6167 _ACEOF
    6168 ;;
    6169 esac
    6170 
    6171 ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t"
    6172 case $ac_cv_c_int8_t in #(
    6173   no|yes) ;; #(
    6174   *)
    6175 
    6176 cat >>confdefs.h <<_ACEOF
    6177 #define int8_t $ac_cv_c_int8_t
    6178 _ACEOF
    6179 ;;
    6180 esac
    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; }
    6184 if ${ac_cv_c_restrict+:} false; then :
    6185   $as_echo_n "(cached) " >&6
    6186 else
    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.  */
    6192 typedef int * int_ptr;
    6193         int foo (int_ptr $ac_kw ip) {
    6194         return ip[0];
    6195        }
    6196 int
    6197 main ()
    6198 {
    6199 int s[1];
    6200         int * $ac_kw t = s;
    6201         t[0] = 0;
    6202         return foo(t)
    6203   ;
    6204   return 0;
    6205 }
    6206 _ACEOF
    6207 if ac_fn_c_try_compile "$LINENO"; then :
    6208   ac_cv_c_restrict=$ac_kw
    6209 fi
    6210 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    6211      test "$ac_cv_c_restrict" != no && break
    6212    done
    6213 
    6214 fi
    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 
    6228 ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
    6229 if test "x$ac_cv_type_size_t" = xyes; then :
    6230 
    6231 else
    6232 
    6233 cat >>confdefs.h <<_ACEOF
    6234 #define size_t unsigned int
    6235 _ACEOF
    6236 
    6237 fi
    6238 
    6239 ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
    6240 case $ac_cv_c_uint16_t in #(
    6241   no|yes) ;; #(
    6242   *)
    6243 
    6244 
    6245 cat >>confdefs.h <<_ACEOF
    6246 #define uint16_t $ac_cv_c_uint16_t
    6247 _ACEOF
    6248 ;;
    6249   esac
    6250 
    6251 ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
    6252 case $ac_cv_c_uint32_t in #(
    6253   no|yes) ;; #(
    6254   *)
    6255 
    6256 $as_echo "#define _UINT32_T 1" >>confdefs.h
    6257 
    6258 
    6259 cat >>confdefs.h <<_ACEOF
    6260 #define uint32_t $ac_cv_c_uint32_t
    6261 _ACEOF
    6262 ;;
    6263   esac
    6264 
    6265 ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t"
    6266 case $ac_cv_c_uint8_t in #(
    6267   no|yes) ;; #(
    6268   *)
    6269 
    6270 $as_echo "#define _UINT8_T 1" >>confdefs.h
    6271 
    6272 
    6273 cat >>confdefs.h <<_ACEOF
    6274 #define uint8_t $ac_cv_c_uint8_t
    6275 _ACEOF
    6276 ;;
    6277   esac
    6278 
    6279 
    6280 # Checks for library functions.
    6281 for ac_func in memset putenv strchr strtol
    6282 do :
    6283   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
    6284 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
    6285 if 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 
    6290 fi
    6291 done
    6292 
    6293 
    6294 ac_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 
     16924
     16925#==============================================================================
     16926ac_config_files="$ac_config_files Makefile driver/Makefile src/Makefile benchmark/Makefile tests/Makefile longrun_tests/Makefile tools/Makefile tools/prettyprinter/Makefile"
     16927
     16928
     16929ac_config_links="$ac_config_links tests/test.py:tests/test.py"
     16930
     16931
     16932ac_config_files="$ac_config_files tests/config.py"
    629616933
    629716934cat >confcache <<\_ACEOF
     
    642017057fi
    642117058
    6422 if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
    6423   as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
    6424 Usually this means the macro was only invoked conditionally." "$LINENO" 5
    6425 fi
    6426 if test -z "${BUILD_RELEASE_TRUE}" && test -z "${BUILD_RELEASE_FALSE}"; then
    6427   as_fn_error $? "conditional \"BUILD_RELEASE\" was never defined.
    6428 Usually this means the macro was only invoked conditionally." "$LINENO" 5
    6429 fi
    6430 if test -z "${BUILD_DEBUG_TRUE}" && test -z "${BUILD_DEBUG_FALSE}"; then
    6431   as_fn_error $? "conditional \"BUILD_DEBUG\" was never defined.
    6432 Usually this means the macro was only invoked conditionally." "$LINENO" 5
    6433 fi
    6434 if test -z "${BUILD_NO_LIB_TRUE}" && test -z "${BUILD_NO_LIB_FALSE}"; then
    6435   as_fn_error $? "conditional \"BUILD_NO_LIB\" was never defined.
    6436 Usually this means the macro was only invoked conditionally." "$LINENO" 5
    6437 fi
    6438 if test -z "${BUILD_CONCURRENCY_TRUE}" && test -z "${BUILD_CONCURRENCY_FALSE}"; then
    6439   as_fn_error $? "conditional \"BUILD_CONCURRENCY\" was never defined.
     17059if test -z "${ENABLE_DISTCC_TRUE}" && test -z "${ENABLE_DISTCC_FALSE}"; then
     17060  as_fn_error $? "conditional \"ENABLE_DISTCC\" was never defined.
    644017061Usually this means the macro was only invoked conditionally." "$LINENO" 5
    644117062fi
     
    645417075if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
    645517076  as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined.
     17077Usually this means the macro was only invoked conditionally." "$LINENO" 5
     17078fi
     17079if test -z "${WITH_LIBFIBRE_TRUE}" && test -z "${WITH_LIBFIBRE_FALSE}"; then
     17080  as_fn_error $? "conditional \"WITH_LIBFIBRE\" was never defined.
     17081Usually this means the macro was only invoked conditionally." "$LINENO" 5
     17082fi
     17083if test -z "${WITH_LIBPROFILER_TRUE}" && test -z "${WITH_LIBPROFILER_FALSE}"; then
     17084  as_fn_error $? "conditional \"WITH_LIBPROFILER\" was never defined.
     17085Usually this means the macro was only invoked conditionally." "$LINENO" 5
     17086fi
     17087if test -z "${WITH_LIBTCMALLOC_TRUE}" && test -z "${WITH_LIBTCMALLOC_FALSE}"; then
     17088  as_fn_error $? "conditional \"WITH_LIBTCMALLOC\" was never defined.
    645617089Usually this means the macro was only invoked conditionally." "$LINENO" 5
    645717090fi
     
    688017513config_files="$ac_config_files"
    688117514config_headers="$ac_config_headers"
     17515config_links="$ac_config_links"
    688217516config_commands="$ac_config_commands"
    688317517
     
    690917543Configuration headers:
    691017544$config_headers
     17545
     17546Configuration links:
     17547$config_links
    691117548
    691217549Configuration commands:
     
    704017677AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
    704117678
     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
     17684sed_quote_subst='$sed_quote_subst'
     17685double_quote_subst='$double_quote_subst'
     17686delay_variable_subst='$delay_variable_subst'
     17687macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
     17688macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
     17689enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
     17690enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
     17691pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
     17692enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
     17693shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
     17694SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
     17695ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
     17696PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
     17697host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
     17698host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
     17699host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
     17700build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
     17701build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
     17702build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
     17703SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
     17704Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
     17705GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
     17706EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
     17707FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
     17708LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
     17709NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
     17710LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
     17711max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
     17712ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
     17713exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
     17714lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
     17715lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
     17716lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
     17717lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
     17718lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
     17719reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
     17720reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
     17721OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
     17722deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
     17723file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
     17724file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
     17725want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
     17726DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
     17727sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
     17728AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
     17729AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
     17730archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
     17731STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
     17732RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
     17733old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
     17734old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
     17735old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
     17736lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
     17737CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
     17738CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
     17739compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
     17740GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
     17741lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
     17742lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
     17743lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
     17744lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
     17745lt_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"`'
     17746lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
     17747nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
     17748lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
     17749lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
     17750objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
     17751MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
     17752lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
     17753lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
     17754lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
     17755lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
     17756lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
     17757need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
     17758MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
     17759DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
     17760NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
     17761LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
     17762OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
     17763OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
     17764libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
     17765shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
     17766extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
     17767archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
     17768enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
     17769export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
     17770whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
     17771compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
     17772old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
     17773old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
     17774archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
     17775archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
     17776module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
     17777module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
     17778with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
     17779allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
     17780no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
     17781hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
     17782hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
     17783hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
     17784hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
     17785hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
     17786hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
     17787hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
     17788inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
     17789link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
     17790always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
     17791export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
     17792exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
     17793include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
     17794prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
     17795postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
     17796file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
     17797variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
     17798need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
     17799need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
     17800version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
     17801runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
     17802shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
     17803shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
     17804libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
     17805library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
     17806soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
     17807install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
     17808postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
     17809postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
     17810finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
     17811finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
     17812hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
     17813sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
     17814configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
     17815configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
     17816hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
     17817enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
     17818enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
     17819enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
     17820old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
     17821striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
     17822compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`'
     17823predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`'
     17824postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`'
     17825predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`'
     17826postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`'
     17827compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`'
     17828LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`'
     17829reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`'
     17830reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17831old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17832compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
     17833GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
     17834lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
     17835lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
     17836lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
     17837lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
     17838lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
     17839archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
     17840enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`'
     17841export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
     17842whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
     17843compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`'
     17844old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17845old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17846archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17847archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17848module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17849module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17850with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
     17851allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
     17852no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
     17853hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
     17854hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
     17855hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
     17856hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
     17857hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`'
     17858hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`'
     17859hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
     17860inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
     17861link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
     17862always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
     17863export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17864exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
     17865include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
     17866prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17867postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
     17868file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
     17869hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
     17870compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
     17871predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`'
     17872postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`'
     17873predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`'
     17874postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`'
     17875compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`'
     17876
     17877LTCC='$LTCC'
     17878LTCFLAGS='$LTCFLAGS'
     17879compiler='$compiler_DEFAULT'
     17880
     17881# A function that is used when there is no print builtin or printf.
     17882func_fallback_echo ()
     17883{
     17884  eval 'cat <<_LTECHO_EOF
     17885\$1
     17886_LTECHO_EOF'
     17887}
     17888
     17889# Quote evaled strings.
     17890for var in SHELL \
     17891ECHO \
     17892PATH_SEPARATOR \
     17893SED \
     17894GREP \
     17895EGREP \
     17896FGREP \
     17897LD \
     17898NM \
     17899LN_S \
     17900lt_SP2NL \
     17901lt_NL2SP \
     17902reload_flag \
     17903OBJDUMP \
     17904deplibs_check_method \
     17905file_magic_cmd \
     17906file_magic_glob \
     17907want_nocaseglob \
     17908DLLTOOL \
     17909sharedlib_from_linklib_cmd \
     17910AR \
     17911AR_FLAGS \
     17912archiver_list_spec \
     17913STRIP \
     17914RANLIB \
     17915CC \
     17916CFLAGS \
     17917compiler \
     17918lt_cv_sys_global_symbol_pipe \
     17919lt_cv_sys_global_symbol_to_cdecl \
     17920lt_cv_sys_global_symbol_to_import \
     17921lt_cv_sys_global_symbol_to_c_name_address \
     17922lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
     17923lt_cv_nm_interface \
     17924nm_file_list_spec \
     17925lt_cv_truncate_bin \
     17926lt_prog_compiler_no_builtin_flag \
     17927lt_prog_compiler_pic \
     17928lt_prog_compiler_wl \
     17929lt_prog_compiler_static \
     17930lt_cv_prog_compiler_c_o \
     17931need_locks \
     17932MANIFEST_TOOL \
     17933DSYMUTIL \
     17934NMEDIT \
     17935LIPO \
     17936OTOOL \
     17937OTOOL64 \
     17938shrext_cmds \
     17939export_dynamic_flag_spec \
     17940whole_archive_flag_spec \
     17941compiler_needs_object \
     17942with_gnu_ld \
     17943allow_undefined_flag \
     17944no_undefined_flag \
     17945hardcode_libdir_flag_spec \
     17946hardcode_libdir_separator \
     17947exclude_expsyms \
     17948include_expsyms \
     17949file_list_spec \
     17950variables_saved_for_relink \
     17951libname_spec \
     17952library_names_spec \
     17953soname_spec \
     17954install_override_mode \
     17955finish_eval \
     17956old_striplib \
     17957striplib \
     17958compiler_lib_search_dirs \
     17959predep_objects \
     17960postdep_objects \
     17961predeps \
     17962postdeps \
     17963compiler_lib_search_path \
     17964LD_CXX \
     17965reload_flag_CXX \
     17966compiler_CXX \
     17967lt_prog_compiler_no_builtin_flag_CXX \
     17968lt_prog_compiler_pic_CXX \
     17969lt_prog_compiler_wl_CXX \
     17970lt_prog_compiler_static_CXX \
     17971lt_cv_prog_compiler_c_o_CXX \
     17972export_dynamic_flag_spec_CXX \
     17973whole_archive_flag_spec_CXX \
     17974compiler_needs_object_CXX \
     17975with_gnu_ld_CXX \
     17976allow_undefined_flag_CXX \
     17977no_undefined_flag_CXX \
     17978hardcode_libdir_flag_spec_CXX \
     17979hardcode_libdir_separator_CXX \
     17980exclude_expsyms_CXX \
     17981include_expsyms_CXX \
     17982file_list_spec_CXX \
     17983compiler_lib_search_dirs_CXX \
     17984predep_objects_CXX \
     17985postdep_objects_CXX \
     17986predeps_CXX \
     17987postdeps_CXX \
     17988compiler_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
     17997done
     17998
     17999# Double-quote double-evaled strings.
     18000for var in reload_cmds \
     18001old_postinstall_cmds \
     18002old_postuninstall_cmds \
     18003old_archive_cmds \
     18004extract_expsyms_cmds \
     18005old_archive_from_new_cmds \
     18006old_archive_from_expsyms_cmds \
     18007archive_cmds \
     18008archive_expsym_cmds \
     18009module_cmds \
     18010module_expsym_cmds \
     18011export_symbols_cmds \
     18012prelink_cmds \
     18013postlink_cmds \
     18014postinstall_cmds \
     18015postuninstall_cmds \
     18016finish_cmds \
     18017sys_lib_search_path_spec \
     18018configure_time_dlsearch_path \
     18019configure_time_lt_sys_library_path \
     18020reload_cmds_CXX \
     18021old_archive_cmds_CXX \
     18022old_archive_from_new_cmds_CXX \
     18023old_archive_from_expsyms_cmds_CXX \
     18024archive_cmds_CXX \
     18025archive_expsym_cmds_CXX \
     18026module_cmds_CXX \
     18027module_expsym_cmds_CXX \
     18028export_symbols_cmds_CXX \
     18029prelink_cmds_CXX \
     18030postlink_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
     18039done
     18040
     18041ac_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.
     18045if test -n "\${ZSH_VERSION+set}"; then
     18046   setopt NO_GLOB_SUBST
     18047fi
     18048
     18049
     18050    PACKAGE='$PACKAGE'
     18051    VERSION='$VERSION'
     18052    RM='$RM'
     18053    ofile='$ofile'
     18054
     18055
     18056
     18057
     18058
     18059
    704218060_ACEOF
    704318061
     
    704818066do
    704918067  case $ac_config_target in
    7050     "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
     18068    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:src/config.h.in" ;;
    705118069    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
     18070    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
    705218071    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
    7053     "src/driver/Makefile") CONFIG_FILES="$CONFIG_FILES src/driver/Makefile" ;;
     18072    "driver/Makefile") CONFIG_FILES="$CONFIG_FILES driver/Makefile" ;;
    705418073    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/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" ;;
     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" ;;
    706118077    "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
    706218078    "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" ;;
    706318081
    706418082  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
     
    707418092  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
    707518093  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
     18094  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
    707618095  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
    707718096fi
     
    737118390
    737218391
    7373 eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
     18392eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS  :L $CONFIG_LINKS  :C $CONFIG_COMMANDS"
    737418393shift
    737518394for ac_tag
     
    764818667          s/.*/./; q'`/stamp-h$_am_stamp_count
    764918668 ;;
    7650 
     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 ;;
    765118701  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
    765218702$as_echo "$as_me: executing $ac_file commands" >&6;}
     
    774918799}
    775018800 ;;
     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.
     18846available_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?
     18854macro_version=$macro_version
     18855macro_revision=$macro_revision
     18856
     18857# Whether or not to build shared libraries.
     18858build_libtool_libs=$enable_shared
     18859
     18860# Whether or not to build static libraries.
     18861build_old_libs=$enable_static
     18862
     18863# What type of objects to build.
     18864pic_mode=$pic_mode
     18865
     18866# Whether or not to optimize for fast installation.
     18867fast_install=$enable_fast_install
     18868
     18869# Shared archive member basename,for filename based shared library versioning on AIX.
     18870shared_archive_member_spec=$shared_archive_member_spec
     18871
     18872# Shell to use when invoking shell scripts.
     18873SHELL=$lt_SHELL
     18874
     18875# An echo program that protects backslashes.
     18876ECHO=$lt_ECHO
     18877
     18878# The PATH separator for the build system.
     18879PATH_SEPARATOR=$lt_PATH_SEPARATOR
     18880
     18881# The host system.
     18882host_alias=$host_alias
     18883host=$host
     18884host_os=$host_os
     18885
     18886# The build system.
     18887build_alias=$build_alias
     18888build=$build
     18889build_os=$build_os
     18890
     18891# A sed program that does not truncate output.
     18892SED=$lt_SED
     18893
     18894# Sed that helps us avoid accidentally triggering echo(1) options like -n.
     18895Xsed="\$SED -e 1s/^X//"
     18896
     18897# A grep program that handles long lines.
     18898GREP=$lt_GREP
     18899
     18900# An ERE matcher.
     18901EGREP=$lt_EGREP
     18902
     18903# A literal string matcher.
     18904FGREP=$lt_FGREP
     18905
     18906# A BSD- or MS-compatible name lister.
     18907NM=$lt_NM
     18908
     18909# Whether we need soft or hard links.
     18910LN_S=$lt_LN_S
     18911
     18912# What is the maximum length of a command?
     18913max_cmd_len=$max_cmd_len
     18914
     18915# Object file suffix (normally "o").
     18916objext=$ac_objext
     18917
     18918# Executable file suffix (normally "").
     18919exeext=$exeext
     18920
     18921# whether the shell understands "unset".
     18922lt_unset=$lt_unset
     18923
     18924# turn spaces into newlines.
     18925SP2NL=$lt_lt_SP2NL
     18926
     18927# turn newlines into spaces.
     18928NL2SP=$lt_lt_NL2SP
     18929
     18930# convert \$build file names to \$host format.
     18931to_host_file_cmd=$lt_cv_to_host_file_cmd
     18932
     18933# convert \$build files to toolchain format.
     18934to_tool_file_cmd=$lt_cv_to_tool_file_cmd
     18935
     18936# An object symbol dumper.
     18937OBJDUMP=$lt_OBJDUMP
     18938
     18939# Method to check whether dependent libraries are shared objects.
     18940deplibs_check_method=$lt_deplibs_check_method
     18941
     18942# Command to use when deplibs_check_method = "file_magic".
     18943file_magic_cmd=$lt_file_magic_cmd
     18944
     18945# How to find potential files when deplibs_check_method = "file_magic".
     18946file_magic_glob=$lt_file_magic_glob
     18947
     18948# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
     18949want_nocaseglob=$lt_want_nocaseglob
     18950
     18951# DLL creation program.
     18952DLLTOOL=$lt_DLLTOOL
     18953
     18954# Command to associate shared and link libraries.
     18955sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
     18956
     18957# The archiver.
     18958AR=$lt_AR
     18959
     18960# Flags to create an archive.
     18961AR_FLAGS=$lt_AR_FLAGS
     18962
     18963# How to feed a file listing to the archiver.
     18964archiver_list_spec=$lt_archiver_list_spec
     18965
     18966# A symbol stripping program.
     18967STRIP=$lt_STRIP
     18968
     18969# Commands used to install an old-style archive.
     18970RANLIB=$lt_RANLIB
     18971old_postinstall_cmds=$lt_old_postinstall_cmds
     18972old_postuninstall_cmds=$lt_old_postuninstall_cmds
     18973
     18974# Whether to use a lock for old archive extraction.
     18975lock_old_archive_extraction=$lock_old_archive_extraction
     18976
     18977# A C compiler.
     18978LTCC=$lt_CC
     18979
     18980# LTCC compiler flags.
     18981LTCFLAGS=$lt_CFLAGS
     18982
     18983# Take the output of nm and produce a listing of raw symbols and C names.
     18984global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
     18985
     18986# Transform the output of nm in a proper C declaration.
     18987global_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.
     18990global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
     18991
     18992# Transform the output of nm in a C name address pair.
     18993global_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.
     18996global_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.
     18999nm_interface=$lt_lt_cv_nm_interface
     19000
     19001# Specify filename containing input files for \$NM.
     19002nm_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.
     19005lt_sysroot=$lt_sysroot
     19006
     19007# Command to truncate a binary pipe.
     19008lt_truncate_bin=$lt_lt_cv_truncate_bin
     19009
     19010# The name of the directory that contains temporary libtool files.
     19011objdir=$objdir
     19012
     19013# Used to examine libraries when file_magic_cmd begins with "file".
     19014MAGIC_CMD=$MAGIC_CMD
     19015
     19016# Must we lock files when doing compilation?
     19017need_locks=$lt_need_locks
     19018
     19019# Manifest tool.
     19020MANIFEST_TOOL=$lt_MANIFEST_TOOL
     19021
     19022# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
     19023DSYMUTIL=$lt_DSYMUTIL
     19024
     19025# Tool to change global to local symbols on Mac OS X.
     19026NMEDIT=$lt_NMEDIT
     19027
     19028# Tool to manipulate fat objects and archives on Mac OS X.
     19029LIPO=$lt_LIPO
     19030
     19031# ldd/readelf like tool for Mach-O binaries on Mac OS X.
     19032OTOOL=$lt_OTOOL
     19033
     19034# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
     19035OTOOL64=$lt_OTOOL64
     19036
     19037# Old archive suffix (normally "a").
     19038libext=$libext
     19039
     19040# Shared library suffix (normally ".so").
     19041shrext_cmds=$lt_shrext_cmds
     19042
     19043# The commands to extract the exported symbol list from a shared archive.
     19044extract_expsyms_cmds=$lt_extract_expsyms_cmds
     19045
     19046# Variables whose values should be saved in libtool wrapper scripts and
     19047# restored at link time.
     19048variables_saved_for_relink=$lt_variables_saved_for_relink
     19049
     19050# Do we need the "lib" prefix for modules?
     19051need_lib_prefix=$need_lib_prefix
     19052
     19053# Do we need a version for libraries?
     19054need_version=$need_version
     19055
     19056# Library versioning type.
     19057version_type=$version_type
     19058
     19059# Shared library runtime path variable.
     19060runpath_var=$runpath_var
     19061
     19062# Shared library path variable.
     19063shlibpath_var=$shlibpath_var
     19064
     19065# Is shlibpath searched before the hard-coded library search path?
     19066shlibpath_overrides_runpath=$shlibpath_overrides_runpath
     19067
     19068# Format of library name prefix.
     19069libname_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
     19073library_names_spec=$lt_library_names_spec
     19074
     19075# The coded name of the library, if different from the real name.
     19076soname_spec=$lt_soname_spec
     19077
     19078# Permission mode override for installation of shared libraries.
     19079install_override_mode=$lt_install_override_mode
     19080
     19081# Command to use after installation of a shared archive.
     19082postinstall_cmds=$lt_postinstall_cmds
     19083
     19084# Command to use after uninstallation of a shared archive.
     19085postuninstall_cmds=$lt_postuninstall_cmds
     19086
     19087# Commands used to finish a libtool library installation in a directory.
     19088finish_cmds=$lt_finish_cmds
     19089
     19090# As "finish_cmds", except a single script fragment to be evaled but
     19091# not shown.
     19092finish_eval=$lt_finish_eval
     19093
     19094# Whether we should hardcode library paths into libraries.
     19095hardcode_into_libs=$hardcode_into_libs
     19096
     19097# Compile-time system search path for libraries.
     19098sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
     19099
     19100# Detected run-time system search path for libraries.
     19101sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
     19102
     19103# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
     19104configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
     19105
     19106# Whether dlopen is supported.
     19107dlopen_support=$enable_dlopen
     19108
     19109# Whether dlopen of programs is supported.
     19110dlopen_self=$enable_dlopen_self
     19111
     19112# Whether dlopen of statically linked programs is supported.
     19113dlopen_self_static=$enable_dlopen_self_static
     19114
     19115# Commands to strip libraries.
     19116old_striplib=$lt_old_striplib
     19117striplib=$lt_striplib
     19118
     19119
     19120# The linker used to build libraries.
     19121LD=$lt_LD
     19122
     19123# How to create reloadable object files.
     19124reload_flag=$lt_reload_flag
     19125reload_cmds=$lt_reload_cmds
     19126
     19127# Commands used to build an old-style archive.
     19128old_archive_cmds=$lt_old_archive_cmds
     19129
     19130# A language specific compiler.
     19131CC=$lt_compiler
     19132
     19133# Is the compiler the GNU compiler?
     19134with_gcc=$GCC
     19135
     19136# Compiler flag to turn off builtin functions.
     19137no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
     19138
     19139# Additional compiler flags for building library objects.
     19140pic_flag=$lt_lt_prog_compiler_pic
     19141
     19142# How to pass a linker flag through the compiler.
     19143wl=$lt_lt_prog_compiler_wl
     19144
     19145# Compiler flag to prevent dynamic linking.
     19146link_static_flag=$lt_lt_prog_compiler_static
     19147
     19148# Does compiler simultaneously support -c and -o options?
     19149compiler_c_o=$lt_lt_cv_prog_compiler_c_o
     19150
     19151# Whether or not to add -lc for building shared libraries.
     19152build_libtool_need_lc=$archive_cmds_need_lc
     19153
     19154# Whether or not to disallow shared libs when runtime libs are static.
     19155allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
     19156
     19157# Compiler flag to allow reflexive dlopens.
     19158export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
     19159
     19160# Compiler flag to generate shared objects directly from archives.
     19161whole_archive_flag_spec=$lt_whole_archive_flag_spec
     19162
     19163# Whether the compiler copes with passing no objects directly.
     19164compiler_needs_object=$lt_compiler_needs_object
     19165
     19166# Create an old-style archive from a shared archive.
     19167old_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.
     19170old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
     19171
     19172# Commands used to build a shared archive.
     19173archive_cmds=$lt_archive_cmds
     19174archive_expsym_cmds=$lt_archive_expsym_cmds
     19175
     19176# Commands used to build a loadable module if different from building
     19177# a shared archive.
     19178module_cmds=$lt_module_cmds
     19179module_expsym_cmds=$lt_module_expsym_cmds
     19180
     19181# Whether we are building with GNU ld or not.
     19182with_gnu_ld=$lt_with_gnu_ld
     19183
     19184# Flag that allows shared libraries with undefined symbols to be built.
     19185allow_undefined_flag=$lt_allow_undefined_flag
     19186
     19187# Flag that enforces no undefined symbols.
     19188no_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
     19192hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
     19193
     19194# Whether we need a single "-rpath" flag with a separated argument.
     19195hardcode_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.
     19199hardcode_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.
     19205hardcode_direct_absolute=$hardcode_direct_absolute
     19206
     19207# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
     19208# into the resulting binary.
     19209hardcode_minus_L=$hardcode_minus_L
     19210
     19211# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
     19212# into the resulting binary.
     19213hardcode_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.
     19218hardcode_automatic=$hardcode_automatic
     19219
     19220# Set to yes if linker adds runtime paths of dependent libraries
     19221# to runtime path list.
     19222inherit_rpath=$inherit_rpath
     19223
     19224# Whether libtool must link a program against all its dependency libraries.
     19225link_all_deplibs=$link_all_deplibs
     19226
     19227# Set to "yes" if exported symbols are required.
     19228always_export_symbols=$always_export_symbols
     19229
     19230# The commands to list exported symbols.
     19231export_symbols_cmds=$lt_export_symbols_cmds
     19232
     19233# Symbols that should not be listed in the preloaded symbols.
     19234exclude_expsyms=$lt_exclude_expsyms
     19235
     19236# Symbols that must always be exported.
     19237include_expsyms=$lt_include_expsyms
     19238
     19239# Commands necessary for linking programs (against libraries) with templates.
     19240prelink_cmds=$lt_prelink_cmds
     19241
     19242# Commands necessary for finishing linking programs.
     19243postlink_cmds=$lt_postlink_cmds
     19244
     19245# Specify filename containing input files.
     19246file_list_spec=$lt_file_list_spec
     19247
     19248# How to hardcode a shared library path into an executable.
     19249hardcode_action=$hardcode_action
     19250
     19251# The directories searched by this compiler when creating a shared library.
     19252compiler_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.
     19256predep_objects=$lt_predep_objects
     19257postdep_objects=$lt_postdep_objects
     19258predeps=$lt_predeps
     19259postdeps=$lt_postdeps
     19260
     19261# The library search path used internally by the compiler when linking
     19262# a shared library.
     19263compiler_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]"
     19287func_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.
     19310func_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.
     19334if test set != "${COLLECT_NAMES+set}"; then
     19335  COLLECT_NAMES=
     19336  export COLLECT_NAMES
     19337fi
     19338_LT_EOF
     19339    ;;
     19340  esac
     19341
     19342
     19343ltmain=$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.
     19363LD=$lt_LD_CXX
     19364
     19365# How to create reloadable object files.
     19366reload_flag=$lt_reload_flag_CXX
     19367reload_cmds=$lt_reload_cmds_CXX
     19368
     19369# Commands used to build an old-style archive.
     19370old_archive_cmds=$lt_old_archive_cmds_CXX
     19371
     19372# A language specific compiler.
     19373CC=$lt_compiler_CXX
     19374
     19375# Is the compiler the GNU compiler?
     19376with_gcc=$GCC_CXX
     19377
     19378# Compiler flag to turn off builtin functions.
     19379no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
     19380
     19381# Additional compiler flags for building library objects.
     19382pic_flag=$lt_lt_prog_compiler_pic_CXX
     19383
     19384# How to pass a linker flag through the compiler.
     19385wl=$lt_lt_prog_compiler_wl_CXX
     19386
     19387# Compiler flag to prevent dynamic linking.
     19388link_static_flag=$lt_lt_prog_compiler_static_CXX
     19389
     19390# Does compiler simultaneously support -c and -o options?
     19391compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
     19392
     19393# Whether or not to add -lc for building shared libraries.
     19394build_libtool_need_lc=$archive_cmds_need_lc_CXX
     19395
     19396# Whether or not to disallow shared libs when runtime libs are static.
     19397allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
     19398
     19399# Compiler flag to allow reflexive dlopens.
     19400export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
     19401
     19402# Compiler flag to generate shared objects directly from archives.
     19403whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
     19404
     19405# Whether the compiler copes with passing no objects directly.
     19406compiler_needs_object=$lt_compiler_needs_object_CXX
     19407
     19408# Create an old-style archive from a shared archive.
     19409old_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.
     19412old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
     19413
     19414# Commands used to build a shared archive.
     19415archive_cmds=$lt_archive_cmds_CXX
     19416archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
     19417
     19418# Commands used to build a loadable module if different from building
     19419# a shared archive.
     19420module_cmds=$lt_module_cmds_CXX
     19421module_expsym_cmds=$lt_module_expsym_cmds_CXX
     19422
     19423# Whether we are building with GNU ld or not.
     19424with_gnu_ld=$lt_with_gnu_ld_CXX
     19425
     19426# Flag that allows shared libraries with undefined symbols to be built.
     19427allow_undefined_flag=$lt_allow_undefined_flag_CXX
     19428
     19429# Flag that enforces no undefined symbols.
     19430no_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
     19434hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
     19435
     19436# Whether we need a single "-rpath" flag with a separated argument.
     19437hardcode_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.
     19441hardcode_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.
     19447hardcode_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.
     19451hardcode_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.
     19455hardcode_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.
     19460hardcode_automatic=$hardcode_automatic_CXX
     19461
     19462# Set to yes if linker adds runtime paths of dependent libraries
     19463# to runtime path list.
     19464inherit_rpath=$inherit_rpath_CXX
     19465
     19466# Whether libtool must link a program against all its dependency libraries.
     19467link_all_deplibs=$link_all_deplibs_CXX
     19468
     19469# Set to "yes" if exported symbols are required.
     19470always_export_symbols=$always_export_symbols_CXX
     19471
     19472# The commands to list exported symbols.
     19473export_symbols_cmds=$lt_export_symbols_cmds_CXX
     19474
     19475# Symbols that should not be listed in the preloaded symbols.
     19476exclude_expsyms=$lt_exclude_expsyms_CXX
     19477
     19478# Symbols that must always be exported.
     19479include_expsyms=$lt_include_expsyms_CXX
     19480
     19481# Commands necessary for linking programs (against libraries) with templates.
     19482prelink_cmds=$lt_prelink_cmds_CXX
     19483
     19484# Commands necessary for finishing linking programs.
     19485postlink_cmds=$lt_postlink_cmds_CXX
     19486
     19487# Specify filename containing input files.
     19488file_list_spec=$lt_file_list_spec_CXX
     19489
     19490# How to hardcode a shared library path into an executable.
     19491hardcode_action=$hardcode_action_CXX
     19492
     19493# The directories searched by this compiler when creating a shared library.
     19494compiler_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.
     19498predep_objects=$lt_predep_objects_CXX
     19499postdep_objects=$lt_postdep_objects_CXX
     19500predeps=$lt_predeps_CXX
     19501postdeps=$lt_postdeps_CXX
     19502
     19503# The library search path used internally by the compiler when linking
     19504# a shared library.
     19505compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
     19506
     19507# ### END LIBTOOL TAG CONFIG: CXX
     19508_LT_EOF
     19509
     19510 ;;
    775119511
    775219512  esac
     
    778819548
    778919549
    7790 if 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;}
    7794 else
    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;}
    7797 fi
    7798 else
    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;}
    7802 else
    7803   { $as_echo "$as_me:${as_lineno-$LINENO}: Running cfa without libcfa" >&5
    7804 $as_echo "$as_me: Running cfa without libcfa" >&6;}
    7805 fi
    7806 fi
    7807 
    780819550# Final text
    780919551{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Cforall configuraton completed. Type \"make -j 8 install\"." >&5
  • configure.ac

    r7951100 rb067d9b  
    55AC_INIT([cfa-cc],[1.0.0.0],[cforall@plg.uwaterloo.ca])
    66AC_CONFIG_AUX_DIR([automake])
     7AC_CONFIG_MACRO_DIRS([automake])
    78#AC_CONFIG_SRCDIR([src/main.cc])
    8 AC_CONFIG_HEADERS([config.h])
    9 AM_SILENT_RULES([no])
     9AC_CONFIG_HEADERS([config.h:src/config.h.in])
     10AM_SILENT_RULES([yes])
     11
     12m4_include([automake/cfa.m4])
     13
     14# don't use the default CFLAGS as they unconditonnaly add -O2
     15: ${CFLAGS=""}
    1016
    1117AM_INIT_AUTOMAKE([subdir-objects])
    12 AM_MAINTAINER_MODE(enable)                      # may require auto* software to be installed
    1318
    1419# Allow program name tansformation
     
    1621AC_ARG_PROGRAM
    1722
     23#==============================================================================
    1824#Trasforming cc1 will break compilation
    19 if test "${program_transform_name}" = ""; then
    20     AC_MSG_ERROR([Program transform not supported.
    21                 Use --with-cfa-name='[[Desired name here]]' instead])
    22 fi
    23 
    24 AC_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
    29 AC_SUBST(CFA_NAME, ${cfa_name})
     25M4CFA_PROGRAM_NAME
     26
     27#==============================================================================
     28# version information
    3029
    3130rm -f version
     
    4746AC_DEFINE_UNQUOTED(CFA_VERSION_FULL, ["${ver_major}.${ver_minor}.${ver_patch}.${ver_build}"], [Major.Minor.Patch.Build])
    4847
    49 # Installation paths
    50 
    51 AC_ARG_WITH(backend-compiler,
    52         [  --with-backend-compiler=PROGRAM     PROGRAM that performs the final code compilation (must be gcc-compatible) ],
    53         backendcompiler=$withval, backendcompiler="")
    54 if test "x$backendcompiler" != "x"; then
    55         BACKEND_CC=${backendcompiler}
    56 else
    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
    62 fi
    63 AC_DEFINE_UNQUOTED(CFA_BACKEND_CC, "${BACKEND_CC}", [Location of include files.])
    64 AC_SUBST(CFA_BACKEND_CC)
    65 
    66 
    67 
    68 AC_ARG_ENABLE(target-release, AS_HELP_STRING([--enable-target-release], [Build and install the release target]))
    69 AC_ARG_ENABLE(target-debug, AS_HELP_STRING([--enable-target-debug], [Build and install the debug target]))
    70 AC_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]) ;;
    75 esac],[build_threading="yes"])
    76 
    77 case "$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                 ;;
    126 esac
    127 
    128 AM_CONDITIONAL([BUILD_RELEASE], [test "x$build_release" = "xyes"])
    129 AM_CONDITIONAL([BUILD_DEBUG], [test "x$build_debug" = "xyes"])
    130 AM_CONDITIONAL([BUILD_NO_LIB], [test "x$build_release$build_debug" = "xnono"])
    131 AM_CONDITIONAL([BUILD_CONCURRENCY], [test "x$build_threading" = "xyes"])
    132 
     48#==============================================================================
     49# HACK to be able to use conditionnals inside makefiles
    13350DOifskipcompile='ifeq ($(skipcompile),yes)
    13451else'
     
    14057AM_SUBST_NOTMAKE([DOendif])
    14158
    142 if test "x$prefix" = "xNONE"; then
    143         cfa_prefix=${ac_default_prefix}
    144 else
    145         cfa_prefix=${prefix}
     59#==============================================================================
     60# distcc support
     61
     62AC_ARG_ENABLE(distcc,
     63        [  --enable-distcc     whether or not to enable distributed compilation],
     64        enable_distcc=$enableval, enable_distcc=no)
     65
     66AM_CONDITIONAL([ENABLE_DISTCC], [test x$enable_distcc = xyes])
     67HAS_DISTCC="False"
     68
     69if test x$enable_distcc = xyes; then
     70        CXX="distcc ${CXX}"
     71        LD="distcc ${LD} -lstdc++"
     72        HAS_DISTCC="True"
     73        echo "Enabling distributed builds"
    14674fi
    147 AC_DEFINE_UNQUOTED(CFA_PREFIX, "${cfa_prefix}", [Location of cfa install.])
    148 AC_SUBST(CFA_PREFIX, ${cfa_prefix})
    149 
    150 if test "$includedir" = '${prefix}/include'; then
    151         cfa_incdir="${cfa_prefix}/include/${cfa_name}"
    152 else
    153         cfa_incdir=${includedir}
    154 fi
    155 AC_DEFINE_UNQUOTED(CFA_INCDIR, "${cfa_incdir}", [Location of include files.])
    156 AC_SUBST(CFA_INCDIR, ${cfa_incdir})
    157 
    158 if test "$bindir" = '${exec_prefix}/bin'; then
    159         cfa_bindir="${cfa_prefix}/bin"
    160 else
    161         cfa_bindir=${bindir}
    162 fi
    163 AC_DEFINE_UNQUOTED(CFA_BINDIR, "${cfa_bindir}", [Location of cfa command.])
    164 AC_SUBST(CFA_BINDIR, ${cfa_bindir})
    165 
    166 if test "$libdir" = '${exec_prefix}/lib'; then
    167         cfa_libdir="${cfa_prefix}/lib/${cfa_name}"
    168 else
    169         cfa_libdir=${libdir}
    170 fi
    171 AC_DEFINE_UNQUOTED(CFA_LIBDIR, "${cfa_libdir}", [Location of cc1 and cfa-cpp commands.])
    172 AC_SUBST(CFA_LIBDIR, ${cfa_libdir})
    173 
     75
     76AC_SUBST(CXX)
     77AC_SUBST(LD)
     78AC_SUBST(HAS_DISTCC)
     79
     80#==============================================================================
     81# Installation paths
     82M4CFA_PARSE_PREFIX
     83
     84#==============================================================================
     85# Create variables for commonly used targets
     86
     87TOP_SRCDIR="$(readlink -m $ac_confdir/)/"
     88TOP_BUILDDIR="$(readlink -m $ac_pwd/)/"
     89
     90AC_DEFINE_UNQUOTED(TOP_SRCDIR, "$TOP_SRCDIR", [Top src directory])
     91AC_DEFINE_UNQUOTED(TOP_BUILDDIR, "$TOP_BUILDDIR", [Top build directory])
     92
     93DRIVER_DIR=${TOP_BUILDDIR}driver/
     94CFACC=${DRIVER_DIR}cfa
     95CFACC_INSTALL=${CFA_BINDIR}${CFA_NAME}
     96CFACPP=${DRIVER_DIR}cfa-cpp
     97AC_SUBST(DRIVER_DIR)
     98AC_SUBST(CFACC)
     99AC_SUBST(CFACC_INSTALL)
     100AC_SUBST(CFACPP)
     101
     102#==============================================================================
     103# Flag variables needed to build in tree
     104LIBCFA_SRC='${TOP_SRCDIR}/libcfa/src'
     105BUILD_IN_TREE_FLAGS="-XCFA -t -B${DRIVER_DIR}"
     106AC_SUBST(BUILD_IN_TREE_FLAGS)
     107
     108#==============================================================================
     109# handle the list of hosts to build for
     110for var in $ac_configure_args
     111do
     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
     127done
     128
     129#==============================================================================
     130# handle the list of hosts to build for
    174131AC_CANONICAL_BUILD
    175132AC_CANONICAL_HOST
    176 AC_SUBST([MACHINE_TYPE],[$host_cpu])
    177133
    178134if ! test "$host_cpu" = "$build_cpu"; then
    179135        case $host_cpu in
    180136                i386)
    181                         CFLAGS+=" -m32 "
    182                         CXXFLAGS+=" -m32 "
    183                         CFAFLAGS+=" -m32 "
    184                         LDFLAGS+=" -m32 "
     137                        HOST_FLAGS="-m32"
    185138                        ;;
    186139                i686)
    187                         CFLAGS+=" -m32 "
    188                   CXXFLAGS+=" -m32 "
    189                   CFAFLAGS+=" -m32 "
    190                   LDFLAGS+=" -m32 "
     140                        HOST_FLAGS="-m32"
    191141                        ;;
    192142                x86_64)
    193                         CFLAGS+=" -m64 "
    194                         CXXFLAGS+=" -m64 "
    195                         CFAFLAGS+=" -m64 "
    196                         LDFLAGS+=" -m64 "
     143                        HOST_FLAGS="-m64"
    197144                        ;;
    198145        esac
    199146fi
    200 
     147AC_SUBST(HOST_FLAGS)
     148
     149default_target="${host_cpu}:debug, ${host_cpu}:nodebug"
     150AC_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
     154AC_ARG_ENABLE(gprofiler,
     155        [  --enable-gprofiler     whether or not to enable gprofiler tools (if available)],
     156        enable_gprofiler=$enableval, enable_gprofiler=yes)
     157
     158AC_ARG_ENABLE(demangler,
     159        [  --enable-demangler     whether or not to build the demangler (executable and library)],
     160        enable_demangler=$enableval, enable_demangler=yes)
     161
     162AC_SUBST(TARGET_HOSTS, ${target_hosts})
     163
     164LIBCFA_PATHS="DRIVER_DIR=${DRIVER_DIR}"
     165
     166for i in $(echo $target_hosts | sed "s/,/ /g")
     167do
     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
     196done
     197
     198AC_SUBST(LIBCFA_TARGET_DIRS)
     199AC_SUBST(LIBCFA_TARGET_MAKEFILES)
     200
     201M4CFA_CANNON_CPU([${host_cpu}])
     202AC_DEFINE_UNQUOTED(CFA_DEFAULT_CPU, "$cannon_arch_name", [Default cpu to use if neither -m32 or -m64 are defined.])
     203AC_DEFINE_UNQUOTED(CFA_64_CPU, "x64", [CPU to use if the -m64 flags is given.])
     204AC_DEFINE_UNQUOTED(CFA_32_CPU, "x86", [CPU to use if the -m32 flags is given.])
     205
     206#==============================================================================
     207# CAFLAGS
    201208AC_DEFINE_UNQUOTED(CFA_FLAGS, "${CFAFLAGS}", [compilation flags for cfa libraries and test programs.])
    202209AC_SUBST(CFA_FLAGS, ${CFAFLAGS})
    203210
     211#==============================================================================
    204212# Checks for programs.
    205213AC_PROG_CXX
    206214AC_PROG_CC
    207215AM_PROG_AS
    208 AM_PROG_CC_C_O  # deprecated
    209216# These are often not installed and people miss seeing the "no", so stop the configure.
    210217AC_PROG_YACC
     
    212219AC_PROG_LEX
    213220if test "${LEX}" = "lex" ; then echo "Error: flex required." ; exit 1 ; fi
     221AC_PROG_LIBTOOL
    214222AC_PROG_INSTALL
    215 AC_PROG_MAKE_SET
    216 AC_PROG_RANLIB
    217223
    218224# Checks for libraries.
     225AC_CHECK_LIB([fibre], [Fibre::yield], [HAVE_LIBFIBRE=1], [HAVE_LIBFIBRE=0])
     226AM_CONDITIONAL([WITH_LIBFIBRE], [test "$HAVE_LIBFIBRE" -eq 1])
     227
     228AC_CHECK_LIB([profiler], [ProfilingIsEnabledForAllThreads], [HAVE_LIBPROFILER=1], [HAVE_LIBPROFILER=0])
     229AM_CONDITIONAL([WITH_LIBPROFILER], [test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBPROFILER" -eq 1])
     230
     231AC_CHECK_LIB([tcmalloc], [malloc], [HAVE_LIBTCMALLOC=1], [HAVE_LIBTCMALLOC=0])
     232AM_CONDITIONAL([WITH_LIBTCMALLOC], [test "x$enable_gprofiler" = "xyes" -a "$HAVE_LIBTCMALLOC" -eq 1])
     233
     234# conditionnally build the demangler
     235if test "x$enable_demangler" == xyes; then
     236        LIBDEMANGLE="libdemangle.a"
     237        DEMANGLER="demangler"
     238else
     239        LIBDEMANGLE=""
     240        DEMANGLER=""
     241fi
     242AC_SUBST([LIBDEMANGLE])
     243AC_SUBST([DEMANGLER])
    219244
    220245# Checks for header files.
    221 AC_FUNC_ALLOCA
    222 AC_CHECK_HEADERS([fenv.h float.h inttypes.h libintl.h limits.h malloc.h stddef.h stdlib.h string.h unistd.h])
     246AC_CHECK_HEADERS([libintl.h malloc.h unistd.h], [], [echo "Error: Missing required header"; exit 1])
    223247
    224248# Checks for typedefs, structures, and compiler characteristics.
    225 AC_HEADER_STDBOOL
    226 AC_C_INLINE
    227 AC_TYPE_INT16_T
    228 AC_TYPE_INT32_T
    229 AC_TYPE_INT8_T
    230 AC_C_RESTRICT
    231 AC_TYPE_SIZE_T
    232 AC_TYPE_UINT16_T
    233 AC_TYPE_UINT32_T
    234 AC_TYPE_UINT8_T
    235 
    236 # Checks for library functions.
    237 AC_CHECK_FUNCS([memset putenv strchr strtol])
    238 
     249AC_CHECK_TYPES([_Float32], AC_DEFINE([HAVE_KEYWORDS_FLOATXX], [], [Have keywords _FloatXX.]), [], [[]])
     250
     251# Checks for compiler flags.
     252M4CFA_CHECK_COMPILE_FLAG([-Wcast-function-type], AC_DEFINE([HAVE_CAST_FUNCTION_TYPE], [], [Have compiler warning cast-function-type.]))
     253
     254#==============================================================================
     255# backend compiler implementation
     256AC_DEFINE_UNQUOTED(CFA_BACKEND_CC, "${CC}", [Backend compiler to use.])
     257AC_SUBST(CFA_BACKEND_CC)
     258
     259#==============================================================================
    239260AC_CONFIG_FILES([
    240261        Makefile
    241         src/driver/Makefile
     262        driver/Makefile
    242263        src/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
     264        benchmark/Makefile
     265        tests/Makefile
     266        longrun_tests/Makefile
    249267        tools/Makefile
    250268        tools/prettyprinter/Makefile
    251269        ])
    252270
    253 AC_OUTPUT
    254 
    255 AM_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)])])
     271AC_CONFIG_LINKS([tests/test.py:tests/test.py])
     272
     273AC_OUTPUT(tests/config.py)
    262274
    263275# Final text
  • doc/LaTeXmacros/common.tex

    r7951100 rb067d9b  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Mon Mar 19 17:18:23 2018
    14 %% Update Count     : 379
     13%% Last Modified On : Fri May 24 07:59:54 2019
     14%% Update Count     : 382
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5555\setlength{\parindentlnth}{\parindent}
    5656
     57\newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
    5758\newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
    5859\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
     
    6061\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    6162\newlength{\columnposn}
    62 \setlength{\gcolumnposn}{2.5in}
     63\setlength{\gcolumnposn}{2.75in}
    6364\setlength{\columnposn}{\gcolumnposn}
    6465\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

    r7951100 rb067d9b  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Fri Apr  6 23:44:50 2018
    11 %% Update Count     : 20
     10%% Last Modified On : Tue Jan  8 14:40:33 2019
     11%% Update Count     : 21
    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, __extension__, exception, fallthrough, fallthru, finally,
     116                coroutine, disable, dtype, enable, exception, __extension__, 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

    r7951100 rb067d9b  
    2121%  toplas: ACM Trans. on Prog. Lang. & Sys.
    2222%  tcs: Theoretical Computer Science
    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."}
     23
     24string{ieeepds="IEEE Transactions on Parallel and Distributed Systems"}
     25@string{ieeepds="IEEE Trans. Parallel Distrib. Syst."}
     26string{ieeese="IEEE Transactions on Software Engineering"}
     27@string{ieeese="IEEE Trans. Softw. Eng."}
     28string{spe="Software---\-Practice and Experience"}
     29@string{spe="Softw. Pract. Exper."}
     30string{ccpe="Concurrency and Computation: Practice and Experience"}
     31@string{ccpe="Concurrency Comput.: Pract. Exper."}
     32string{sigplan="SIGPLAN Notices"}
     33@string{sigplan="SIGPLAN Not."}
     34string{joop="Journal of Object-Oriented Programming"}
     35@string{joop="J. of Object-Oriented Program."}
    3536@string{popl="Conference Record of the ACM Symposium on Principles of Programming Languages"}
    3637@string{osr="Operating Systems Review"}
    3738@string{pldi="Programming Language Design and Implementation"}
    3839@string{toplas="Transactions on Programming Languages and Systems"}
    39 @string{mathann="Mathematische Annalen"}
    40 % @string{mathann="Math. Ann."}
     40string{mathann="Mathematische Annalen"}
     41@string{mathann="Math. Ann."}
    4142
    4243% A
     
    329330    contributer = {pabuhr@plg},
    330331    author      = {Nissim Francez},
    331     title       = {Another Advantage of Key word Notation for Parameter Communication with Subprograms},
     332    title       = {Another Advantage of Keyword Notation for Parameter Communication with Subprograms},
    332333    journal     = cacm,
    333334    volume      = 20,
     
    566567}
    567568
     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
    568580@article{Kessels82,
    569581    keywords    = {concurrency, critical section},
     
    653665    author      = {Joung, Yuh-Jzer},
    654666    title       = {Asynchronous group mutual exclusion},
    655     journal     = {Distributed Computing},
     667    journal     = {Dist. Comput.},
     668    optjournal  = {Distributed Computing},
    656669    year        = {2000},
    657670    month       = {Nov},
     
    700713
    701714% 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}
    702729
    703730@incollection{beta:old,
     
    782809        time computable inheritance hierarchy.
    783810    },
    784     comment = {
     811    comment     = {
    785812        Classes are predicates; if object {\tt o} is in class {\tt C}, then
    786813        {\tt C} is true of {\tt o}.  Classes are combined with {\tt :AND},
     
    804831    year        = 2015,
    805832    howpublished= {\href{http://www.boost.org/doc/libs/1_61_0/libs/coroutine/doc/html/index.html}
    806                   {{http://www.boost.org/\-doc/\-libs/1\_61\_0/\-libs/\-coroutine/\-doc/\-html/\-index.html}}},
    807     optnote     = {Accessed: 2016-09},
     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}},
    808844}
    809845
     
    816852    month       = oct,
    817853    type        = {Diplomarbeit},
    818     note        = {{\small\textsf{ftp://\-plg.uwaterloo.ca/\-pub/\-theses/\-KrischerThesis.ps.gz}}},
     854    note        = {\href{https://plg.uwaterloo.ca/~usystem/theses/KrischerThesis.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-theses/\-KrischerThesis.pdf}},
    819855}
    820856
     
    907943}
    908944
     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
    909966@misc{Cforall,
     967    contributer = {pabuhr@plg},
    910968    key         = {Cforall},
    911     title       = {\textsf{C}{$\mathbf{\forall}$} Features},
    912     howpublished= {\url{https://plg.uwaterloo.ca/~cforall/features}},
    913     optnote     = {Accessed: 2018-01-01},
     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}},
    914979}
    915980
     
    925990}
    926991
    927 @misc{CFAStackEvaluation,
     992@phdthesis{Moss19,
     993    keywords    = {type system, generic type, resolution algorithm, type environment, Cforall},
    928994    author      = {Aaron Moss},
    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},
     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}},
    9431000}
    9441001
     
    9621019    comment     = {
    9631020        The evidence given is thin.
    964         }
     1021    },
    9651022}
    9661023
     
    9721029    journal     = {Dr. Dobb's Journal of Software Tools},
    9731030    year        = 1989,
    974     month       = feb, volume = 14, number = 2, pages = {45-51},
     1031    month       = feb,
     1032    volume      = 14,
     1033    number      = 2,
     1034    pages       = {45-51},
    9751035    comment     = {
    9761036       A light-weight multitasking kernel for MS-DOS.  A task\_control
     
    10481108    year        = 2006,
    10491109    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}
    10501119}
    10511120
     
    10841153    month       = oct,
    10851154    year        = 2001,
    1086     note        = {\href{http://plg.uwaterloo.ca/~cforall/cfa.ps}{http://\-plg.uwaterloo.ca/\-\char`\~cforall/\-cfa.ps}},
     1155    note        = {\href{http://plg.uwaterloo.ca/~cforall/cfa.ps}{http://\-plg.uwaterloo.ca/\-$\sim$cforall/\-cfa.ps}},
    10871156}
    10881157
     
    10961165    year        = 1998,
    10971166    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/}}
    10981194}
    10991195
     
    11831279        that is ``compiled''.
    11841280    },
    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     }
    11951281}
    11961282
     
    12061292    number      = 11,
    12071293    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},
    12081313}
    12091314
     
    12681373    journal     = sigplan,
    12691374    year        = 1986,
    1270     month       = oct, volume = 21, number = 10, pages = {19-28},
     1375    month       = oct,
     1376    volume      = 21,
     1377    number      = 10,
     1378    pages       = {19-28},
    12711379    note        = {Object Oriented Programming Workshop}
    12721380}
     
    13881496        Process-valued expressions and process variables.  Processes have
    13891497        execution priority: Create {\em process-type-name}(args) [with
    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)
     1498        priority(p)], and the priority can be changed on the fly.  Complicated
     1499        guard/screen structure on accept: accept {\em transaction}(param names)
    13931500        [suchthat (exp)] [by (exp)] [compoundstatement].  Accepts cannot
    13941501        appear in functions!  Can specify timeouts on transaction calls.
     
    14251532                Many errors in the two solutions.
    14261533    }
     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}},
    14271543}
    14281544
     
    14911607}
    14921608
    1493 @techreport{uC++,
     1609@manual{uC++,
    14941610    keywords    = {C++, concurrency, light-weight process, shared memory},
    14951611    contributer = {pabuhr@plg},
     1612    key         = {uC++},
    14961613    author      = {Peter A. Buhr},
    14971614    title       = {$\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}} Annotated Reference Manual, Version 7.0.0},
    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}},
     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}},
    15031619}
    15041620
     
    15671683}
    15681684
     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
    15691694@book{Andrews91:book,
    15701695    keywords    = {concurrency},
     
    15751700    address     = {Redwood City},
    15761701    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}
    15771715}
    15781716
     
    15911729
    15921730@mastersthesis{Delisle18,
    1593     author      = {Thierry Delisle },
     1731    keywords    = {concurrency, Cforall},
     1732    contributer = {pabuhr@plg},
     1733    author      = {Thierry Delisle},
    15941734    title       = {Concurrency in \textsf{C}$\mathbf{\forall}$},
    15951735    school      = {School of Computer Science, University of Waterloo},
    15961736    year        = 2018,
    1597     address     = {Waterloo, Ontario, Canada, N2L 3G1},
     1737    optaddress  = {Waterloo, Ontario, Canada, N2L 3G1},
    15981738    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},
    15991750}
    16001751
     
    16901841    howpublished= {\href{https://www.airs.com/blog/archives/428}
    16911842                  {https://www.airs.com/\-blog/\-archives/\-428}},
    1692     optnote     = {Accessed: 2018-05},
    16931843}
    16941844
     
    17711921    author      = {Glen Ditchfield},
    17721922    title       = {Conversions for \textsf{C}$\mathbf{\forall}$},
    1773     note        = {\href{http://plg.uwaterloo.ca/~cforall/Conversions/index.html}{http://\-plg.uwaterloo.ca/\-\textasciitilde cforall/\-Conversions/\-index.html}},
     1923    note        = {\href{http://plg.uwaterloo.ca/~cforall/Conversions/index.html}{http://\-plg.uwaterloo.ca/\-$\sim$cforall/\-Conversions/\-index.html}},
    17741924    month       = {Nov},
    17751925    year        = {2002},
     
    17861936    year        = 1965,
    17871937    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}},
    17881971}
    17891972
     
    18332016}
    18342017
    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},
     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}},
    18432025}
    18442026
     
    18992081    note        = {Svensk Standard SS 63 61 14},
    19002082    year        = 1987,
    1901     abstract    = {
    1902         Standard for the programming language SIMULA.  Written in English.
    1903     }
     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},
    19042097}
    19052098
     
    20412234    year        = {1998},
    20422235    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}
    20432246}
    20442247
     
    21942397}
    21952398
     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
    21962415@article{design,
    21972416    keywords    = {Smalltalk, designing classes},
     
    22012420    journal     = joop,
    22022421    year        = 1988,
    2203     volume      = 1, number = 2, pages = {22-35},
     2422    volume      = 1,
     2423    number      = 2,
     2424    pages       = {22-35},
    22042425    comment     = {
    22052426        Abstract classes represent standard protocols.  ``It is better to
     
    22862507    year        = 1990,
    22872508    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}
    22882518}
    22892519
     
    23942624}
    23952625
     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
    23962647@book{Eiffel,
    23972648    keywords    = {Eiffel},
     
    24122663    journal     = ipl,
    24132664    year        = 1980,
    2414     month       = apr, volume = 10, number = 3, pages = {120-123},
     2665    month       = apr,
     2666    volume      = 10,
     2667    number      = 3,
     2668    pages       = {120-123},
    24152669    comment     = {
    24162670        The ``two-pass'' algorithm.  An upward pass over a parse tree
     
    24462700}
    24472701
    2448 @InProceedings{chambers89a,
     2702@inproceedings{chambers89a,
    24492703    keywords    = {maps, delegation},
    24502704    author      = "Craig Chambers and David Ungar and Elgin Lee",
    2451     title       = "An Efficient Implementation of {SELF}, a Dynamically-Typed
    2452                  Object-Oriented Language Based on Prototypes",
     2705    title       = "An Efficient Implementation of {SELF}, a Dynamically-Typed Object-Oriented Language Based on Prototypes",
    24532706    crossref    = "OOPSLA89",
    24542707    pages       = {49-70}
    24552708}
    24562709
     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
    24572722@article{oop:encapsulation,
    24582723    keywords    = {Encapsulation, Inheritance, Subclasses, Multiple Inheritance},
    24592724    contributer = {gjditchfield@plg},
    24602725    author      = {Alan Snyder},
    2461     title       = {Encapsulation and Inheritance in Object-Oriented Programming
    2462         Languages},
     2726    title       = {Encapsulation and Inheritance in Object-Oriented Programming Languages},
    24632727    journal     = sigplan,
    24642728    volume      = {21},    number = {11},
     
    24952759    title       = {Encapsulators: A New Software Paradigm in Smalltalk-80},
    24962760    journal     = sigplan,
    2497     volume      = {21},    number       = {11},
     2761    volume      = {21},
     2762    number      = {11},
    24982763    pages       = {341-346},
    2499     month       = nov, year = 1986,
     2764    month       = nov,
     2765    year        = 1986,
    25002766    comment     = {
    25012767        Encapsulators are objects that surround other objects.
     
    25682834    year        = 1979,
    25692835    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},
    25702849}
    25712850
     
    27793058    title       = {Extending Modula-2 to Build Large, Integrated Systems},
    27803059    journal     = {IEEE Software},
    2781     month       = nov, year = 1986,
    2782     volume      = 3, number = 6, pages = {46-57},
     3060    month       = nov,
     3061    year        = 1986,
     3062    volume      = 3,
     3063    number      = 6,
     3064    pages       = {46-57},
    27833065    comment     = {
    27843066        Exceptions can have a parameter.  Procedures can declare the
     
    28133095    year        = 2014,
    28143096    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},
    28163097}
    28173098
     
    28253106    year        = 1988,
    28263107    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}
    28273122}
    28283123
     
    28603155    keywords    = {concurrency, mutual exclusion, performance experiment, software solutions},
    28613156    title       = {Fast mutual exclusion by the {T}riangle algorithm},
    2862     author      = {Wim H. Hesselink and Peter Buhr and David Dice},
     3157    author      = {Wim H. Hesselink and Peter A. Buhr and David Dice},
    28633158    journal     = ccpe,
    28643159    volume      = 30,
     
    28673162    month       = feb,
    28683163    publisher   = {John Wiley \& Sons},
    2869     note        = {\url{https://doi.org/10.1002/cpe.4183}}
     3164    note        = {\href{https://doi.org/10.1002/cpe.4183}{https://\-doi.org/\-10.1002/\-cpe.4183}}
    28703165}
    28713166
     
    28833178}
    28843179
     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
    28853190@inproceedings{F-bound,
    28863191    keywords    = {},
     
    29303235}
    29313236
     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
    29323268@manual{Fortran95,
    29333269    keywords    = {Fortran 95},
     
    29503286    address     = {\href{https://www.iso.org/standard/50459.html}{https://\-www.iso.org/\-standard/\-50459.html}},
    29513287    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,
    29523299}
    29533300
     
    31703517    keywords    = {Go programming language},
    31713518    contributer = {pabuhr@plg},
     3519    author      = {Robert Griesemer and Rob Pike and Ken Thompson},
    31723520    title       = {{Go} Programming Language},
    3173     author      = {Robert Griesemer and Rob Pike and Ken Thompson},
    31743521    organization= {Google},
    31753522    year        = 2009,
     
    31993546    year        = 2014,
    32003547    howpublished= {https://developer.gnome.org/gobject/stable/},
    3201     optnote     = {Accessed: 2017-04},
    32023548}
    32033549
     
    32793625    edition     = {{S}imon {M}arlow},
    32803626    year        = 2010,
    3281     note        = {\href{https://haskell.org/definition/haskell2010.pdf}{https://haskell.org/\-definition/\-haskell2010.pdf}},
     3627    note        = {\href{https://haskell.org/definition/haskell2010.pdf}{https://\-haskell.org/\-definition/\-haskell2010.pdf}},
    32823628}
    32833629
     
    33533699}
    33543700
     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
    33553714@article{Buhr15a,
    33563715    keywords    = {software solution, mutual exclusion, performance experiment},
     
    34883847    publisher   = {ACM Press},
    34893848    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},
    34903886}
    34913887
     
    37944190}
    37954191
     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
    37964205% J
    37974206                 
     
    38174226}
    38184227
     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
    38194249@manual{JUC,
    38204250    keywords    = {Java concurrency library},
     
    38294259% K
    38304260
     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
    38314272@article{Duggan96,
    38324273    keywords    = {concurrency, critical section},
    38334274    contributer = {pabuhr@plg},
    3834     author      = {Dominic Duggan and G. V. Cormack and John Ophel},
     4275    author      = {Dominic Duggan and Gordon V. Cormack and John Ophel},
    38354276    title       = {Kinded Type Inference for Parametric Overloading},
    38364277    journal     = acta,
     
    39724413}
    39734414
     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
    39744425@article{Linda,
    39754426    keywords    = {Linda, concurrency},
     
    39854436}
    39864437
     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
    39874449@book{Weissman67,
    39884450    keywords    = {lisp},
     
    39944456}
    39954457
     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
    39964480@article{Sundell08,
    39974481    keywords    = {lock free, deque},
     
    40044488    year        = 2008,
    40054489    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},
    40064502}
    40074503
     
    40204516}
    40214517
     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
    40224527% M
    40234528
     
    40294534    publisher   = {Motorola},
    40304535    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},
    40314547}
    40324548
     
    40514567}
    40524568
     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
    40534579@inproceedings{mprof,
    40544580    keywords    = {malloc},
     
    40674593    month       = sep,
    40684594    year        = 2006,
    4069     note        = {\textsf{http://cs.anu.edu.au/\-\char`\~Robin.Garner/\-mmtk-guide.pdf}},
     4595    note        = {\textsf{http://cs.anu.edu.au/\-$\sim$Robin.Garner/\-mmtk-guide.pdf}},
    40704596}
    40714597
     
    41714697    month       = sep,
    41724698    year        = 1994,
    4173     note        = {{\small\textsf{ftp://\-plg.uwaterloo.ca/\-pub/\-uSystem/\-uSystem.ps.gz}}},
     4699    note        = {\href{https://plg.uwaterloo.ca/~usystem/pub/uSystem/uSystem.pdf}{https://\-plg.uwaterloo.ca/\-$\sim$usystem/\-pub/\-uSystem/\-uSystem.pdf}},
    41744700}
    41754701
     
    43474873}
    43484874%    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}
    43494889
    43504890@manual{MPI,
     
    45155055
    45165056% 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}
    45175067
    45185068@article{Haddon77,
     
    46415191}
    46425192
     5193@misc{nginx,
     5194    key         = {nginx},
     5195    author      = {{NGINX}},
     5196    howpublished= {\href{https://www.nginx.com}{https://\-www.nginx.com}},
     5197}
     5198
    46435199@article{Herlihy05,
    46445200    keywords    = {Multiprocessors, concurrent data structures, dynamic data structures, memory management, nonblocking synchronization},
     
    46975253    year        = 1995,
    46985254    number      = 31,
    4699     note        = {{\small\textsf{http://\-www.cs.wustl.edu/\-\char`\~schmidt/\-PDF/\-IPC\_SAP-92.pdf}}},
     5255    note        = {{\small\textsf{http://\-www.cs.wustl.edu/\-$\sim$schmidt/\-PDF/\-IPC\_SAP-92.pdf}}},
    47005256}
    47015257
     
    47515307@misc{obj-c-book,
    47525308    keywords    = {objective-c},
    4753     contributor = {a3moss@uwaterloo.ca},
     5309    contributor = {pabuhr@plg},
    47545310    key         = {Objective-C},
    4755     title       = {Objective-C},
     5311    author      = {Objective-C},
    47565312    publisher   = {Apple Inc.},
    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}
     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}},
    47605315}
    47615316
     
    47665321    title       = {{X}code 7 Release Notes},
    47675322    year        = 2015,
    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}
     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}},
    47705324}
    47715325
     
    48935447}
    48945448
    4895 @techreport{OpenMP,
     5449@manual{OpenMP,
    48965450    keywords    = {concurrency, openmp, spmd},
    48975451    contributer = {pabuhr@plg},
    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 }
     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}
    49045477
    49055478@book{Deitel04,
     
    52665839}
    52675840
     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
    52685857@article{Anderson90,
    52695858    keywords    = {spin locks, back off, performance},
     
    52775866    number      = 1,
    52785867    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}
    52795879}
    52805880
     
    54886088}
    54896089
     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
    54906106@book{PowerPC,
    54916107    key         = {PowerPC processor},
     
    55606176    address     = {\href{https://www.iso.org/standard/64029.html}{https://\-www.iso.org/\-standard/\-64029.html}},
    55616177    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,
    55626189}
    55636190
     
    57136340    institution = {Carnegie Mellon University},
    57146341    year        = 1991,
    5715     month       = feb, number = "CMU-CS-91-106",
     6342    month       = feb,
     6343    number      = {CMU-CS-91-106},
    57166344    annote      = {
    57176345        Discusses a typed lambda calculus with
     
    57536381}
    57546382
     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
    57556393@article{promises,
    57566394    keywords    = {futures, Argus, call streams, rpc},
    57576395    contributer = {gjditchfield@plg},
    57586396    author      = {Barbara Liskov and Liuba Shrira},
    5759     title       = {Promises: Linguistic Support for Efficient Asynchronous
    5760           Procedure Calls in Distributed Systems},
     6397    title       = {Promises: Linguistic Support for Efficient Asynchronous Procedure Calls in Distributed Systems},
    57616398    journal     = sigplan,
    57626399    year        = 1988,
    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},
     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},
    57666405    abstract    = {
    57676406        This paper deals with the integration of an efficient asynchronous
     
    58136452}
    58146453
     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
    58156465@manual{Python,
    58166466    keywords    = {Python},
    58176467    contributer = {pabuhr@plg},
    5818     title       = {Python Reference Manual, Release 2.5},
    5819     author      = {Guido van Rossum},
     6468    author      = {Python},
     6469    title       = {Python Language Reference, Release 3.7.2},
    58206470    organization= {Python Software Foundation},
    5821     month       = sep,
    5822     year        = 2006,
    5823     note        = {Fred L. Drake, Jr., editor},
     6471    address     = {\href{https://docs.python.org/3/reference/index.html}{https://\-docs.python.org/\-3/\-reference/\-index.html}},
     6472    year        = 2018,
    58246473}
    58256474
    58266475% 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}
    58276487
    58286488@article{Grossman06,
    58296489    keywords    = {Cyclone, existential types, polymorphism, type variables},
    58306490    contributer = {a3moss@plg},
    5831     author      = {D. Grossman},
     6491    author      = {Dan Grossman},
    58326492    title       = {Quantified Types in an Imperative Language},
    58336493    journal     = toplas,
     
    58396499    issn        = {0164-0925},
    58406500    pages       = {429-475},
    5841     url         = {http://doi.acm.org.proxy.lib.uwaterloo.ca/10.1145/1133651.1133653},
     6501    url         = {http://doi.acm.org/10.1145/1133651.1133653},
    58426502    doi         = {10.1145/1133651.1133653},
    58436503    acmid       = {1133653},
     
    58616521}
    58626522
     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
    58636533% R
    58646534
     
    59386608}
    59396609
     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
    59406623@article{Robinson48,
    59416624    keywords    = {recursion, Ackermann function},
     
    59636646}
    59646647
     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
    59656659@article{RemoteRendezvous,
    59666660    keywords    = {rendezvous, concurrency},
     
    59766670}
    59776671
     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
    59786683@article{Euclid,
    59796684    keywords    = {Euclid},
     
    60076712    school      = {School of Computer Science, University of Waterloo},
    60086713    year        = 2017,
    6009     address     = {Waterloo, Ontario, Canada, N2L 3G1},
     6714    optaddress  = {Waterloo, Ontario, Canada, N2L 3G1},
    60106715    note        = {\href{https://uwspace.uwaterloo.ca/handle/10012/11830}{https://\-uwspace.uwaterloo.ca/\-handle/\-10012/\-11830}},
    60116716}
     
    60826787    contributer = {pabuhr@plg},
    60836788    key         = {Rust},
    6084     title       = {The {R}ust Programming Language},
    6085     address     = {The Rust Project Developers},
     6789    title       = {{R}ust Programming Language},
     6790    optaddress  = {Rust Project Developers},
    60866791    year        = 2015,
    60876792    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,
    60886803}
    60896804
     
    61496864    publisher   = {Springer},
    61506865    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},
    61516908}
    61526909
     
    67827539}
    67837540
     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
    67847551% T
    67857552
     
    68347601    contributer = {pabuhr@plg},
    68357602    key         = {TIOBE Index},
    6836     title       = {{TIOBE} Index},
     7603    author      = {{TIOBE Index}},
    68377604    howpublished= {\href{http://www.tiobe.com/tiobe_index}{http://\-www.tiobe.com/\-tiobe\_index}},
    6838     optnote     = {Accessed: 2018-09},
     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)}},
    68397613}
    68407614
     
    69747748    year        = 1980
    69757749}
     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}
    69767757 
    69777758@article{Leroy00,
     
    69897770        Argues against declaring exceptions on routine definitions.
    69907771    },
     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}
    69917779}
    69927780
     
    71097897    title       = {Usability Challenges in Exception Handling},
    71107898    booktitle   = {5th International Workshop on Exception Handling (WEH)},
    7111     organization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)},
     7899    optorganization= {16th International Symposium on the Foundations of Software Engineering (FSE 16)},
    71127900    address     = {Zurich, Switzerland},
    71137901    month       = jun,
     
    71617949    year        = 2017,
    71627950    howpublished= {\url{https://wiki.gnome.org/Projects/Vala/Manual}},
    7163     optnote     = {Accessed: 2017-04}
    71647951}
    71657952
     
    72538040}
    72548041
     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
    72558055@techreport{Moss90,
    72568056    keywords    = {Swizzling, database},
     
    72978097}
    72988098
     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
    72998120% X
    73008121
    73018122% 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}
    73028138
    73038139% Z
     
    73178153    year        = 1986,
    73188154    editor      = {Norman Meyrowitz},
    7319     publisher   = sigplan # " 21(11)",
     8155    publisher   = sigplan,
    73208156    organization= {Association for Computing Machinery},
    73218157    address     = {Portland, Oregon},
    7322     month       = sep # { 29}
     8158    month       = sep,
    73238159}
    73248160
     
    73298165    year        = 1987,
    73308166    editor      = {Norman Meyrowitz},
    7331     publisher   = sigplan # " 22(12)",
     8167    publisher   = sigplan,
    73328168    organization= {Association for Computing Machinery},
    73338169    address     = {Orlando, Florida},
    7334     month       = oct # { 4--8}
     8170    month       = oct,
    73358171}
    73368172
     
    73418177    year        = 1988,
    73428178    editor      = {Norman Meyrowitz},
    7343     publisher   = sigplan # " 23(11)",
     8179    publisher   = sigplan,
    73448180    organization= {Association for Computing Machinery},
    73458181    address     = {San Diego, California},
    7346     month       = sep # { 25--30}
     8182    month       = sep,
    73478183}
    73488184
     
    73538189    year        = 1989,
    73548190    editor      = {Norman Meyrowitz},
    7355     publisher   = sigplan # " 24(10)",
     8191    publisher   = sigplan,
    73568192    organization= {Association for Computing Machinery},
    73578193    address     = {New Orleans, Louisiana},
    7358     month       = oct # { 1--6}
     8194    month       = oct,
    73598195}
    73608196
     
    73658201    year        = 1990,
    73668202    editor      = {Norman Meyrowitz},
    7367     publisher   = sigplan # " 25(10)",
     8203    publisher   = sigplan,
    73688204    organization= {Association for Computing Machinery},
    73698205    address     = {Ottawa, Canada},
    7370     month       = oct # { 21--25}
     8206    month       = oct,
    73718207}
    73728208
     
    73778213    year        = 1991,
    73788214    editor      = {Andreas Paepcke},
    7379     publisher   = sigplan # " 26(11)",
     8215    publisher   = sigplan,
    73808216    organization= {Association for Computing Machinery},
    73818217    address     = {Phoenix, Arizona},
    7382     month       = oct # { 6--11}
    7383 }
     8218    month       = oct,
     8219}
  • doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls

    r7951100 rb067d9b  
    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#2\par\vspace*{0\p@}}%
     1856    {\abstractfont\baselineskip15pt\ifFWabstract\hsize\textwidth\fi\hsize0.68\textwidth#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@}{-27pt \@plus -2pt \@minus -2pt}{12\p@}{\sectionfont}}%
    2447 \renewcommand\subsection{\@startsection{subsection}{2}{\z@}{-23pt \@plus -2pt \@minus -2pt}{5\p@}{\subsectionfont}}%
     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}}%
    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

    r7951100 rb067d9b  
    3333
    3434DOCUMENT = generic_types.pdf
     35BASE = ${basename ${DOCUMENT}}
    3536
    3637# Directives #
     
    4142
    4243clean :
    43         @rm -frv ${DOCUMENT} ${basename ${DOCUMENT}}.ps ${Build}
     44        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    4445
    4546# File Dependencies #
    4647
    47 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     48${DOCUMENT} : ${BASE}.ps
    4849        ps2pdf $<
    4950
    50 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
     51${BASE}.ps : ${BASE}.dvi
    5152        dvips ${Build}/$< -o $@
    5253
    53 ${basename ${DOCUMENT}}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ../../bibliography/pl.bib
     54${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     55                ../../bibliography/pl.bib | ${Build}
    5456        # Must have *.aux file containing citations for bibtex
    5557        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    6365## Define the default recipes.
    6466
    65 ${Build}:
     67${Build} :
    6668        mkdir -p ${Build}
    6769
     
    6971        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    7072
    71 %.tex : %.fig
     73%.tex : %.fig | ${Build}
    7274        fig2dev -L eepic $< > ${Build}/$@
    7375
    74 %.ps : %.fig
     76%.ps : %.fig | ${Build}
    7577        fig2dev -L ps $< > ${Build}/$@
    7678
    77 %.pstex : %.fig
     79%.pstex : %.fig | ${Build}
    7880        fig2dev -L pstex $< > ${Build}/$@
    7981        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/concurrency/Makefile

    r7951100 rb067d9b  
    44Figures = figures
    55Macros = ../AMA/AMA-stix/ama
    6 TeXLIB = .:annex:../../LaTeXmacros:${Macros}:${Build}:../../bibliography:
     6TeXLIB = .:../../LaTeXmacros:${Macros}:${Build}:
    77LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    8 BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
     8BibTeX = BIBINPUTS=annex:../../bibliography: && export BIBINPUTS && bibtex
    99
    1010MAKEFLAGS = --no-print-directory # --silent
     
    1515SOURCES = ${addsuffix .tex, \
    1616Paper \
    17 style/style \
    18 style/cfa-format \
    1917}
    2018
    2119FIGURES = ${addsuffix .tex, \
    22 monitor \
    23 ext_monitor \
    2420int_monitor \
    2521dependency \
     22RunTimeStructure \
    2623}
    2724
    2825PICTURES = ${addsuffix .pstex, \
     26FullProdConsStack \
     27FullCoroutinePhases \
     28corlayout \
     29CondSigWait \
     30monitor \
     31ext_monitor \
    2932system \
    3033monitor_structs \
     
    5962        dvips ${Build}/$< -o $@
    6063
    61 ${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    62                 annex/local.bib ../../bibliography/pl.bib
     64${BASE}.dvi : Makefile ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     65                annex/local.bib ../../bibliography/pl.bib | ${Build}
    6366        # Must have *.aux file containing citations for bibtex
    6467        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    65         ${BibTeX} ${Build}/${basename $@}
     68        -${BibTeX} ${Build}/${basename $@}
    6669        # Some citations reference others so run again to resolve these citations
    6770        ${LaTeX} ${basename $@}.tex
    68         ${BibTeX} ${Build}/${basename $@}
     71        -${BibTeX} ${Build}/${basename $@}
    6972        # Run again to finish citations
    7073        ${LaTeX} ${basename $@}.tex
     
    7275## Define the default recipes.
    7376
    74 ${Build}:
     77${Build} :
    7578        mkdir -p ${Build}
    7679
    77 ${BASE}.out.ps: ${Build}
     80${BASE}.out.ps : | ${Build}
    7881        ln -fs ${Build}/Paper.out.ps .
    7982
    80 WileyNJD-AMA.bst:
     83WileyNJD-AMA.bst :
    8184        ln -fs ../AMA/AMA-stix/ama/WileyNJD-AMA.bst .
    8285
    83 %.tex : %.fig ${Build}
     86%.tex : %.fig | ${Build}
    8487        fig2dev -L eepic $< > ${Build}/$@
    8588
    86 %.ps : %.fig ${Build}
     89%.ps : %.fig | ${Build}
    8790        fig2dev -L ps $< > ${Build}/$@
    8891
    89 %.pstex : %.fig ${Build}
     92%.pstex : %.fig | ${Build}
    9093        fig2dev -L pstex $< > ${Build}/$@
    9194        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/concurrency/Paper.tex

    r7951100 rb067d9b  
    33\articletype{RESEARCH ARTICLE}%
    44
    5 \received{26 April 2016}
    6 \revised{6 June 2016}
    7 \accepted{6 June 2016}
     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}
    814
    915\raggedbottom
     
    1521\usepackage{epic,eepic}
    1622\usepackage{xspace}
     23\usepackage{enumitem}
    1724\usepackage{comment}
    1825\usepackage{upquote}                                            % switch curled `'" to straight
     
    2128\renewcommand{\thesubfigure}{(\Alph{subfigure})}
    2229\captionsetup{justification=raggedright,singlelinecheck=false}
    23 \usepackage{siunitx}
    24 \sisetup{binary-units=true}
     30\usepackage{dcolumn}                                            % align decimal points in tables
     31\usepackage{capt-of}
     32\setlength{\multicolsep}{6.0pt plus 2.0pt minus 1.5pt}
    2533
    2634\hypersetup{breaklinks=true}
     
    3240\renewcommand{\linenumberfont}{\scriptsize\sffamily}
    3341
     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
    3445\renewcommand{\textfraction}{0.0}                       % the entire page maybe devoted to floats with no text on the page at all
    3546
     
    132143\makeatother
    133144
    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
     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
    140156
    141157% CFA programming language, based on ANSI C (with some gcc additions)
     
    145161                auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
    146162                coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally,
    147                 __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__,
     163                __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__,
    148164                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
    149165                otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread,
    150166                _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,
    151167                virtual, __volatile, __volatile__, waitfor, when, with, zero_t},
    152         moredirectives={defined,include_next}%
     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,
    153174}
    154175
     
    167188aboveskip=4pt,                                                                                  % spacing above/below code block
    168189belowskip=3pt,
    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,
    174190moredelim=**[is][\color{red}]{`}{`},
    175191}% lstset
     
    197213}
    198214
     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
    199236\lstnewenvironment{cfa}[1][]
    200237{\lstset{#1}}
     
    207244{}
    208245\lstnewenvironment{Go}[1][]
    209 {\lstset{#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}}
    210250{}
    211251
     
    222262}
    223263
    224 \title{\texorpdfstring{Concurrency in \protect\CFA}{Concurrency in Cforall}}
     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}}
    225270
    226271\author[1]{Thierry Delisle}
     
    232277\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}}
    233278
    234 \fundingInfo{Natural Sciences and Engineering Research Council of Canada}
     279% \fundingInfo{Natural Sciences and Engineering Research Council of Canada}
    235280
    236281\abstract[Summary]{
    237 \CFA is a modern, polymorphic, \emph{non-object-oriented} extension of the C programming language.
    238 This paper discusses the design of the concurrency and parallelism features in \CFA, and the concurrent runtime-system.
    239 These features are created from scratch as ISO C lacks concurrency, relying largely on the pthreads library.
    240 Coroutines and lightweight (user) threads are introduced into the language.
    241 In addition, monitors are added as a high-level mechanism for mutual exclusion and synchronization.
    242 A unique contribution is allowing multiple monitors to be safely acquired simultaneously.
    243 All features respect the expectations of C programmers, while being fully integrate with the \CFA polymorphic type-system and other language features.
    244 Finally, experimental results are presented to compare the performance of the new features with similar mechanisms in other concurrent programming-languages.
     282\CFA is a polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language.
     283This paper discusses the design philosophy and implementation of its advanced control-flow and concurrent/parallel features, along with the supporting runtime written in \CFA.
     284These 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.
     287The runtime provides significant programmer simplification and safety by eliminating spurious wakeup and monitor barging.
     288The runtime also ensures multiple monitors can be safely acquired \emph{simultaneously} (deadlock free), and this feature is fully integrated with all monitor synchronization mechanisms.
     289All control-flow features integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers.
     290Experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming languages.
    245291}%
    246292
    247 \keywords{concurrency, parallelism, coroutines, threads, monitors, runtime, C, Cforall}
     293\keywords{generator, coroutine, concurrency, parallelism, thread, monitor, runtime, C, \CFA (Cforall)}
    248294
    249295
     
    256302\section{Introduction}
    257303
    258 This paper provides a minimal concurrency \newterm{Application Program Interface} (API) that is simple, efficient and can be used to build other concurrency features.
    259 While the simplest concurrency system is a thread and a lock, this low-level approach is hard to master.
    260 An easier approach for programmers is to support higher-level constructs as the basis of concurrency.
    261 Indeed, for highly productive concurrent programming, high-level approaches are much more popular~\cite{Hochstein05}.
    262 Examples 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 
    264 The following terminology is used.
    265 A \newterm{thread} is a fundamental unit of execution that runs a sequence of code and requires a stack to maintain state.
    266 Multiple 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.
    270 Parallelism implies \emph{actual} simultaneous execution, where concurrency only requires \emph{apparent} simultaneous execution.
    271 As such, parallelism only affects performance, which is observed through differences in space and/or time at runtime.
    272 
    273 Hence, there are two problems to be solved: concurrency and parallelism.
    274 While these two concepts are often combined, they are distinct, requiring different tools~\cite[\S~2]{Buhr05a}.
    275 Concurrency tools handle synchronization and mutual exclusion, while parallelism tools handle performance, cost and resource utilization.
    276 
    277 The proposed concurrency API is implemented in a dialect of C, called \CFA.
    278 The 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 
    283 The following is a quick introduction to the \CFA language, specifically tailored to the features needed to support concurrency.
    284 Extended 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.
    288 Like C, the basics of \CFA revolve around structures and routines.
    289 Virtually all of the code generated by the \CFA translator respects C memory layouts and calling conventions.
    290 While \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}.
    291 While 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}
    298 int x = 1, y = 2, z = 3;
    299 int * p1 = &x, ** p2 = &p1,  *** p3 = &p2,      $\C{// pointers to x}$
    300         `&` r1 = x,  `&&` r2 = r1,  `&&&` r3 = r2;      $\C{// references to x}$
    301 int * p4 = &z, `&` r4 = z;
    302 
    303 *p1 = 3; **p2 = 3; ***p3 = 3;       // change x
    304 r1 =  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}
    308 A reference is a handle to an object, like a pointer, but is automatically dereferenced by the specified number of levels.
    309 Referencing (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 
    315 Heterogeneous data is aggregated into a structure/union.
    316 To 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}
    321 struct S { char c; int i; double d; };
    322 struct 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}
    327 void 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}
    334 void 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}
    342 Object-oriented programming languages only provide implicit qualification for the receiver.
    343 
    344 In 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}
    349 and may appear as the body of a routine or nested within a routine body.
    350 Each expression in the expression-list provides a type and object.
    351 The type must be an aggregate type.
    352 (Enumerations are already opened.)
    353 The object is the implicit qualifier for the open structure-fields.
    354 All 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.
    360 Both 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}
    369 const short int `MIN` = -32768;
    370 const int `MIN` = -2147483648;
    371 const long int `MIN` = -9223372036854775808L;
    372 \end{cfa}
    373 &
    374 \begin{cfa}
    375 short int si = `MIN`;
    376 int i = `MIN`;
    377 long 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}
    385 void `f`( void );
    386 void `f`( char );
    387 void `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}
    401 char `f`( int );
    402 double `f`( int );
    403 [char, double] `f`( int );
    404 \end{cfa}
    405 &
    406 \begin{cfa}
    407 char c = `f`( 3 );
    408 double d = `f`( 3 );
    409 [d, c] = `f`( 3 );
    410 \end{cfa}
    411 \end{tabular}
    412 \lstMakeShortInline@%
    413 \end{cquote}
    414 Overloading is important for \CFA concurrency since the runtime system relies on creating different types to represent concurrency objects.
    415 Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions to prevent name clashes.
    416 As seen in Section~\ref{basics}, routine @main@ is heavily overloaded.
    417 
    418 Variable overloading is useful in the parallel semantics of the @with@ statement for fields with the same name:
    419 \begin{cfa}
    420 struct S { int `i`; int j; double m; } s;
    421 struct T { int `i`; int k; int m; } t;
    422 with ( 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}
    432 For 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 
    437 Overloading also extends to operators.
    438 Operator-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}
    443 int ++? (int op);
    444 int ?++ (int op);
    445 int `?+?` (int op1, int op2);
    446 int ?<=?(int op1, int op2);
    447 int ?=? (int & op1, int op2);
    448 int ?+=?(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}
    461 struct S { int i, j; };
    462 S `?+?`( S op1, S op2) { // add two structures
    463         return (S){op1.i + op2.i, op1.j + op2.j};
    464 }
    465 S s1 = {1, 2}, s2 = {2, 3}, s3;
    466 s3 = s1 `+` s2;         // compute sum: s3 == {2, 5}
    467 \end{cfa}
    468 \end{tabular}
    469 \lstMakeShortInline@%
    470 \end{cquote}
    471 While 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 
    477 The 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.
    478 For 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}
    480 forall( otype T | { void `?{}`( T *, zero_t ); T `?+?`( T, T ); } ) // constraint type, 0 and +
    481 T 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 }
    487 S sa[5];
    488 int 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}
    493 trait `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 };
    500 forall( otype T `| sumable( T )` )                      $\C{// use trait}$
    501 T sum( T a[$\,$], size_t size );
    502 \end{cfa}
    503 
    504 Assertions 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 
    508 Using the return type for discrimination, it is possible to write a type-safe @alloc@ based on the C @malloc@:
    509 \begin{cfa}
    510 forall( dtype T | sized(T) ) T * alloc( void ) { return (T *)malloc( sizeof(T) ); }
    511 int * ip = alloc();                                                     $\C{// select type and size from left-hand side}$
    512 double * dp = alloc();
    513 struct S {...} * sp = alloc();
    514 \end{cfa}
    515 where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    516 
    517 
    518 \subsection{Constructors / Destructors}
    519 
    520 Object lifetime is a challenge in non-managed programming languages.
    521 \CFA responds with \CC-like constructors and destructors:
    522 \begin{cfa}
    523 struct VLA { int len, * data; };                        $\C{// variable length array of integers}$
    524 void ?{}( VLA & vla ) with ( vla ) { len = 10;  data = alloc( len ); }  $\C{// default constructor}$
    525 void ?{}( VLA & vla, int size, char fill ) with ( vla ) { len = size;  data = alloc( len, fill ); } // initialization
    526 void ?{}( VLA & vla, VLA other ) { vla.len = other.len;  vla.data = other.data; } $\C{// copy, shallow}$
    527 void ^?{}( 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}
    540 Like \CC, construction is implicit on allocation (stack/heap) and destruction is implicit on deallocation.
    541 The 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}$
    547 struct S * s = new();                                           $\C{// allocation, call constructor}$
    548 ...
    549 delete( 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 
    556 At its core, concurrency is based on multiple call-stacks and scheduling threads executing on these stacks.
    557 Multiple 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}.
    558 In 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.
    559 A \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;
    560 a \newterm{stackfull} coroutine executes on its own stack, allowing full generality.
    561 Only stackfull coroutines are a stepping-stone to concurrency.
    562 
    563 The 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}.
    564 Therefore, a minimal concurrency system is possible using coroutines (see Section \ref{coroutine}) in conjunction with a scheduler to decide where to context switch next.
    565 The resulting execution system now follows a cooperative threading-model, called \newterm{non-preemptive scheduling}.
    566 
    567 Because 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.}
    568 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.
    569 For 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.
    570 A 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 
    572 Regardless of the approach used, a subset of concurrency related challenges start to appear.
    573 For 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}.
    574 While a scheduler introduces uncertainty in the order of execution, preemption introduces uncertainty where context switches occur.
    575 Interestingly, uncertainty is necessary for the runtime (operating) system to give the illusion of parallelism on a single processor and increase performance on multiple processors.
    576 The reason is that only the runtime has complete knowledge about resources and how to best utilized them.
    577 However, the introduction of unrestricted non-determinism results in the need for \newterm{mutual exclusion} and \newterm{synchronization} to restrict non-determinism for correctness;
    578 otherwise, it is impossible to write meaningful programs.
    579 Optimal 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 
    584 An important missing feature in C is threading\footnote{While the C11 standard defines a ``threads.h'' header, it is minimal and defined as optional.
    585 As such, library support for threading is far from widespread.
    586 At the time of writing the paper, neither \protect\lstinline|gcc| nor \protect\lstinline|clang| support ``threads.h'' in their standard libraries.}.
    587 In 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.
    588 As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers familiar with imperative languages.
    589 Furthermore, because C is a system-level language, programmers expect to choose precisely which features they need and which cost they are willing to pay.
    590 Hence, 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 
    595 While 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.
    596 Coroutines are generalized routines allowing execution to be temporarily suspend and later resumed.
    597 Hence, 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.
    598 This capability is accomplish via the coroutine's stack, where suspend/resume context switch among stacks.
    599 Because 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.
    600 Therefore, the core \CFA coroutine-API for has two fundamental features: independent call-stacks and @suspend@/@resume@ operations.
    601 
    602 For 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}
    606 0                                       & n = 0         \\
    607 1                                       & n = 1         \\
    608 \mathsf{fib}(n-1) + \mathsf{fib}(n-2)   & n \ge 2       \\
    609 \end{array}
    610 \right.
    611 \end{displaymath}
    612 Figure~\ref{f:GlobalVariables} illustrates the following problems:
    613 unique unencapsulated global variables necessary to retain state between calls;
    614 only one Fibonacci generator;
    615 execution state must be explicitly retained via explicit state variables.
    616 Figure~\ref{f:ExternalState} addresses these issues:
    617 unencapsulated program global variables become encapsulated structure variables;
    618 unique global variables are replaced by multiple Fibonacci objects;
    619 explicit execution state is removed by precomputing the first two Fibonacci numbers and returning $\mathsf{fib}(n-2)$.
     304This 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.
     307However, 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.},
     308backwards-compatible extension of the C programming language.
     309In 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.
     310Within 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}.
     311However, \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;
     312no high-level language concurrency features are defined.
     313Interestingly, 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).
     314Finally, 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
     316In contrast, there has been a renewed interest during the past decade in user-level (M:N, green) threading in old and new programming languages.
     317As multi-core hardware became available in the 1980/90s, both user and kernel threading were examined.
     318Kernel 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}.
     319Libraries like pthreads were developed for C, and the Solaris operating-system switched from user (JDK 1.1~\cite{JDK1.1}) to kernel threads.
     320As 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.
     321From 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}.
     322The 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}.
     323As well, user-threading facilitates a simpler concurrency approach using thread objects that leverage sequential patterns versus events with call-backs~\cite{Adya02,vonBehren03}.
     324Finally, 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
     326A 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}.
     327The 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.
     328One solution is low-level qualifiers and functions (\eg @volatile@ and atomics) allowing \emph{programmers} to explicitly write safe (race-free~\cite{Boehm12}) programs.
     329A safer solution is high-level language constructs so the \emph{compiler} knows the optimization boundaries, and hence, provides implicit safety.
     330This 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.
     332The 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.
     334Finally, 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
     336Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety for performance when necessary.
     337Two concurrency violations of this philosophy are \emph{spurious wakeup} (random wakeup~\cite[\S~8]{Buhr05a}) and \emph{barging}\footnote{
     338The 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.
     340However, spurious wakeup is \emph{not} a foundational concurrency property~\cite[\S~8]{Buhr05a}, it is a performance design choice.
     341Similarly, signals-as-hints are often a performance decision.
     342We 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.)
     344Clawing back performance, when local non-determinism is unimportant, should be an option not the default.
     345
     346\begin{comment}
     347Most 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.
     348As a result, there is a significant learning curve to move to these languages, and C legacy-code must be rewritten.
     349While \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.
     350Hence, 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.
     355We 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.
     356The main contributions of this work are:
     357\begin{itemize}[topsep=3pt,itemsep=1pt]
     358\item
     359language-level generators, coroutines and user-level threading, which respect the expectations of C programmers.
     360\item
     361monitor 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
     363providing 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
     367a runtime system with no spurious wakeup.
     368\item
     369a dynamic partitioning mechanism to segregate the execution environment for specialized requirements.
     370% \item
     371% a non-blocking I/O library
     372\item
     373experimental results showing comparable performance of the new features with similar mechanisms in other programming languages.
     374\end{itemize}
     375
     376Section~\ref{s:StatefulFunction} begins advanced control by introducing sequential functions that retain data and execution state between calls, which produces constructs @generator@ and @coroutine@.
     377Section~\ref{s:Concurrency} begins concurrency, or how to create (fork) and destroy (join) a thread, which produces the @thread@ construct.
     378Section~\ref{s:MutualExclusionSynchronization} discusses the two mechanisms to restricted nondeterminism when controlling shared access to resources (mutual exclusion) and timing relationships among threads (synchronization).
     379Section~\ref{s:Monitor} shows how both mutual exclusion and synchronization are safely embedded in the @monitor@ and @thread@ constructs.
     380Section~\ref{s:CFARuntimeStructure} describes the large-scale mechanism to structure (cluster) threads and virtual processors (kernel threads).
     381Section~\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
     387The 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.
     388Hence, 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.
     389This capability is accomplished by retaining a data/execution \emph{closure} between invocations.
     390If 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.
     391If 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.
     392Hence, refactoring a stackless coroutine may require changing it to stackful.
     393A 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.
     394As well, activating a stateful function is \emph{asymmetric} or \emph{symmetric}, identified by resume/suspend (no cycles) and resume/resume (cycles).
     395A fixed closure activated by modified call/return is faster than a variable closure activated by context switching.
     396Additionally, any storage management for the closure (especially in unmanaged languages, \ie no garbage collection) must also be factored into design and performance.
     397Therefore, selecting between stackless and stackful semantics is a tradeoff between programming requirements and performance, where stackless is faster and stackful is more general.
     398Note, creation cost is amortized across usage, so activation cost is usually the dominant factor.
    620399
    621400\begin{figure}
    622401\centering
    623 \newbox\myboxA
    624402\begin{lrbox}{\myboxA}
    625403\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    626 `int f1, f2, state = 1;`   // single global variables
    627 int 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         }
     404typedef struct {
     405        int fn1, fn;
     406} Fib;
     407#define FibCtor { 1, 0 }
     408int fib( Fib * f ) {
     409
     410
     411
     412        int fn = f->fn; f->fn = f->fn1;
     413                f->fn1 = f->fn + fn;
    634414        return fn;
     415
    635416}
    636417int main() {
    637 
    638         for ( int i = 0; i < 10; i += 1 ) {
    639                 printf( "%d\n", fib() );
    640         }
     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 ) );
    641422}
    642423\end{cfa}
    643424\end{lrbox}
    644425
    645 \newbox\myboxB
    646426\begin{lrbox}{\myboxB}
    647427\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    648 #define FIB_INIT `{ 0, 1 }`
    649 typedef struct { int f2, f1; } Fib;
    650 int 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;
     428`generator` Fib {
     429        int fn1, fn;
     430};
     431
     432void `main(Fib & fib)` with(fib) {
     433
     434        [fn1, fn] = [1, 0];
     435        for () {
     436                `suspend;`
     437                [fn1, fn] = [fn, fn + fn1];
     438
     439        }
    657440}
    658441int 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 ) );
     442        Fib f1, f2;
     443        for ( 10 )
     444                sout | `resume( f1 )`.fn
     445                         | `resume( f2 )`.fn;
     446}
     447\end{cfa}
     448\end{lrbox}
     449
     450\begin{lrbox}{\myboxC}
     451\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     452typedef struct {
     453        int fn1, fn;  void * `next`;
     454} Fib;
     455#define FibCtor { 1, 0, NULL }
     456Fib * 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;
    662463        }
    663464}
     465int 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}
    664471\end{cfa}
    665472\end{lrbox}
    666473
    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}
     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}
    672485
    673486\bigskip
    674487
    675 \newbox\myboxA
    676488\begin{lrbox}{\myboxA}
    677489\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    678 `coroutine` Fib { int fn; };
    679 void 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()`;
     490`generator Fmt` {
     491        char ch;
     492        int g, b;
     493};
     494void ?{}( Fmt & fmt ) { `resume(fmt);` } // constructor
     495void ^?{}( Fmt & f ) with(f) { $\C[1.75in]{// destructor}$
     496        if ( g != 0 || b != 0 ) sout | nl; }
     497void `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
    685506        }
    686507}
    687 int next( Fib & fib ) with( fib ) {
    688         `resume( fib );`
    689         return fn;
    690 }
    691508int main() {
    692         Fib f1, f2;
    693         for ( int i = 1; i <= 10; i += 1 ) {
    694                 sout | next( f1 ) | next( f2 ) | endl;
     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 );`
    695514        }
    696 }
     515
     516} $\C{// fmt destructor called}\CRT$
    697517\end{cfa}
    698518\end{lrbox}
    699 \newbox\myboxB
     519
    700520\begin{lrbox}{\myboxB}
    701521\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    702 `coroutine` Fib { int ret; };
    703 void main( Fib & f ) with( fib ) {
    704         int fn, f1 = 1, f2 = 0;
     522typedef struct {
     523        void * next;
     524        char ch;
     525        int g, b;
     526} Fmt;
     527void comain( Fmt * f ) {
     528        if ( f->next ) goto *f->next;
     529        f->next = &&s1;
    705530        for ( ;; ) {
    706                 ret = f2;
    707 
    708                 fn = f1 + f2;  f2 = f1;  f1 = fn; `suspend();`
     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" );
    709538        }
    710539}
    711 int next( Fib & fib ) with( fib ) {
    712         `resume( fib );`
    713         return ret;
    714 }
    715 
    716 
    717 
    718 
    719 
    720 
     540int 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}
    721549\end{cfa}
    722550\end{lrbox}
    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}
     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}
    728560\end{figure}
    729561
    730 Using a coroutine, it is possible to express the Fibonacci formula directly without any of the C problems.
    731 Figure~\ref{f:Coroutine3States} creates a @coroutine@ type:
    732 \begin{cfa}
    733 `coroutine` Fib { int fn; };
    734 \end{cfa}
    735 which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface routines @next@.
    736 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.
    737 The 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.
    738 The interface routine @next@, takes a Fibonacci instance and context switches to it using @resume@;
    739 on restart, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.
    740 The first @resume@ is special because it cocalls the coroutine at its coroutine main and allocates the stack;
    741 when the coroutine main returns, its stack is deallocated.
    742 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.
    743 Figure~\ref{f:Coroutine1State} shows the coroutine version of the C version in Figure~\ref{f:ExternalState}.
    744 Coroutine generators are called \newterm{output coroutines} because values are only returned.
    745 
    746 Figure~\ref{f:CFAFmt} shows an \newterm{input coroutine}, @Format@, for restructuring text into groups of characters of fixed-size blocks.
    747 For example, the input of the left is reformatted into the output on the right.
    748 \begin{quote}
     562Stateful functions appear as generators, coroutines, and threads, where presentations are based on function objects or pointers~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
     563For example, Python presents generators as a function object:
     564\begin{python}
     565def Gen():
     566        ... `yield val` ...
     567gen = Gen()
     568for i in range( 10 ):
     569        print( next( gen ) )
     570\end{python}
     571Boost presents coroutines in terms of four functor object-types:
     572\begin{cfa}
     573asymmetric_coroutine<>::pull_type
     574asymmetric_coroutine<>::push_type
     575symmetric_coroutine<>::call_type
     576symmetric_coroutine<>::yield_type
     577\end{cfa}
     578and 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}
     580void * rtn( void * arg ) { ... }
     581int i = 3, rc;
     582pthread_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.
     595Essentially, the generator/coroutine/thread function is semantically coupled with a generator/coroutine/thread custom type.
     596The custom type solves several issues, while accessing the underlying mechanisms used by the custom types is still allowed.
     597
     598
     599\subsection{Generator}
     600
     601Stackless generators have the potential to be very small and fast, \ie as small and fast as function call/return for both creation and execution.
     602The \CFA goal is to achieve this performance target, possibly at the cost of some semantic complexity.
     603A series of different kinds of generators and their implementation demonstrate how this goal is accomplished.
     604
     605Figure~\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.
     606This generator is an \emph{output generator}, producing a new result on each resumption.
     607To 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.
     608An additional requirement is the ability to create an arbitrary number of generators (of any kind), \ie retaining one state in global variables is insufficient;
     609hence, state is retained in a closure between calls.
     610Figure~\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.
     611The C version only has the middle execution state because the top execution state is declaration initialization.
     612Figure~\ref{f:CFAFibonacciGen} shows the \CFA approach, which also has a manual closure, but replaces the structure with a custom \CFA @generator@ type.
     613This generator type is then connected to a function that \emph{must be named \lstinline|main|},\footnote{
     614The name \lstinline|main| has special meaning in C, specifically the function where a program starts execution.
     615Hence, overloading this name for other starting points (generator/coroutine/thread) is a logical extension.}
     616called a \emph{generator main},which takes as its only parameter a reference to the generator type.
     617The generator main contains @suspend@ statements that suspend execution without ending the generator versus @return@.
     618For the Fibonacci generator-main,\footnote{
     619The \CFA \lstinline|with| opens an aggregate scope making its fields directly accessible, like Pascal \lstinline|with|, but using parallel semantics.
     620Multiple aggregates may be opened.}
     621the top initialization state appears at the start and the middle execution state is denoted by statement @suspend@.
     622Any local variables in @main@ \emph{are not retained} between calls;
     623hence local variables are only for temporary computations \emph{between} suspends.
     624All retained state \emph{must} appear in the generator's type.
     625As 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.
     626The 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.
     627Resuming an ended (returned) generator is undefined.
     628Function @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.
     629Figure~\ref{f:CFibonacciSim} shows the C implementation of the \CFA generator only needs one additional field, @next@, to handle retention of execution state.
     630The computed @goto@ at the start of the generator main, which branches after the previous suspend, adds very little cost to the resume call.
     631Finally, an explicit generator type provides both design and performance benefits, such as multiple type-safe interface functions taking and returning arbitrary types.\footnote{
     632The \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}
     635int ?()( Fib & fib ) { return `resume( fib )`.fn; } $\C[3.9in]{// function-call interface}$
     636int ?()( Fib & fib, int N ) { for ( N - 1 ) `fib()`; return `fib()`; } $\C{// use function-call interface to skip N values}$
     637double ?()( Fib & fib ) { return (int)`fib()` / 3.14159; } $\C{// different return type, cast prevents recursive call}\CRT$
     638sout | (int)f1() | (double)f1() | f2( 2 ); // alternative interface, cast selects call based on return type, step 2 values
     639\end{cfa}
     640Now, the generator can be a separately compiled opaque-type only accessed through its interface functions.
     641For 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
     643Having 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}.)
     645This 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.
     646However, dynamic allocation significantly increases the cost of generator creation/destruction and is a showstopper for embedded real-time programming.
     647But 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.
     648With 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.
     649Finally, 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.
     650As well, C programmers are not afraid of this kind of semantic programming requirement, if it results in very small, fast generators.
     651
     652Figure~\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}
    749654\tt
    750655\begin{tabular}{@{}l|l@{}}
    751656\multicolumn{1}{c|}{\textbf{\textrm{input}}} & \multicolumn{1}{c}{\textbf{\textrm{output}}} \\
    752 abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
     657\begin{tabular}[t]{@{}ll@{}}
     658abcdefghijklmnopqrstuvwxyz \\
     659abcdefghijklmnopqrstuvwxyz
     660\end{tabular}
    753661&
    754662\begin{tabular}[t]{@{}lllll@{}}
     
    758666\end{tabular}
    759667\end{tabular}
    760 \end{quote}
    761 The 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.
    762 The destruction provides a newline if formatted text ends with a full line.
    763 Figure~\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.
     668\end{center}
     669The 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.
     670The destructor provides a newline, if formatted text ends with a full line.
     671Figure~\ref{f:CFormatSim} shows the C implementation of the \CFA input generator with one additional field and the computed @goto@.
     672For contrast, Figure~\ref{f:PythonFormatter} shows the equivalent Python format generator with the same properties as the Fibonacci generator.
     673
     674Figure~\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}.
     675Device drives follow the pattern of simple data state but complex execution state, \ie finite state-machine (FSM) parsing a protocol.
     676For 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}
     680is a network message beginning with the control character STX, ending with an ETX, and followed by a 2-byte cyclic-redundancy check.
     681Control characters may appear in a message if preceded by an ESC.
     682When 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.
     683The 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.
     684Hence, the device driver is an input/output generator.
     685
     686Note, 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.
     687As 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.
     689In contrast, the execution state is large, with one @resume@ and seven @suspend@s.
     690Hence, 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.
     691Because FSMs can be complex and frequently occur in important domains, direct generator support is important in a system programming language.
    764692
    765693\begin{figure}
     
    767695\newbox\myboxA
    768696\begin{lrbox}{\myboxA}
     697\begin{python}[aboveskip=0pt,belowskip=0pt]
     698def Fib():
     699        fn1, fn = 0, 1
     700        while True:
     701                `yield fn1`
     702                fn1, fn = fn, fn1 + fn
     703f1 = Fib()
     704f2 = Fib()
     705for 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]
     719def 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()
     730fmt = Fmt()
     731`next( fmt )`                    # prime, next prewritten
     732for 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@{}}
    769747\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    770 `coroutine` Format {
    771         char ch;   // used for communication
    772         int g, b;  // global because used in destructor
     748enum 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;
    773755};
    774 void 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
     756void ?{}( Driver & d, char * m ) { d.msg = m; }
     757Status next( Driver & d, char b ) with( d ) {
     758        byte = b; `resume( d );` return status;
     759}
     760void 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;`
    780779                        }
    781                         sout | "  ";               // separator
     780                        if ( lnth >= MaxMsg ) { // buffer full ?
     781                                status = ELNTH; `suspend;` continue msg; }
     782                        msg[lnth++] = byte;
     783                        sum += byte;
    782784                }
    783                 sout | endl;
     785                msg[lnth] = '\0'; // terminate string
     786                `suspend;`
     787                crc = byte << 8;
     788                `suspend;`
     789                status = (crc | byte) == sum ? MSG : ECRC;
     790                `suspend;`
    784791        }
    785792}
    786 void ?{}( Format & fmt ) { `resume( fmt );` }
    787 void ^?{}( Format & fmt ) with( fmt ) {
    788         if ( g != 0 || b != 0 ) sout | endl;
    789 }
    790 void format( Format & fmt ) {
    791         `resume( fmt );`
     793\end{cfa}
     794\end{tabular}
     795\caption{Device-driver generator for communication protocol}
     796\label{f:DeviceDriverGen}
     797\end{figure}
     798
     799Figure~\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.)
     801This control flow is similar to recursion for functions but without stack growth.
     802The steps for symmetric control-flow are creating, executing, and terminating the cycle.
     803Constructing 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.
     807Once 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).
     808Terminating 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).
     809The starting stack-frame is below the last active generator because the resume/resume cycle does not grow the stack.
     810Also, 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.
     811Destructor cost occurs when the generator instance is deallocated, which is easily controlled by the programmer.
     812
     813Figure~\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.
     814This 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.
     815However, before the jump, the caller must reset its stack (and any registers) equivalent to a @return@, but subsequently jump forward.
     816This semantics is basically a tail-call optimization, which compilers already perform.
     817The example shows the assembly code to undo the generator's entry code before the direct jump.
     818This assembly code depends on what entry code is generated, specifically if there are local variables and the level of optimization.
     819To provide this new calling convention requires a mechanism built into the compiler, which is beyond the scope of \CFA at this time.
     820Nevertheless, it is possible to hand generate any symmetric generators for proof of concept and performance testing.
     821A 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
     834void `main( PingPong & pp )` with(pp) {
     835        for ( ; i < N; i += 1 ) {
     836                sout | name | i;
     837                `resume( partner );`
     838        }
    792839}
    793840int main() {
    794         Format fmt;
    795         eof: for ( ;; ) {
    796                 sin | fmt.ch;
    797           if ( eof( sin ) ) break eof;
    798                 format( fmt );
     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]
     851typedef 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}
     858void 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
     883Finally, part of this generator work was inspired by the recent \CCtwenty generator proposal~\cite{C++20Coroutine19} (which they call coroutines).
     884Our work provides the same high-performance asymmetric generators as \CCtwenty, and extends their work with symmetric generators.
     885An 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}
     890Since the current generator's stack is released before calling the compound statement, the compound statement can only reference variables in the generator's type.
     891This 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.
     892Hence, this mechanism provides a general and safe handoff of the generator among competing threads.
     893
     894
     895\subsection{Coroutine}
     896\label{s:Coroutine}
     897
     898Stackful coroutines extend generator semantics, \ie there is an implicit closure and @suspend@ may appear in a helper function called from the coroutine main.
     899A coroutine is specified by replacing @generator@ with @coroutine@ for the type.
     900Coroutine 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.
     901A series of different kinds of coroutines and their implementations demonstrate how coroutines extend generators.
     902
     903First, 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]
     906Move the declaration of @fn1@ to the start of coroutine main.
     907\begin{cfa}[xleftmargin=0pt]
     908void main( Fib & fib ) with(fib) {
     909        `int fn1;`
     910\end{cfa}
     911\item[Formatter]
     912Move the declaration of @g@ and @b@ to the for loops in the coroutine main.
     913\begin{cfa}[xleftmargin=0pt]
     914for ( `g`; 5 ) {
     915        for ( `b`; 4 ) {
     916\end{cfa}
     917\item[Device Driver]
     918Move 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]
     926Move the declaration of @i@ to the for loop in the coroutine main.
     927\begin{cfa}[xleftmargin=0pt]
     928void main( PingPong & pp ) with(pp) {
     929        for ( `i`; N ) {
     930\end{cfa}
     931\end{description}
     932It 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}
     934unsigned 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}
     942A call to this function is placed at the end of the driver's coroutine-main.
     943For complex finite-state machines, refactoring is part of normal program abstraction, especially when code is used in multiple places.
     944Again, this complexity is usually associated with execution state rather than data state.
     945
     946\begin{comment}
     947Figure~\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@.
     948Like 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.
     949The 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@.
     950The interface function @next@, takes a Fibonacci instance and context switches to it using @resume@;
     951on restart, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.
     952The first @resume@ is special because it allocates the coroutine stack and cocalls its coroutine main on that stack;
     953when the coroutine main returns, its stack is deallocated.
     954Hence, @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.
     955Figure~\ref{f:Coroutine1State} shows the coroutine version of the C version in Figure~\ref{f:ExternalState}.
     956Coroutine 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 }
     984typedef struct { int fn1, fn; } Fib;
     985int 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
     995int 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 ) );
    7991000        }
    8001001}
     
    8051006\begin{lrbox}{\myboxB}
    8061007\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    807 struct Format {
    808         char ch;
    809         int g, b;
    810 };
    811 void 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" );
     1008`coroutine` Fib { int fn1; };
     1009void main( Fib & fib ) with( fib ) {
     1010        int fn;
     1011        [fn1, fn] = [0, 1];
     1012        for () {
     1013                `suspend;`
     1014                [fn1, fn] = [fn, fn1 + fn];
    8261015        }
    8271016}
     1017int ?()( Fib & fib ) with( fib ) {
     1018        return `resume( fib )`.fn1;
     1019}
    8281020int main() {
    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 }
     1021        Fib f1, f2;
     1022        for ( 10 ) {
     1023                sout | f1() | f2();
     1024}
     1025
     1026
    8381027\end{cfa}
    8391028\end{lrbox}
    840 \subfloat[\CFA Coroutine]{\label{f:CFAFmt}\usebox\myboxA}
     1029
     1030\newbox\myboxC
     1031\begin{lrbox}{\myboxC}
     1032\begin{python}[aboveskip=0pt,belowskip=0pt]
     1033
     1034def 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
     1045f1 = Fib()
     1046f2 = Fib()
     1047for 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}
     1066\end{figure}
     1067
     1068\bigskip
     1069
     1070\newbox\myboxA
     1071\begin{lrbox}{\myboxA}
     1072\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     1073`coroutine` Fib { int fn; };
     1074void 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}
     1080int next( Fib & fib ) with( fib ) { `resume( fib );` return fn; }
     1081int 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
     1092def 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
     1099f1 = Fibonacci()
     1100f2 = Fibonacci()
     1101for 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}
    8411107\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}
     1108\subfloat[Python]{\label{f:Coroutine1State}\usebox\myboxB}
     1109\caption{Fibonacci input coroutine, 3 states, internal variables}
     1110\label{f:cfa-fibonacci}
    8451111\end{figure}
    846 
    847 The 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
    848 However, 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.)
    851 This control flow is similar to recursion for normal routines, but again there is no stack growth from the context switch.
     1112\end{comment}
    8521113
    8531114\begin{figure}
     
    8571118\begin{cfa}
    8581119`coroutine` Prod {
    859         Cons & c;
     1120        Cons & c;                       // communication
    8601121        int N, money, receipt;
    8611122};
    8621123void main( Prod & prod ) with( prod ) {
    8631124        // 1st resume starts here
    864         for ( int i = 0; i < N; i += 1 ) {
     1125        for ( i; N ) {
    8651126                int p1 = random( 100 ), p2 = random( 100 );
    866                 sout | p1 | " " | p2 | endl;
     1127                sout | p1 | " " | p2;
    8671128                int status = delivery( c, p1, p2 );
    868                 sout | " $" | money | endl | status | endl;
     1129                sout | " $" | money | nl | status;
    8691130                receipt += 1;
    8701131        }
    8711132        stop( c );
    872         sout | "prod stops" | endl;
     1133        sout | "prod stops";
    8731134}
    8741135int payment( Prod & prod, int money ) {
     
    8911152\begin{cfa}
    8921153`coroutine` Cons {
    893         Prod & p;
     1154        Prod & p;                       // communication
    8941155        int p1, p2, status;
    895         _Bool done;
     1156        bool done;
    8961157};
    8971158void ?{}( Cons & cons, Prod & p ) {
    898         &cons.p = &p;
     1159        &cons.p = &p; // reassignable reference
    8991160        cons.[status, done ] = [0, false];
    9001161}
    901 void ^?{}( Cons & cons ) {}
    9021162void main( Cons & cons ) with( cons ) {
    9031163        // 1st resume starts here
    9041164        int money = 1, receipt;
    9051165        for ( ; ! done; ) {
    906                 sout | p1 | " " | p2 | endl | " $" | money | endl;
     1166                sout | p1 | " " | p2 | nl | " $" | money;
    9071167                status += 1;
    9081168                receipt = payment( p, money );
    909                 sout | " #" | receipt | endl;
     1169                sout | " #" | receipt;
    9101170                money += 1;
    9111171        }
    912         sout | "cons stops" | endl;
     1172        sout | "cons stops";
    9131173}
    9141174int delivery( Cons & cons, int p1, int p2 ) {
     
    9211181        `resume( cons );`
    9221182}
     1183
    9231184\end{cfa}
    9241185\end{tabular}
    925 \caption{Producer / consumer: resume-resume cycle, bi-directional communication}
     1186\caption{Producer / consumer: resume-resume cycle, bidirectional communication}
    9261187\label{f:ProdCons}
    9271188\end{figure}
    9281189
    929 Figure~\ref{f:ProdCons} shows a producer/consumer symmetric-coroutine performing bi-directional communication.
    930 Since 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@.
    931 The @start@ routine communicates both the number of elements to be produced and the consumer into the producer's coroutine structure.
    932 Then 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.
     1190Figure~\ref{f:ProdCons} shows the ping-pong example in Figure~\ref{f:CFAPingPongGen} extended into a producer/consumer symmetric-coroutine performing bidirectional communication.
     1191This example is illustrative because both producer/consumer have two interface functions with @resume@s that suspend execution in these interface (helper) functions.
     1192The 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.
     1193The 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.
    9341195
    9351196The producer call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status.
    936 For the first resume, @cons@'s stack is initialized, creating local variables retained between subsequent activations of the coroutine.
    937 The 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).
    938 The call from the consumer to the @payment@ introduces the cycle between producer and consumer.
     1197On the first resume, @cons@'s stack is created and initialized, holding local-state variables retained between subsequent activations of the coroutine.
     1198The 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).
     1199The call from the consumer to @payment@ introduces the cycle between producer and consumer.
    9391200When @payment@ is called, the consumer copies values into the producer's communication variable and a resume is executed.
    940 The context switch restarts the producer at the point where it was last context switched, so it continues in @delivery@ after the resume.
    941 
     1201The context switch restarts the producer at the point where it last context switched, so it continues in @delivery@ after the resume.
    9421202@delivery@ returns the status value in @prod@'s coroutine main, where the status is printed.
    9431203The loop then repeats calling @delivery@, where each call resumes the consumer coroutine.
     
    9451205The consumer increments and returns the receipt to the call in @cons@'s coroutine main.
    9461206The loop then repeats calling @payment@, where each call resumes the producer coroutine.
    947 
    948 After iterating $N$ times, the producer calls @stop@.
    949 The @done@ flag is set to stop the consumer's execution and a resume is executed.
    950 The context switch restarts @cons@ in @payment@ and it returns with the last receipt.
    951 The 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.
    953 The program main restarts after the resume in @start@.
    954 @start@ returns and the program main terminates.
    955 
    956 
    957 \subsection{Coroutine Implementation}
    958 
    959 A 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.
    960 There are several solutions to this problem and the chosen option forced the \CFA coroutine design.
    961 
    962 Object-oriented inheritance provides extra fields and code in a restricted context, but it requires programmers to explicitly perform the inheritance:
    963 \begin{cfa}
    964 struct mycoroutine $\textbf{\textsf{inherits}}$ baseCoroutine { ... }
    965 \end{cfa}
    966 and the programming language (and possibly its tool set, \eg debugger) may need to understand @baseCoroutine@ because of the stack.
    967 Furthermore, 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 
    970 An alternatively is composition:
    971 \begin{cfa}
    972 struct mycoroutine {
    973         ... // declarations
     1207Figure~\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
     1227Terminating 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.
     1228Furthermore, 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.
     1229When a coroutine's main ends, its stack is already unwound so any stack allocated objects with destructors have been finalized.
     1230The na\"{i}ve semantics for coroutine-cycle termination is to context switch to the last resumer, like executing a @suspend@/@return@ in a generator.
     1231However, for coroutines, the last resumer is \emph{not} implicitly below the current stack frame, as for generators, because each coroutine's stack is independent.
     1232Unfortunately, it is impossible to determine statically if a coroutine is in a cycle and unrealistic to check dynamically (graph-cycle problem).
     1233Hence, a compromise solution is necessary that works for asymmetric (acyclic) and symmetric (cyclic) coroutines.
     1234
     1235Our solution is to context switch back to the first resumer (starter) once the coroutine ends.
     1236This semantics works well for the most common asymmetric and symmetric coroutine usage patterns.
     1237For asymmetric coroutines, it is common for the first resumer (starter) coroutine to be the only resumer.
     1238All previous generators converted to coroutines have this property.
     1239For symmetric coroutines, it is common for the cycle creator to persist for the lifetime of the cycle.
     1240Hence, the starter coroutine is remembered on the first resume and ending the coroutine resumes the starter.
     1241Figure~\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.
     1242For 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
     1244The producer/consumer example does not illustrate the full power of the starter semantics because @cons@ always ends first.
     1245Assume generator @PingPong@ is converted to a coroutine.
     1246Figure~\ref{f:PingPongFullCoroutineSteps} shows the creation, starter, and cyclic execution steps of the coroutine version.
     1247The program main creates (declares) coroutine instances @ping@ and @pong@.
     1248Next, program main resumes @ping@, making it @ping@'s starter, and @ping@'s main resumes @pong@'s main, making it @pong@'s starter.
     1249Execution forms a cycle when @pong@ resumes @ping@, and cycles $N$ times.
     1250By adjusting $N$ for either @ping@/@pong@, it is possible to have either one finish first, instead of @pong@ always ending first.
     1251If @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@.
     1252If @ping@ ends first, it resumes its starter the program main in function @start@.
     1253Regardless of the cycle complexity, the starter stack always leads back to the program main, but the stack can be entered at an arbitrary point.
     1254Once back at the program main, coroutines @ping@ and @pong@ are deallocated.
     1255For generators, deallocation runs the destructors for all objects in the generator type.
     1256For 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.
     1257Hence, 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.
     1258So 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.
     1259Explicitly 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
     1261Finally, there is an interesting effect for @suspend@ with symmetric coroutines.
     1262A coroutine must retain its last resumer to suspend back because the resumer is on a different stack.
     1263These reverse pointers allow @suspend@ to cycle \emph{backwards}, which may be useful in certain cases.
     1264However, 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.
     1265To prevent losing this information, a self-resume does not overwrite the last resumer.
     1266
     1267
     1268\subsection{Generator / Coroutine Implementation}
     1269
     1270A 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.
     1271There are several solutions to these problem, which follow from the object-oriented flavour of adopting custom types.
     1272
     1273For object-oriented languages, inheritance is used to provide extra fields and code via explicit inheritance:
     1274\begin{cfa}[morekeywords={class,inherits}]
     1275class 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.
     1278The 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.
     1279Alternatives, such as explicitly starting threads as in Java, are repetitive and forgetting to call start is a common source of errors.
     1280An alternative is composition:
     1281\begin{cfa}
     1282struct myCoroutine {
     1283        ... // declaration/communication variables
    9741284        baseCoroutine dummy; // composition, last declaration
    9751285}
    9761286\end{cfa}
    977 which also requires an explicit declaration that must be the last one to ensure correct initialization order.
     1287which also requires an explicit declaration that must be last to ensure correct initialization order.
    9781288However, there is nothing preventing wrong placement or multiple declarations.
    9791289
    980 For coroutines as for threads, many implementations are based on routine pointers or routine objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
    981 For example, Boost implements coroutines in terms of four functor object-types:
    982 \begin{cfa}
    983 asymmetric_coroutine<>::pull_type
    984 asymmetric_coroutine<>::push_type
    985 symmetric_coroutine<>::call_type
    986 symmetric_coroutine<>::yield_type
    987 \end{cfa}
    988 Similarly, the canonical threading paradigm is often based on routine pointers, \eg @pthread@~\cite{pthreads}, \Csharp~\cite{Csharp}, Go~\cite{Go}, and Scala~\cite{Scala}.
    989 However, the generic thread-handle (identifier) is limited (few operations), unless it is wrapped in a custom type.
    990 \begin{cfa}
    991 void mycor( coroutine_t cid, void * arg ) {
    992         int * value = (int *)arg;                               $\C{// type unsafe, pointer-size only}$
    993         // Coroutine body
    994 }
    995 int 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}
    1001 Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda-based coroutines adds very little.
    1002 
    1003 Note, the type @coroutine_t@ must be an abstract handle to the coroutine, because the coroutine descriptor and its stack are non-copyable.
    1004 Copying the coroutine descriptor results in copies being out of date with the current state of the stack.
    1005 Correspondingly, 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 
    1008 The selected approach is to use language support by introducing a new kind of aggregate (structure):
    1009 \begin{cfa}
    1010 coroutine Fibonacci {
    1011         int fn; // communication variables
    1012 };
    1013 \end{cfa}
    1014 The @coroutine@ keyword means the compiler (and tool set) can find and inject code where needed.
    1015 The downside of this approach is that it makes coroutine a special case in the language.
    1016 Users wanting to extend coroutines or build their own for various reasons can only do so in ways offered by the language.
    1017 Furthermore, implementing coroutines without language supports also displays the power of a programming language.
    1018 While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed without using the language support.
    1019 The reserved keyword eases use for the common cases.
    1020 
    1021 Part 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:
     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,
     1292and IDEs using simple parsing can find and manipulate types with special properties.
     1293The downside of this approach is that it makes custom types a special case in the language.
     1294Users wanting to extend custom types or build their own can only do so in ways offered by the language.
     1295Furthermore, 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
     1298Part 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.
    10221299\begin{cfa}
    10231300trait is_coroutine( `dtype` T ) {
     
    10251302        coroutine_desc * get_coroutine( T & );
    10261303};
    1027 forall( `dtype` T | is_coroutine(T) ) void suspend( T & );
    1028 forall( `dtype` T | is_coroutine(T) ) void resume( T & );
    1029 \end{cfa}
    1030 The @dtype@ property of the trait ensures the coroutine descriptor is non-copyable, so all coroutines must be passed by reference (pointer).
    1031 The 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.
    1032 The @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.
    1033 The 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.
    1034 The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory layout of a coroutine is trivial when implementing the @get_coroutine@ routine, and possibly redefining @suspend@ and @resume@.
    1035 The \CFA keyword @coroutine@ implicitly implements the getter and forward declarations required for implementing the coroutine main:
     1304forall( `dtype` T | is_coroutine(T) ) void $suspend$( T & ), resume( T & );
     1305\end{cfa}
     1306Note, copying generators/coroutines/threads is not meaningful.
     1307For example, both the resumer and suspender descriptors can have bidirectional pointers;
     1308copying these coroutines does not update the internal pointers so behaviour of both copies would be difficult to understand.
     1309Furthermore, two coroutines cannot logically execute on the same stack.
     1310A 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.
     1311The \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).
     1312The 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.
     1313The @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.
     1314The 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
     1316The \CFA custom-type @coroutine@ implicitly implements the getter and forward declarations for the coroutine main.
    10361317\begin{cquote}
    10371318\begin{tabular}{@{}ccc@{}}
     
    10691350\end{tabular}
    10701351\end{cquote}
    1071 The 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 
    1077 Both user and kernel threads are supported, where user threads provide concurrency and kernel threads provide parallelism.
    1078 Like 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:
     1352The 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
     1354Figure~\ref{f:CoroutineMemoryLayout} shows different memory-layout options for a coroutine (where a task is similar).
     1355The coroutine handle is the @coroutine@ instance containing programmer specified type global/communication variables across interface functions.
     1356The coroutine descriptor contains all implicit declarations needed by the runtime, \eg @suspend@/@resume@, and can be part of the coroutine handle or separate.
     1357The coroutine stack can appear in a number of locations and be fixed or variable sized.
     1358Hence, the coroutine's stack could be a VLS\footnote{
     1359We are examining variable-sized structures (VLS), where fields can be variable-sized structures or arrays.
     1360Once allocated, a VLS is fixed sized.}
     1361on the allocating stack, provided the allocating stack is large enough.
     1362For a VLS stack allocation/deallocation is an inexpensive adjustment of the stack pointer, modulo any stack constructor costs (\eg initial frame setup).
     1363For heap stack allocation, allocation/deallocation is an expensive heap allocation (where the heap can be a shared resource), modulo any stack constructor costs.
     1364With 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.
     1365Currently, \CFA supports stack/heap allocated descriptors but only fixed-sized heap allocated stacks.
     1366In \CFA debug-mode, the fixed-sized stack is terminated with a write-only page, which catches most stack overflows.
     1367Experience teaching concurrency with \uC~\cite{CS343} shows fixed-sized stacks are rarely an issue for students.
     1368Split-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
     1381Concurrency is nondeterministic scheduling of independent sequential execution paths (threads), where each thread has its own stack.
     1382A single thread with multiple call stacks, \newterm{coroutining}~\cite{Conway63,Marlin80}, does \emph{not} imply concurrency~\cite[\S~2]{Buhr05a}.
     1383In coroutining, coroutines self-schedule the thread across stacks so execution is deterministic.
     1384(It is \emph{impossible} to generate a concurrency error when coroutining.)
     1385However, coroutines are a stepping stone towards concurrency.
     1386
     1387The 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}.
     1388Therefore, a minimal concurrency system requires coroutines \emph{in conjunction with a nondeterministic scheduler}.
     1389The resulting execution system now follows a cooperative threading model~\cite{Adya02,libdill}, called \newterm{non-preemptive scheduling}.
     1390Adding \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}.
     1391While a scheduler introduces uncertain execution among explicit context switches, preemption introduces uncertainty by introducing implicit context switches.
     1392Uncertainty gives the illusion of parallelism on a single processor and provides a mechanism to access and increase performance on multiple processors.
     1393The reason is that the scheduler/runtime have complete knowledge about resources and how to best utilized them.
     1394However, the introduction of unrestricted nondeterminism results in the need for \newterm{mutual exclusion} and \newterm{synchronization}, which restrict nondeterminism for correctness;
     1395otherwise, it is impossible to write meaningful concurrent programs.
     1396Optimal concurrent performance is often obtained by having as much nondeterminism as mutual exclusion and synchronization correctness allow.
     1397
     1398A scheduler can either be a stackless or stackful.
     1399For 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.
     1400For 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.
     1401The \CFA runtime uses a stackful scheduler for uniformity and security.
     1402
     1403
     1404\subsection{Thread}
     1405\label{s:threads}
     1406
     1407Threading needs the ability to start a thread and wait for its completion.
     1408A common API for this ability is @fork@ and @join@.
     1409\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}
     1413class MyTask extends Thread {...}
     1414mytask t = new MyTask(...);
     1415`t.start();` // start
     1416// concurrency
     1417`t.join();` // wait
     1418\end{cfa}
     1419&
     1420\begin{cfa}
     1421class MyTask { ... } // functor
     1422MyTask mytask;
     1423`thread t( mytask, ... );` // start
     1424// concurrency
     1425`t.join();` // wait
     1426\end{cfa}
     1427&
     1428\begin{cfa}
     1429void * rtn( void * arg ) {...}
     1430pthread_t t;  int i = 3;
     1431`pthread_create( &t, rtn, (void *)i );` // start
     1432// concurrency
     1433`pthread_join( t, NULL );` // wait
     1434\end{cfa}
     1435\end{tabular}
     1436\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}
     1439thread MyTask {};
     1440void main( MyTask & this ) { ... }
     1441int 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}
     1446This semantic ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic (termination) synchronization.
     1447For block allocation to arbitrary depth, including recursion, threads are created/destroyed in a lattice structure (tree with top and bottom).
     1448Arbitrary topologies are possible using dynamic allocation, allowing threads to outlive their declaration scope, identical to normal dynamic allocation.
     1449\begin{cfa}
     1450MyTask * factory( int N ) { ... return `anew( N )`; } $\C{// allocate heap-based threads, implicit start after construction}$
     1451int 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
     1458Figure~\ref{s:ConcurrentMatrixSummation} shows concurrently adding the rows of a matrix and then totalling the subtotals sequentially, after all the row threads have terminated.
     1459The program uses heap-based threads because each thread needs different constructor values.
     1460(Python provides a simple iteration mechanism to initialize array elements to different values allowing stack allocation.)
     1461The allocation/deallocation pattern appears unusual because allocated objects are immediately deallocated without any intervening code.
     1462However, 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.
     1464
     1465\begin{figure}
     1466\begin{cfa}
     1467`thread` Adder { int * row, cols, & subtotal; } $\C{// communication variables}$
     1468void ?{}( Adder & adder, int row[], int cols, int & subtotal ) {
     1469        adder.[ row, cols, &subtotal ] = [ row, cols, &subtotal ];
     1470}
     1471void main( Adder & adder ) with( adder ) {
     1472        subtotal = 0;
     1473        for ( c; cols ) { subtotal += row[c]; }
     1474}
     1475int 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}
     1491\label{s:ConcurrentMatrixSummation}
     1492\end{figure}
     1493
     1494
     1495\subsection{Thread Implementation}
     1496
     1497Threads 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.
     1498Like coroutines, and for the same design reasons, \CFA provides a custom @thread@ type and a @trait@ to enforce and restrict the task-interface functions.
    10791499\begin{cquote}
    10801500\begin{tabular}{@{}c@{\hspace{3\parindentlnth}}c@{}}
    10811501\begin{cfa}
    10821502thread myThread {
    1083         // communication variables
     1503        ... // declaration/communication variables
    10841504};
    10851505
     
    10891509\begin{cfa}
    10901510trait is_thread( `dtype` T ) {
    1091       void main( T & );
    1092       thread_desc * get_thread( T & );
    1093       void ^?{}( T & `mutex` );
     1511        void main( T & );
     1512        thread_desc * get_thread( T & );
     1513        void ^?{}( T & `mutex` );
    10941514};
    10951515\end{cfa}
    10961516\end{tabular}
    10971517\end{cquote}
    1098 (The qualifier @mutex@ for the destructor parameter is discussed in Section~\ref{s:Monitors}.)
    1099 Like a coroutine, the statically-typed @main@ routine is the starting point (first stack frame) of a user thread.
    1100 The difference is that a coroutine borrows a thread from its caller, so the first thread resuming a coroutine creates an instance of @main@;
    1101 whereas, 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{
    1102 The \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).}
    1103 No 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 ???
    1106 As such the @main@ routine of a thread can be defined as
    1107 \begin{cfa}
    1108 thread foo {};
    1109 
    1110 void main(foo & this) {
    1111         sout | "Hello World!" | endl;
    1112 }
    1113 \end{cfa}
    1114 
    1115 In 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.
    1116 With 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}
    1118 typedef void (*voidRtn)(int);
    1119 
    1120 thread RtnRunner {
    1121         voidRtn func;
    1122         int arg;
    1123 };
    1124 
    1125 void ?{}(RtnRunner & this, voidRtn inRtn, int arg) {
    1126         this.func = inRtn;
    1127         this.arg  = arg;
    1128 }
    1129 
    1130 void main(RtnRunner & this) {
    1131         // thread starts here and runs the routine
    1132         this.func( this.arg );
    1133 }
    1134 
    1135 void hello(/*unused*/ int) {
    1136         sout | "Hello World!" | endl;
    1137 }
    1138 
    1139 int main() {
    1140         RtnRunner f = {hello, 42};
    1141         return 0?
    1142 }
    1143 \end{cfa}
    1144 A 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 
    1147 For user threads to be useful, it must be possible to start and stop the underlying thread, and wait for it to complete execution.
    1148 While using an API such as @fork@ and @join@ is relatively common, such an interface is awkward and unnecessary.
    1149 A simple approach is to use allocation/deallocation principles, and have threads implicitly @fork@ after construction and @join@ before destruction.
    1150 \begin{cfa}
    1151 thread World {};
    1152 void main( World & this ) {
    1153         sout | "World!" | endl;
    1154 }
    1155 int main() {
    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}
    1160 This semantics ensures a thread is started and stopped exactly once, eliminating some programming error, and scales to multiple threads for basic (termination) synchronization.
    1161 This 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}
    1163 int 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}
    1174 The heap-based approach allows arbitrary thread-creation topologies, with respect to fork/join-style concurrency.
    1175 
    1176 Figure~\ref{s:ConcurrentMatrixSummation} shows concurrently adding the rows of a matrix and then totalling the subtotals sequential, after all the row threads have terminated.
    1177 The program uses heap-based threads because each thread needs different constructor values.
    1178 (Python provides a simple iteration mechanism to initialize array elements to different values allowing stack allocation.)
    1179 The allocation/deallocation pattern appears unusual because allocated objects are immediately deleted without any intervening code.
    1180 However, for threads, the deletion provides implicit synchronization, which is the intervening code.
    1181 While 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.
    1182 
    1183 \begin{figure}
    1184 \begin{cfa}
    1185 thread Adder {
    1186     int * row, cols, & subtotal;                        $\C{// communication}$
    1187 };
    1188 void ?{}( Adder & adder, int row[], int cols, int & subtotal ) {
    1189     adder.[ row, cols, &subtotal ] = [ row, cols, &subtotal ];
    1190 }
    1191 void main( Adder & adder ) with( adder ) {
    1192     subtotal = 0;
    1193     for ( int c = 0; c < cols; c += 1 ) {
    1194                 subtotal += row[c];
    1195     }
    1196 }
    1197 int main() {
    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}
    1213 \label{s:ConcurrentMatrixSummation}
    1214 \end{figure}
     1518Like 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).
     1519Similarly, 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}.)
     1521The 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;
     1522whereas, a thread is scheduling for execution in @main@ immediately after its constructor is run.
     1523No 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.
    12151524
    12161525
    12171526\section{Mutual Exclusion / Synchronization}
    1218 
    1219 Uncontrolled non-deterministic execution is meaningless.
    1220 To 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}.
    1221 Since 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).
    1222 In 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}).
    1223 However, 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).
    1224 Hence, a programmer must learn and manipulate two sets of design patterns.
     1527\label{s:MutualExclusionSynchronization}
     1528
     1529Unrestricted nondeterminism is meaningless as there is no way to know when the result is completed without synchronization.
     1530To 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}.
     1531Some 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).
     1532However, these approaches introduce a new communication mechanism for concurrency different from the standard communication using function call/return.
     1533Hence, a programmer must learn and manipulate two sets of design/programming patterns.
    12251534While this distinction can be hidden away in library code, effective use of the library still has to take both paradigms into account.
    1226 In contrast, approaches based on statefull models more closely resemble the standard call/return programming-model, resulting in a single programming paradigm.
    1227 
    1228 At 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}.
     1535In contrast, approaches based on stateful models more closely resemble the standard call/return programming model, resulting in a single programming paradigm.
     1536
     1537At 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}.
    12291538However, for productivity it is always desirable to use the highest-level construct that provides the necessary efficiency~\cite{Hochstein05}.
    12301539A newer approach for restricting non-determinism is transactional memory~\cite{Herlihy93}.
    1231 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 was rejected as the core paradigm for concurrency in \CFA.
     1540While 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.
    12321541
    12331542One of the most natural, elegant, and efficient mechanisms for mutual exclusion and synchronization for shared-memory systems is the \emph{monitor}.
    1234 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}.
     1543First 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}.
    12351544In 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.
    1236 For these reasons, \CFA selected monitors as the core high-level concurrency-construct, upon which higher-level approaches can be easily constructed.
     1545For these reasons, \CFA selected monitors as the core high-level concurrency construct, upon which higher-level approaches can be easily constructed.
    12371546
    12381547
    12391548\subsection{Mutual Exclusion}
    12401549
    1241 A group of instructions manipulating a specific instance of shared data that must be performed atomically is called an (individual) \newterm{critical-section}~\cite{Dijkstra65}.
    1242 The 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.
    1243 The 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.
     1550A 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}.
     1551The 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.
     1552The readers/writer problem~\cite{Courtois71} is an instance of a group critical-section, where readers share a session but writers have a unique session.
    12451553
    12461554However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use.
    12471555Methods 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.
    1248 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.
    1249 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.
     1556Ease 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.
     1557For 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.
    12501558However, a significant challenge with locks is composability because it takes careful organization for multiple locks to be used while preventing deadlock.
    12511559Easing composability is another feature higher-level mutual-exclusion mechanisms can offer.
     
    12561564Synchronization enforces relative ordering of execution, and synchronization tools provide numerous mechanisms to establish these timing relationships.
    12571565Low-level synchronization primitives offer good performance and flexibility at the cost of ease of use;
    1258 higher-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.
    1259 Often 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.
    1260 If a writer thread is scheduled for next access, but another reader thread acquires the critical section first, that reader has \newterm{barged}.
     1566higher-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.
     1567Often 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.
     1568If the calling reader is scheduled before the waiting writer, the reader has barged.
    12611569Barging 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).
    1262 Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs.
    1263 This challenge is often split into two different approaches: barging avoidance and barging prevention.
    1264 Algorithms that allow a barger, but divert it until later using current synchronization state (flags), are avoiding the barger;
    1265 algorithms that preclude a barger from entering during synchronization in the critical section prevent barging completely.
    1266 Techniques 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 
    1272 A \textbf{monitor} is a set of routines that ensure mutual exclusion when accessing shared state.
    1273 More 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).
    1274 The strong association with the call/return paradigm eases programmability, readability and maintainability, at a slight cost in flexibility and efficiency.
    1275 
    1276 Note, 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.
    1277 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.
    1278 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.
    1279 As for coroutines/tasks, a non-copyable (@dtype@) trait is used to capture this requirement, so all locks/monitors must be passed by reference (pointer).
     1570Preventing or detecting barging is an involved challenge with low-level locks, which is made easier through higher-level constructs.
     1571This challenge is often split into two different approaches: barging avoidance and prevention.
     1572Algorithms that unconditionally releasing a lock for competing threads to acquire use barging avoidance during synchronization to force a barging thread to wait;
     1573algorithms that conditionally hold locks during synchronization, \eg baton-passing~\cite{Andrews89}, prevent barging completely.
     1574
     1575
     1576\section{Monitor}
     1577\label{s:Monitor}
     1578
     1579A \textbf{monitor} is a set of functions that ensure mutual exclusion when accessing shared state.
     1580More 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).
     1581Restricting 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
     1584The 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}$
     1587int ++?( Aint & `mutex`$\(_{opt}\)$ this ) with( this ) { return ++cnt; } $\C{// increment}$
     1588int ?=?( Aint & `mutex`$\(_{opt}\)$ lhs, int rhs ) with( lhs ) { cnt = rhs; } $\C{// conversions with int}\CRT$
     1589int ?=?( 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.)
     1593The 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.
     1594The assignment operators provide bidirectional conversion between an atomic and normal integer without accessing field @cnt@;
     1595these operations only need @mutex@, if reading/writing the implementation type is not atomic.
     1596The 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}
     1598int i = 0, j = 0, k = 5;
     1599Aint x = { 0 }, y = { 0 }, z = { 5 }; $\C{// no mutex required}$
     1600++x; ++y; ++z; $\C{// safe increment by multiple threads}$
     1601x = 2; y = i; z = k; $\C{// conversions}$
     1602i = 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}
     1607monitor M { ... } m;
     1608void foo( M & mutex m ) { ... } $\C{// acquire mutual exclusion}$
     1609void 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.
     1614Similar safety is offered by \emph{explicit} mechanisms like \CC RAII;
     1615monitor \emph{implicit} safety ensures no programmer usage errors.
     1616Furthermore, 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;
     1617RAII is purely a mutual-exclusion mechanism (see Section~\ref{s:Scheduling}).
     1618
     1619
     1620\subsection{Monitor Implementation}
     1621
     1622For 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}
     1626monitor M {
     1627        ... // shared data
     1628};
     1629
     1630\end{cfa}
     1631&
    12801632\begin{cfa}
    12811633trait is_monitor( `dtype` T ) {
     
    12841636};
    12851637\end{cfa}
     1638\end{tabular}
     1639\end{cquote}
     1640The @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.
     1643Similarly, 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.
     1644The custom monitor type also inserts any locks needed to implement the mutual exclusion semantics.
    12861645
    12871646
     
    12891648\label{s:MutexAcquisition}
    12901649
    1291 While correctness implicitly implies a monitor's mutual exclusion is acquired and released, there are implementation options about when and where the locking/unlocking occurs.
     1650While the monitor lock provides mutual exclusion for shared data, there are implementation options for when and where the locking/unlocking occurs.
    12921651(Much of this discussion also applies to basic locks.)
    1293 For 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]
    1295 monitor Aint { int cnt; };                                      $\C{// atomic integer counter}$
    1296 void ?{}( Aint & `nomutex` this ) with( this ) { cnt = 0; } $\C{// constructor}$
    1297 int ?=?( Aint & `mutex`$\(_{opt}\)$ lhs, int rhs ) with( lhs ) { cnt = rhs; } $\C{// conversions}$
    1298 void ?{}( int & this, Aint & `mutex`$\(_{opt}\)$ v ) { this = v.cnt; }
    1299 int ?=?( int & lhs, Aint & `mutex`$\(_{opt}\)$ rhs ) with( rhs ) { lhs = cnt; }
    1300 int ++?( Aint & `mutex`$\(_{opt}\)$ this ) with( this ) { return ++cnt; } $\C{// increment}$
    1301 \end{cfa}
    1302 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.
    1303 (While a constructor may publish its address into a global variable, doing so generates a race-condition.)
    1304 The conversion operators for initializing and assigning with a normal integer only need @mutex@, if reading/writing the implementation type is not atomic.
    1305 Finally, 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 
    1307 The 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}
    1309 Aint x, y, z;
    1310 ++x; ++y; ++z;                                                          $\C{// safe increment by multiple threads}$
    1311 x = 2; y = 2; z = 2;                                            $\C{// conversions}$
    1312 int i = x, j = y, k = z;
    1313 i = x; j = y; k = z;
    1314 \end{cfa}
    1315 
    1316 For maximum usability, monitors have \newterm{multi-acquire} semantics allowing a thread to acquire it multiple times without deadlock.
    1317 For example, atomically printing the contents of a binary tree:
    1318 \begin{cfa}
    1319 monitor Tree {
    1320         Tree * left, right;
    1321         // value
    1322 };
    1323 void 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 
    1330 Mandatory monitor qualifiers have the benefit of being self-documented, but requiring both @mutex@ and \lstinline[morekeywords=nomutex]@nomutex@ for all monitor parameter is redundant.
    1331 Instead, one of qualifier semantics can be the default, and the other required.
    1332 For example, assume the safe @mutex@ option for a monitor parameter because assuming \lstinline[morekeywords=nomutex]@nomutex@ may cause subtle errors.
    1333 On the other hand, assuming \lstinline[morekeywords=nomutex]@nomutex@ is the \emph{normal} parameter behaviour, stating explicitly ``this parameter is not special''.
     1652For example, a monitor may be passed through multiple helper functions before it is necessary to acquire the monitor's mutual exclusion.
     1653
     1654The benefit of mandatory monitor qualifiers is self-documentation, but requiring both @mutex@ and \lstinline[morekeywords=nomutex]@nomutex@ for all monitor parameters is redundant.
     1655Instead, the semantics has one qualifier as the default and the other required.
     1656For example, make the safe @mutex@ qualifier the default because assuming \lstinline[morekeywords=nomutex]@nomutex@ may cause subtle errors.
     1657Alternatively, make the unsafe \lstinline[morekeywords=nomutex]@nomutex@ qualifier the default because it is the \emph{normal} parameter semantics while @mutex@ parameters are rare.
    13341658Providing a default qualifier implies knowing whether a parameter is a monitor.
    1335 Since \CFA relies heavily on traits as an abstraction mechanism, the distinction between a type that is a monitor and a type that looks like a monitor can become blurred.
     1659Since \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.
    13361660For 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@.
    13371661
    13381662The next semantic decision is establishing which parameter \emph{types} may be qualified with @mutex@.
    1339 Given:
     1663The following has monitor parameter types that are composed of multiple objects.
    13401664\begin{cfa}
    13411665monitor M { ... }
    1342 int f1( M & mutex m );
    1343 int f2( M * mutex m );
    1344 int f3( M * mutex m[] );
    1345 int f4( stack( M * ) & mutex m );
    1346 \end{cfa}
    1347 the issue is that some of these parameter types are composed of multiple objects.
    1348 For @f1@, there is only a single parameter object.
    1349 Adding indirection in @f2@ still identifies a single object.
    1350 However, the matrix in @f3@ introduces multiple objects.
    1351 While shown shortly, multiple acquisition is possible;
    1352 however array lengths are often unknown in C.
    1353 This issue is exacerbated in @f4@, where the data structure must be safely traversed to acquire all of its elements.
    1354 
    1355 To make the issue tractable, \CFA only acquires one monitor per parameter with at most one level of indirection.
    1356 However, the C type-system has an ambiguity with respects to arrays.
    1357 Is the argument for @f2@ a single object or an array of objects?
    1358 If it is an array, only the first element of the array is acquired, which seems unsafe;
    1359 hence, @mutex@ is disallowed for array parameters.
    1360 \begin{cfa}
    1361 int f1( M & mutex m );                                          $\C{// allowed: recommended case}$
    1362 int f2( M * mutex m );                                          $\C{// disallowed: could be an array}$
    1363 int f3( M mutex m[$\,$] );                                      $\C{// disallowed: array length unknown}$
    1364 int f4( M ** mutex m );                                         $\C{// disallowed: could be an array}$
    1365 int 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 
    1370 For 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.
    1372 A positive consequence of this design decision is the ability to support multi-monitor routines.
    1373 \begin{cfa}
    1374 int f( M & mutex x, M & mutex y );              $\C{// multiple monitor parameter of any type}$
    1375 M m1, m2;
    1376 f( 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.)
    1379 In practice, writing multi-locking routines that do not deadlocks is tricky.
    1380 Having language support for such a feature is therefore a significant asset for \CFA.
    1381 
    1382 The capability to acquire multiple locks before entering a critical section is called \newterm{bulk acquire}.
    1383 In previous example, \CFA guarantees the order of acquisition is consistent across calls to different routines using the same monitors as arguments.
    1384 This consistent ordering means acquiring multiple monitors is safe from deadlock.
    1385 However, users can force the acquiring order.
    1386 For example, notice the use of @mutex@/\lstinline[morekeywords=nomutex]@nomutex@ and how this affects the acquiring order:
    1387 \begin{cfa}
    1388 void foo( M & mutex m1, M & mutex m2 );         $\C{// acquire m1 and m2}$
     1666int f1( M & mutex m ); $\C{// single parameter object}$
     1667int f2( M * mutex m ); $\C{// single or multiple parameter object}$
     1668int f3( M * mutex m[$\,$] ); $\C{// multiple parameter object}$
     1669int f4( stack( M * ) & mutex m ); $\C{// multiple parameters object}$
     1670\end{cfa}
     1671Function @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.
     1672Function @f3@ has a multiple object matrix, and @f4@ a multiple object data structure.
     1673While shown shortly, multiple object acquisition is possible, but the number of objects must be statically known.
     1674Therefore, \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
     1676For 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.
     1678A positive consequence of this design decision is the ability to support multi-monitor functions,\footnote{
     1679While object-oriented monitors can be extended with a mutex qualifier for multiple-monitor members, no prior example of this feature could be found.}
     1680called \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.
     1682Figure~\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.
     1683A \CFA programmer only has to manage when to acquire mutual exclusion;
     1684a \CC programmer must select the correct lock and acquisition mechanism from a panoply of locking options.
     1685Making 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]
     1691monitor BankAccount {
     1692
     1693        int balance;
     1694} b1 = { 0 }, b2 = { 0 };
     1695void deposit( BankAccount & `mutex` b,
     1696                        int deposit ) with(b) {
     1697        balance += deposit;
     1698}
     1699void 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; };
     1706void 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}
     1712int 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]
     1721struct BankAccount {
     1722        `recursive_mutex m;`
     1723        int balance = 0;
     1724} b1, b2;
     1725void deposit( BankAccount & b, int deposit ) {
     1726        `scoped_lock lock( b.m );`
     1727        b.balance += deposit;
     1728}
     1729void 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
     1736void 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}
     1742int 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
     1759Users can still force the acquiring order by using @mutex@/\lstinline[morekeywords=nomutex]@nomutex@.
     1760\begin{cfa}
     1761void foo( M & mutex m1, M & mutex m2 ); $\C{// acquire m1 and m2}$
    13891762void bar( M & mutex m1, M & /* nomutex */ m2 ) { $\C{// acquire m1}$
    1390         ... foo( m1, m2 ); ...                                  $\C{// acquire m2}$
     1763        ... foo( m1, m2 ); ... $\C{// acquire m2}$
    13911764}
    13921765void baz( M & /* nomutex */ m1, M & mutex m2 ) { $\C{// acquire m2}$
    1393         ... foo( m1, m2 ); ...                                  $\C{// acquire m1}$
    1394 }
    1395 \end{cfa}
    1396 The multi-acquire semantics allows @bar@ or @baz@ to acquire a monitor lock and reacquire it in @foo@.
    1397 In the calls to @bar@ and @baz@, the monitors are acquired in opposite order.
    1398 
    1399 However, 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}.
    1400 In \CFA, safety is guaranteed by using bulk acquire of all monitors to shared objects, whereas other monitor systems provide no aid.
    1401 While \CFA provides only a partial solution, the \CFA partial solution handles many useful cases.
    1402 \begin{cfa}
    1403 monitor Bank { ... };
    1404 void deposit( Bank & `mutex` b, int deposit );
    1405 void 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}
    1410 This example shows a trivial solution to the bank-account transfer problem~\cite{BankTransfer}.
    1411 Without multi- and bulk acquire, the solution to this problem requires careful engineering.
    1412 
    1413 
    1414 \subsection{\protect\lstinline|mutex| statement} \label{mutex-stmt}
    1415 
    1416 The monitor call-semantics associate all locking semantics to routines.
    1417 Like Java, \CFA offers an alternative @mutex@ statement to reduce refactoring and naming.
     1766        ... foo( m1, m2 ); ... $\C{// acquire m1}$
     1767}
     1768\end{cfa}
     1769The bulk-acquire semantics allow @bar@ or @baz@ to acquire a monitor lock and reacquire it in @foo@.
     1770The calls to @bar@ and @baz@ acquired the monitors in opposite order, possibly resulting in deadlock.
     1771However, this case is the simplest instance of the \emph{nested-monitor problem}~\cite{Lister77}, where monitors are acquired in sequence versus bulk.
     1772Detecting 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
     1775Finally, like Java, \CFA offers an alternative @mutex@ statement to reduce refactoring and naming.
    14181776\begin{cquote}
    1419 \begin{tabular}{@{}c|@{\hspace{\parindentlnth}}c@{}}
    1420 routine call & @mutex@ statement \\
    1421 \begin{cfa}
    1422 monitor M {};
     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]
     1781monitor M { ... };
    14231782void foo( M & mutex m1, M & mutex m2 ) {
    14241783        // critical section
     
    14291788\end{cfa}
    14301789&
    1431 \begin{cfa}
     1790\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    14321791
    14331792void bar( M & m1, M & m2 ) {
     
    14421801
    14431802
    1444 \section{Internal Scheduling}
    1445 \label{s:InternalScheduling}
    1446 
    1447 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, Figure~\ref{f:GenericBoundedBuffer}, may be full/empty so produce/consumer threads must block.
     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.
     1808This 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.)
     1809While 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.
    14481810Leaving the monitor and trying again (busy waiting) is impractical for high-level programming.
    1449 Monitors 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.
    1450 The 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.
     1811Monitors eliminate busy waiting by providing synchronization to schedule threads needing access to the shared data, where threads block versus spinning.
     1812Synchronization is generally achieved with internal~\cite{Hoare74} or external~\cite[\S~2.9.2]{uC++} scheduling.
    14511813\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.
    1452 
    1453 Figure~\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@.
    1454 The @wait@ routine atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the routine's parameter list.
    1455 The appropriate condition lock is signalled to unblock an opposite kind of thread after an element is inserted/removed from the buffer.
    1456 Signalling is unconditional, because signalling an empty condition lock does nothing.
    1457 Signalling semantics cannot have the signaller and signalled thread in the monitor simultaneously, which means:
    1458 \begin{enumerate}
    1459 \item
    1460 The signalling thread returns immediately, and the signalled thread continues.
    1461 \item
    1462 The signalling thread continues and the signalled thread is marked for urgent unblocking at the next scheduling point (exit/wait).
    1463 \item
    1464 The signalling thread blocks but is marked for urgrent unblocking at the next scheduling point and the signalled thread continues.
    1465 \end{enumerate}
    1466 The 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.
    1468 Finally, while it is common to store a @condition@ as a field of the monitor, in \CFA, a @condition@ variable can be created/stored independently.
    1469 Furthermore, 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.
     1814Finally, \CFA monitors do not allow calling threads to barge ahead of signalled threads, which simplifies synchronization among threads in the monitor and increases correctness.
     1815If barging is allowed, synchronization between a signaller and signallee is difficult, often requiring additional flags and multiple unblock/block cycles.
     1816In 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}
     1821Furthermore, \CFA concurrency has no spurious wakeup~\cite[\S~9]{Buhr05a}, which eliminates an implicit form of self barging.
     1822Hence, a \CFA @wait@ statement is not enclosed in a @while@ loop retesting a blocking predicate, which can cause thread starvation due to barging.
     1823
     1824Figure~\ref{f:MonitorScheduling} shows general internal/external scheduling (for the bounded-buffer example in Figure~\ref{f:InternalExternalScheduling}).
     1825External calling threads block on the calling queue, if the monitor is occupied, otherwise they enter in FIFO order.
     1826Internal threads block on condition queues via @wait@ and reenter from the condition in FIFO order.
     1827Alternatively, 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
     1829There are three signalling mechanisms to unblock waiting threads to enter the monitor.
     1830Note, 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.
     1831For internal scheduling, threads are unblocked from condition queues using @signal@, where the signallee is moved to urgent and the signaller continues (solid line).
     1832Multiple signals move multiple signallees to urgent until the condition is empty.
     1833When 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.)
     1835The 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
     1837For external scheduling, the condition queues are not used;
     1838instead 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)$.)
     1840The @waitfor@ has the same semantics as @signal_block@, where the signalled thread executes before the signallee, which waits on urgent.
     1841Executing multiple @waitfor@s from different signalled functions causes the calling threads to move to urgent.
     1842External scheduling requires urgent to be a stack, because the signaller expects to execute immediately after the specified monitor call has exited or waited.
     1843Internal 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.
     1844If 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.
     1845We tried both a stack for @waitfor@ and queue for signalling, but that resulted in complex semantics about which thread enters next.
     1846Hence, \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
     1864Figure~\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@.
     1865The @wait@ function atomically blocks the calling thread and implicitly releases the monitor lock(s) for all monitors in the function's parameter list.
     1866The appropriate condition variable is signalled to unblock an opposite kind of thread after an element is inserted/removed from the buffer.
     1867Signalling is unconditional, because signalling an empty condition variable does nothing.
     1868It 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.
     1869In \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.
    14701883
    14711884\begin{figure}
     
    14811894        };
    14821895        void ?{}( Buffer(T) & buffer ) with(buffer) {
    1483                 [front, back, count] = 0;
     1896                front = back = count = 0;
    14841897        }
    1485 
    14861898        void insert( Buffer(T) & mutex buffer, T elem )
    14871899                                with(buffer) {
     
    15001912\end{lrbox}
    15011913
     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
    15021943\newbox\myboxB
    15031944\begin{lrbox}{\myboxB}
    15041945\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    1505 forall( 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 }
     1946monitor ReadersWriter {
     1947        int rcnt, wcnt; // readers/writer using resource
     1948};
     1949void ?{}( ReadersWriter & rw ) with(rw) {
     1950        rcnt = wcnt = 0;
     1951}
     1952void EndRead( ReadersWriter & mutex rw ) with(rw) {
     1953        rcnt -= 1;
     1954}
     1955void EndWrite( ReadersWriter & mutex rw ) with(rw) {
     1956        wcnt = 0;
     1957}
     1958void StartRead( ReadersWriter & mutex rw ) with(rw) {
     1959        if ( wcnt > 0 ) `waitfor( EndWrite, rw );`
     1960        rcnt += 1;
     1961}
     1962void 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
    15281968\end{cfa}
    15291969\end{lrbox}
    15301970
    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}
     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}
    15361979\end{figure}
    15371980
    1538 Figure~\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.
    1539 External 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.
     1981Figure~\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]
     1983if ( count == 10 ) `waitfor( remove, buffer )`;       |      if ( count == 0 ) `waitfor( insert, buffer )`;
     1984\end{cfa}
     1985Here, 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.
     1986External 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.
    15401987If 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.
    1541 Threads 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 
    1543 Both internal and external scheduling extend to multiple monitors in a natural way.
    1544 \begin{cfa}
    1545 monitor M { `condition e`; ... };
    1546 void 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 
    1552 void rtn$\(_1\)$( M & mutex m1, M & mutex m2 );
    1553 void rtn$\(_2\)$( M & mutex m1 );
    1554 void 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}
    1559 For @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 )@.
    1560 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@.
    1561 Wait statically verifies the released monitors are the acquired mutex-parameters so unconditional release is safe.
    1562 Similarly, 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 )@.
    1563 To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @waitfor( rtn, m1 )@.
    1564 Waitfor statically verifies the released monitors are the same as the acquired mutex-parameters of the given routine or routine pointer.
    1565 To statically verify the released monitors match with the accepted routine's mutex parameters, the routine (pointer) prototype must be accessible.
    1566 
    1567 Given the ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock.
    1568 \begin{cfa}
    1569 void foo( M & mutex m1, M & mutex m2 ) {
    1570         ... wait( `e, m1` ); ...                                $\C{// release m1, keeping m2 acquired )}$
    1571 void baz( M & mutex m1, M & mutex m2 ) {        $\C{// must acquire m1 and m2 )}$
    1572         ... signal( `e` ); ...
    1573 \end{cfa}
    1574 The @wait@ only releases @m1@ so the signalling thread cannot acquire both @m1@ and @m2@ to  enter @baz@ to get to the @signal@.
    1575 While 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 
    1577 Finally, an important aspect of monitor implementation is barging, \ie can calling threads barge ahead of signalled threads?
    1578 If 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}
    1580 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.
    1581 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}
    1582 \end{quote}
    1583 \CFA scheduling \emph{precludes} barging, which simplifies synchronization among threads in the monitor and increases correctness.
    1584 For example, there are no loops in either bounded buffer solution in Figure~\ref{f:GenericBoundedBuffer}.
    1585 Supporting 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 
    1590 Figure~\ref{f:BargingPrevention} shows \CFA code where bulk acquire adds complexity to the internal-signalling semantics.
    1591 The complexity begins at the end of the inner @mutex@ statement, where the semantics of internal scheduling need to be extended for multiple monitors.
    1592 The problem is that bulk acquire is used in the inner @mutex@ statement where one of the monitors is already acquired.
    1593 When 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.
    1594 However, 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]
    1600 monitor M m1, m2;
    1601 condition c;
    1602 mutex( 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 
    1618 mutex( 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 
    1634 mutex( 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 
    1656 The 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.
    1657 It 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.
    1658 This 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.
    1659 This solution releases the monitors once every monitor in a group can be released.
    1660 However, since some monitors are never released (\eg the monitor of a thread), this interpretation means a group might never be released.
    1661 A 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 
    1663 However, 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.
    1664 Figure~\ref{f:dependency} shows a slightly different example where a third thread is waiting on monitor @A@, using a different condition variable.
    1665 Because the third thread is signalled when secretly holding @B@, the goal  becomes unreachable.
    1666 Depending 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 
    1673 Note that ordering is not determined by a race condition but by whether signalled threads are enqueued in FIFO or FILO order.
    1674 However, 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 
    1676 In both cases, the threads need to be able to distinguish, on a per monitor basis, which ones need to be released and which ones need to be transferred, which means 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}
    1683 Thread $\alpha$
    1684 \begin{cfa}[numbers=left, firstnumber=1]
    1685 acquire A
    1686         acquire A & B
    1687                 wait A & B
    1688         release A & B
    1689 release A
    1690 \end{cfa}
    1691 \columnbreak
    1692 Thread $\gamma$
    1693 \begin{cfa}[numbers=left, firstnumber=6, escapechar=|]
    1694 acquire 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
    1702 Thread $\beta$
    1703 \begin{cfa}[numbers=left, firstnumber=12, escapechar=|]
    1704 acquire 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 
    1718 In listing \ref{f:int-bulk-cfa}, there is a solution that satisfies both barging prevention and mutual exclusion.
    1719 If 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).
    1720 Dynamically finding the correct order is therefore the second possible solution.
    1721 The problem is effectively resolving a dependency graph of ownership requirements.
    1722 Here even the simplest of code snippets requires two transfers and has a super-linear complexity.
    1723 This 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.
    1724 Furthermore, 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}
    1728 acquire A
    1729         acquire B
    1730                 acquire C
    1731                         wait A & B & C
    1732                 release C
    1733         release B
    1734 release A
    1735 \end{cfa}
    1736 
    1737 \columnbreak
    1738 
    1739 \begin{cfa}
    1740 acquire A
    1741         acquire B
    1742                 acquire C
    1743                         signal A & B & C
    1744                 release C
    1745         release B
    1746 release 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 
    1753 Given 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$).
    1754 The 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.
    1755 Resolving 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 
    1760 Finally, the solution that is chosen for \CFA is to use partial signalling.
    1761 Again 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@.
    1762 Only when it reaches line \ref{line:lastRelease} does it actually wake up the waiting thread.
    1763 This 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.
    1764 This solution has a much simpler implementation than a dependency graph solving algorithms, which is why it was chosen.
    1765 Furthermore, after being fully implemented, this solution does not appear to have any significant downsides.
    1766 
    1767 Using 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}
     1988Threads 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.
     1989Figure~\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@.
     1990The writer does a similar action for each reader or writer using the resource.
     1991Note, no new calls to @StarRead@/@StartWrite@ may occur when waiting for the call to @EndRead@/@EndWrite@.
     1992External scheduling allows waiting for events from other threads while restricting unrelated events, that would otherwise have to wait on conditions in the monitor.
     1993The 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.
     1994While 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
     1997Figure~\ref{f:DatingService} shows a dating service demonstrating non-blocking and blocking signalling.
     1998The dating service matches girl and boy threads with matching compatibility codes so they can exchange phone numbers.
     1999A thread blocks until an appropriate partner arrives.
     2000The complexity is exchanging phone numbers in the monitor because of the mutual-exclusion property.
     2001For 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.
     2002For 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.
     2003The 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;
     2004as well, an arriving thread may not find a partner and must wait, which requires a condition variable, and condition variables imply internal scheduling.
     2005Furthermore, 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.
     2006Putting loops around the @wait@s does not correct the problem;
     2007the simple solution must be restructured to account for barging.
    17762008
    17772009\begin{figure}
     
    17842016        int GirlPhNo, BoyPhNo;
    17852017        condition Girls[CCodes], Boys[CCodes];
    1786         condition exchange;
     2018        `condition exchange;`
    17872019};
    17882020int girl( DS & mutex ds, int phNo, int ccode ) {
     
    17902022                wait( Girls[ccode] );
    17912023                GirlPhNo = phNo;
    1792                 exchange.signal();
     2024                `signal( exchange );`
    17932025        } else {
    17942026                GirlPhNo = phNo;
    1795                 signal( Boys[ccode] );
    1796                 exchange.wait();
    1797         } // if
     2027                `signal( Boys[ccode] );`
     2028                `wait( exchange );`
     2029        }
    17982030        return BoyPhNo;
    17992031}
     
    18202052        } else {
    18212053                GirlPhNo = phNo; // make phone number available
    1822                 signal_block( Boys[ccode] ); // restart boy
     2054                `signal_block( Boys[ccode] );` // restart boy
    18232055
    18242056        } // if
     
    18342066\qquad
    18352067\subfloat[\lstinline@signal_block@]{\label{f:DatingSignalBlock}\usebox\myboxB}
    1836 \caption{Dating service. }
    1837 \label{f:Dating service}
     2068\caption{Dating service}
     2069\label{f:DatingService}
    18382070\end{figure}
    18392071
    1840 An important note is that, until now, signalling a monitor was a delayed operation.
    1841 The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the @signal@ statement.
    1842 However, in some cases, it may be more convenient for users to immediately transfer ownership to the thread that is waiting for cooperation, which is achieved using the @signal_block@ routine.
    1843 
    1844 The example in table \ref{tbl:datingservice} highlights the difference in behaviour.
    1845 As mentioned, @signal@ only transfers ownership once the current critical section exits; this behaviour requires additional synchronization when a two-way handshake is needed.
    1846 To avoid this explicit synchronization, the @condition@ type offers the @signal_block@ routine, which handles the two-way handshake as shown in the example.
    1847 This feature removes the need for a second condition variables and simplifies programming.
    1848 Like 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 % ======================================================================
    1855 An 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|}
    1860 Internal Scheduling & External Scheduling & Go\\
    1861 \hline
    1862 \begin{uC++}[tabsize=3]
    1863 _Monitor Semaphore {
    1864         condition c;
    1865         bool inUse;
    1866 public:
    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;
    1881 public:
    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]
    1893 type MySem struct {
    1894         inUse bool
    1895         c     chan bool
    1896 }
    1897 
    1898 // acquire
    1899 func (s MySem) P() {
    1900         if s.inUse {
    1901                 select {
    1902                 case <-s.c:
    1903                 }
    1904         }
    1905         s.inUse = true
    1906 }
    1907 
    1908 // release
    1909 func (s MySem) V() {
    1910         s.inUse = false
    1911 
    1912         // This actually deadlocks
    1913         // when single thread
    1914         s.c <- false
    1915 }
    1916 \end{Go}
     2072In 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;
     2073the 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.
     2074The waiter unblocks next from the urgent queue, uses/takes the state, and exits the monitor.
     2075Blocking signal is the reverse, where the waiter is providing the cooperation for the signalling thread;
     2076the 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.
     2077The waiter changes state and exits the monitor, and the signaller unblocks next from the urgent queue to use/take the state.
     2078
     2079Both 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}
     2083monitor M { `condition e`; ... };
     2084void 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}
     2092void rtn$\(_1\)$( M & mutex m1, M & mutex m2 );
     2093void rtn$\(_2\)$( M & mutex m1 );
     2094void 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}
    19172099\end{tabular}
    1918 \caption{Different forms of scheduling.}
    1919 \label{tbl:sched}
    1920 \end{table}
    1921 \end{comment}
    1922 
    1923 This method is more constrained and explicit, which helps users reduce the non-deterministic nature of concurrency.
    1924 Indeed, as the following examples demonstrate, external scheduling allows users to wait for events from other threads without the concern of unrelated events occurring.
    1925 External 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).
    1926 Of 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.
    1927 Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multiple-monitor routines.
    1928 The previous example shows a simple use @_Accept@ versus @wait@/@signal@ and its advantages.
    1929 Note 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 
    1931 For 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.
    1932 On 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 % ======================================================================
    1939 In \uC, a monitor class declaration includes an exhaustive list of monitor operations.
    1940 Since \CFA is not object oriented, monitors become both more difficult to implement and less clear for a user:
    1941 
    1942 \begin{cfa}
    1943 monitor A {};
    1944 
    1945 void f(A & mutex a);
    1946 void g(A & mutex a) {
    1947         waitfor(f); // Obvious which f() to wait for
    1948 }
    1949 
    1950 void f(A & mutex a, int); // New different F added in scope
    1951 void h(A & mutex a) {
    1952         waitfor(f); // Less obvious which f() to wait for
    1953 }
    1954 \end{cfa}
    1955 
    1956 Furthermore, external scheduling is an example where implementation constraints become visible from the interface.
    1957 Here 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}
    1972 For the first two conditions, it is easy to implement a check that can evaluate the condition in a few instructions.
    1973 However, a fast check for @monitor accepts me@ is much harder to implement depending on the constraints put on the monitors.
    1974 Indeed, monitors are often expressed as an entry queue and some acceptor queue as in Figure~\ref{fig:ClassicalMonitor}.
     2100\end{cquote}
     2101For @wait( e )@, the default semantics is to atomically block the signaller and release all acquired mutex parameters, \ie @wait( e, m1, m2 )@.
     2102To override the implicit multi-monitor wait, specific mutex parameter(s) can be specified, \eg @wait( e, m1 )@.
     2103Wait cannot statically verifies the released monitors are the acquired mutex-parameters without disallowing separately compiled helper functions calling @wait@.
     2104While \CC supports bulk locking, @wait@ only accepts a single lock for a condition variable, so bulk locking with condition variables is asymmetric.
     2105Finally, a signaller,
     2106\begin{cfa}
     2107void baz( M & mutex m1, M & mutex m2 ) {
     2108        ... signal( e ); ...
     2109}
     2110\end{cfa}
     2111must 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
     2113Similarly, for @waitfor( rtn )@, the default semantics is to atomically block the acceptor and release all acquired mutex parameters, \ie @waitfor( rtn, m1, m2 )@.
     2114To 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.
     2118Overloaded functions can be disambiguated using a cast
     2119\begin{cfa}
     2120void rtn( M & mutex m );
     2121`int` rtn( M & mutex m );
     2122waitfor( (`int` (*)( M & mutex ))rtn, m );
     2123\end{cfa}
     2124
     2125The ability to release a subset of acquired monitors can result in a \newterm{nested monitor}~\cite{Lister77} deadlock.
     2126\begin{cfa}
     2127void foo( M & mutex m1, M & mutex m2 ) {
     2128        ... wait( `e, m1` ); ...                                $\C{// release m1, keeping m2 acquired )}$
     2129void bar( M & mutex m1, M & mutex m2 ) {        $\C{// must acquire m1 and m2 )}$
     2130        ... signal( `e` ); ...
     2131\end{cfa}
     2132The @wait@ only releases @m1@ so the signalling thread cannot acquire @m1@ and @m2@ to enter @bar@ and @signal@ the condition.
     2133While 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
     2139Figure~\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.
     2140For a @waitfor@ clause to be executed, its @when@ must be true and an outstanding call to its corresponding member(s) must exist.
     2141The \emph{conditional-expression} of a @when@ may call a function, but the function must not block or context switch.
     2142If 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@.
     2143If 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.
     2144If there is a @timeout@ clause, it provides an upper bound on waiting.
     2145If 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.
     2146Hence, the terminating @else@ clause allows a conditional attempt to accept a call without blocking.
     2147If both @timeout@ and @else@ clause are present, the @else@ must be conditional, or the @timeout@ is never triggered.
     2148There is also a traditional future wait queue (not shown) (\eg Microsoft (@WaitForMultipleObjects@)), to wait for a specified number of future elements in the queue.
    19752149
    19762150\begin{figure}
    19772151\centering
    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}
     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}
    19882165\end{figure}
    19892166
    1990 There are other alternatives to these pictures, but in the case of the left picture, implementing a fast accept check is relatively easy.
    1991 Restricted 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.
    1992 This approach requires a unique dense ordering of routines with an upper-bound and that ordering must be consistent across translation units.
    1993 For OO languages these constraints are common, since objects only offer adding member routines consistently across translation units via inheritance.
    1994 However, in \CFA users can extend objects with mutex routines that are only visible in certain translation unit.
    1995 This 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 
    1997 The alternative is to alter the implementation as in Figure~\ref{fig:BulkMonitor}.
    1998 Here, the mutex routine called is associated with a thread on the entry queue while a list of acceptable routines is kept separate.
    1999 Generating a mask dynamically means that the storage for the mask information can vary between calls to @waitfor@, allowing for more flexibility and extensions.
    2000 Storing an array of accepted routine pointers replaces the single instruction bitmask comparison with dereferencing a pointer followed by a linear search.
    2001 Furthermore, 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.
     2167Note, a group of conditional @waitfor@ clauses is \emph{not} the same as a group of @if@ statements, \eg:
     2168\begin{cfa}
     2169if ( C1 ) waitfor( mem1 );                       when ( C1 ) waitfor( mem1 );
     2170else if ( C2 ) waitfor( mem2 );         or when ( C2 ) waitfor( mem2 );
     2171\end{cfa}
     2172The left example only accepts @mem1@ if @C1@ is true or only @mem2@ if @C2@ is true.
     2173The right example accepts either @mem1@ or @mem2@ if @C1@ and @C2@ are true.
     2174
     2175An 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}
     2177void 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 ) { ... }
     2182        }
     2183        // clean up
     2184}
     2185\end{cfa}
     2186When the program main deallocates the buffer, it first calls the buffer's destructor, which is accepted, the destructor runs, and the buffer is deallocated.
     2187However, the buffer thread cannot continue after the destructor call because the object is gone;
     2188hence, clean up in @main@ cannot occur, which means destructors for local objects are not run.
     2189To 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.
     2190Then, the destructor caller unblocks from urgent to deallocate the object.
     2191Accepting the destructor is the idiomatic way in \CFA to terminate a thread performing direct communication.
     2192
     2193
     2194\subsection{Bulk Barging Prevention}
     2195
     2196Figure~\ref{f:BulkBargingPrevention} shows \CFA code where bulk acquire adds complexity to the internal-signalling semantics.
     2197The complexity begins at the end of the inner @mutex@ statement, where the semantics of internal scheduling need to be extended for multiple monitors.
     2198The problem is that bulk acquire is used in the inner @mutex@ statement where one of the monitors is already acquired.
     2199When 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.
     2200However, both the signalling and waiting threads W1 and W2 need some subset of monitors @m1@ and @m2@.
     2201\begin{cquote}
     2202condition c: (order 1) W2(@m2@), W1(@m1@,@m2@)\ \ \ or\ \ \ (order 2) W1(@m1@,@m2@), W2(@m2@) \\
     2203S: 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}
    20022206
    20032207\begin{figure}
    2004 \begin{cfa}[caption={Example of nested external scheduling},label={f:nest-ext}]
    2005 monitor M {};
    2006 void foo( M & mutex a ) {}
    2007 void bar( M & mutex b ) {
    2008         // Nested in the waitfor(bar, c) call
    2009         waitfor(foo, b);
    2010 }
    2011 void baz( M & mutex c ) {
    2012         waitfor(bar, c);
    2013 }
    2014 
    2015 \end{cfa}
     2208\newbox\myboxA
     2209\begin{lrbox}{\myboxA}
     2210\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     2211monitor M m1, m2;
     2212condition c;
     2213mutex( 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
     2229mutex( 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
     2245mutex( 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}
    20162265\end{figure}
    20172266
    2018 Note 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.
    2019 These details are omitted from the picture for the sake of simplicity.
    2020 
    2021 At this point, a decision must be made between flexibility and performance.
    2022 Many design decisions in \CFA achieve both flexibility and performance, for example polymorphic routines add significant flexibility but inlining them means the optimizer can easily remove any runtime cost.
    2023 Here, however, the cost of flexibility cannot be trivially removed.
    2024 In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be  hard to write.
    2025 This 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 % ======================================================================
     2267One 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.
     2268However, 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.
     2269If 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.
     2271To support this efficient semantics (and prevent barging), the implementation maintains a list of monitors acquired for each blocked thread.
     2272When a signaller exits or waits in a monitor function/statement, the front waiter on urgent is unblocked if all its monitors are released.
     2273Implementing 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
     2280In an object-oriented programming language, a class includes an exhaustive list of operations.
     2281A 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.)
     2283In 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
     2285However, 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
     2288translation unit 1
     2289        void `f`( M & mutex m );
     2290        void g( M & mutex m ) { waitfor( `f`, m ); }
     2291translation 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}
     2296The @waitfor@ statements in each translation unit cannot form a unique bit-mask because the monitor type does not carry that information.
     2297Hence, function pointers are used to identify the functions listed in the @waitfor@ statement, stored in a variable-sized array.
     2298Then, the same implementation approach used for the urgent stack is used for the calling queue.
     2299Each 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
    20292303\subsection{Multi-Monitor Scheduling}
    2030 % ======================================================================
    2031 % ======================================================================
    2032 
    2033 External scheduling, like internal scheduling, becomes significantly more complex when introducing multi-monitor syntax.
    2034 Even in the simplest possible case, some new semantics needs to be established:
    2035 \begin{cfa}
    2036 monitor M {};
    2037 
    2038 void f(M & mutex a);
    2039 
    2040 void 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}
    2044 The obvious solution is to specify the correct monitor as follows:
    2045 
    2046 \begin{cfa}
    2047 monitor M {};
    2048 
    2049 void f(M & mutex a);
    2050 
    2051 void g(M & mutex a, M & mutex b) {
    2052         // wait for call to f with argument b
    2053         waitfor(f, b);
    2054 }
    2055 \end{cfa}
    2056 This syntax is unambiguous.
    2057 Both locks are acquired and kept by @g@.
    2058 When routine @f@ is called, the lock for monitor @b@ is temporarily transferred from @g@ to @f@ (while @g@ still holds lock @a@).
    2059 This behaviour can be extended to the multi-monitor @waitfor@ statement as follows.
    2060 
    2061 \begin{cfa}
    2062 monitor M {};
    2063 
    2064 void f(M & mutex a, M & mutex b);
    2065 
    2066 void 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 
    2072 Note 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 
    2074 An important behaviour to note is when a set of monitors only match partially:
    2075 
    2076 \begin{cfa}
    2077 mutex struct A {};
    2078 
    2079 mutex struct B {};
    2080 
    2081 void g(A & mutex a, B & mutex b) {
    2082         waitfor(f, a, b);
    2083 }
    2084 
    2085 A a1, a2;
    2086 B b;
    2087 
    2088 void foo() {
    2089         g(a1, b); // block on accept
    2090 }
    2091 
    2092 void bar() {
    2093         f(a2, b); // fulfill cooperation
    2094 }
    2095 \end{cfa}
    2096 While 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.
    2097 In both cases, partially matching monitor sets does not wakeup the waiting thread.
    2098 It 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 
    2106 Syntactically, the @waitfor@ statement takes a routine identifier and a set of monitors.
    2107 While 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.
    2108 It checks that the set of monitors passed in matches the requirements for a routine call.
    2109 Figure~\ref{f:waitfor} shows various usages of the waitfor statement and which are acceptable.
    2110 The choice of the routine type is made ignoring any non-@mutex@ parameter.
    2111 One limitation of the current implementation is that it does not handle overloading, but overloading is possible.
     2304\label{s:Multi-MonitorScheduling}
     2305
     2306External scheduling, like internal scheduling, becomes significantly more complex for multi-monitor semantics.
     2307Even in the simplest case, new semantics need to be established.
     2308\begin{cfa}
     2309monitor M { ... };
     2310void f( M & mutex m1 );
     2311void g( M & mutex m1, M & mutex m2 ) { `waitfor( f );` } $\C{// pass m1 or m2 to f?}$
     2312\end{cfa}
     2313The solution is for the programmer to disambiguate:
     2314\begin{cfa}
     2315waitfor( f, `m2` ); $\C{// wait for call to f with argument m2}$
     2316\end{cfa}
     2317Both 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@.
     2318This behaviour can be extended to the multi-monitor @waitfor@ statement.
     2319\begin{cfa}
     2320monitor M { ... };
     2321void f( M & mutex m1, M & mutex m2 );
     2322void 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}
     2324Again, the set of monitors passed to the @waitfor@ statement must be entirely contained in the set of monitors already acquired by the accepting function.
     2325Also, the order of the monitors in a @waitfor@ statement is unimportant.
     2326
     2327Figure~\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.
     2328For both examples, the set of monitors is disjoint so unblocking is impossible.
     2329
    21122330\begin{figure}
    2113 \begin{cfa}[caption={Various correct and incorrect uses of the waitfor statement},label={f:waitfor}]
    2114 monitor A{};
    2115 monitor B{};
    2116 
    2117 void f1( A & mutex );
    2118 void f2( A & mutex, B & mutex );
    2119 void f3( A & mutex, int );
    2120 void f4( A & mutex, int );
    2121 void f4( A & mutex, double );
    2122 
    2123 void 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}
     2331\centering
     2332\begin{lrbox}{\myboxA}
     2333\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     2334monitor M1 {} m11, m12;
     2335monitor M2 {} m2;
     2336condition c;
     2337void f( M1 & mutex m1, M2 & mutex m2 ) {
     2338        signal( c );
     2339}
     2340void g( M1 & mutex m1, M2 & mutex m2 ) {
     2341        wait( c );
     2342}
     2343g( `m11`, m2 ); // block on wait
     2344f( `m12`, m2 ); // cannot fulfil
     2345\end{cfa}
     2346\end{lrbox}
     2347
     2348\begin{lrbox}{\myboxB}
     2349\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     2350monitor M1 {} m11, m12;
     2351monitor M2 {} m2;
     2352
     2353void f( M1 & mutex m1, M2 & mutex m2 ) {
     2354
     2355}
     2356void g( M1 & mutex m1, M2 & mutex m2 ) {
     2357        waitfor( f, m1, m2 );
     2358}
     2359g( `m11`, m2 ); // block on accept
     2360f( `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}
    21432370\end{figure}
    21442371
    2145 Finally, for added flexibility, \CFA supports constructing a complex @waitfor@ statement using the @or@, @timeout@ and @else@.
    2146 Indeed, 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.
    2147 To 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.
    2148 A @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.
    2149 Any 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.
    2150 Figure~\ref{f:waitfor2} demonstrates several complex masks and some incorrect ones.
     2372
     2373\subsection{\texorpdfstring{\protect\lstinline@mutex@ Threads}{mutex Threads}}
     2374
     2375Threads 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.
     2376Hence, all monitor features are available when using threads.
     2377Figure~\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.)
     2379The program main in both programs communicates directly with the other thread versus indirect communication where two threads interact through a passive monitor.
     2380Both direct and indirection thread communication are valuable tools in structuring concurrent programs.
    21512381
    21522382\begin{figure}
    2153 \lstset{language=CFA,deletedelim=**[is][]{`}{`}}
    2154 \begin{cfa}
    2155 monitor A{};
    2156 
    2157 void f1( A & mutex );
    2158 void f2( A & mutex );
    2159 
    2160 void 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;
     2383\centering
     2384\begin{lrbox}{\myboxA}
     2385\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     2386
     2387struct Msg { int i, j; };
     2388thread GoRtn { int i;  float f;  Msg m; };
     2389void mem1( GoRtn & mutex gortn, int i ) { gortn.i = i; }
     2390void mem2( GoRtn & mutex gortn, float f ) { gortn.f = f; }
     2391void mem3( GoRtn & mutex gortn, Msg m ) { gortn.m = m; }
     2392void ^?{}( GoRtn & mutex ) {}
     2393
     2394void 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
    21652403        }
    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;
     2404
     2405}
     2406int 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]
     2419func 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                        }
     2436                }
     2437                `shake <- "SHAKE"` $\C{// completion}$
    21702438        }
    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;
     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}
     2457\end{figure}
     2458
     2459\begin{comment}
     2460The 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}
     2467thread Ping {} pi;
     2468void ping( Ping & mutex ) {}
     2469void main( Ping & pi ) {
     2470        for ( 10 ) {
     2471                `waitfor( ping, pi );`
     2472                `pong( po );`
    21772473        }
    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;
     2474}
     2475int main() {}
     2476\end{cfa}
     2477&
     2478\begin{cfa}
     2479thread Pong {} po;
     2480void pong( Pong & mutex ) {}
     2481void main( Pong & po ) {
     2482        for ( 10 ) {
     2483                `ping( pi );`
     2484                `waitfor( pong, po );`
    21822485        }
    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 % ======================================================================
    2208 An interesting use for the @waitfor@ statement is destructor semantics.
    2209 Indeed, the @waitfor@ statement can accept any @mutex@ routine, which includes the destructor (see section \ref{data}).
    2210 However, 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.
    2211 The simplest approach is to disallow @waitfor@ on a destructor.
    2212 However, 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.
    2213 \begin{figure}
    2214 \begin{cfa}[caption={Example of an executor which executes action in series until the destructor is called.},label={f:dtor-order}]
    2215 monitor Executer {};
    2216 struct  Action;
    2217 
    2218 void ^?{}   (Executer & mutex this);
    2219 void execute(Executer & mutex this, const Action & );
    2220 void run    (Executer & mutex this) {
    2221         while(true) {
    2222                    waitfor(execute, this);
    2223                 or waitfor(^?{}   , this) {
    2224                         break;
    2225                 }
    2226         }
    2227 }
    2228 \end{cfa}
    2229 \end{figure}
    2230 For 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.
    2231 Switching 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}
    2242 Historically, computer performance was about processor speeds and instruction counts.
    2243 However, with heat dissipation being a direct consequence of speed increase, parallelism has become the new source for increased performance~\cite{Sutter05, Sutter05b}.
    2244 In this decade, it is no longer reasonable to create a high-performance application without caring about parallelism.
    2245 Indeed, parallelism is an important aspect of performance and more specifically throughput and hardware utilization.
    2246 The lowest-level approach of parallelism is to use \textbf{kthread} in combination with semantics like @fork@, @join@, \etc.
    2247 However, since these have significant costs and limitations, \textbf{kthread} are now mostly used as an implementation tool rather than a user oriented one.
    2248 There are several alternatives to solve these issues that all have strengths and weaknesses.
    2249 While 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}
    2253 A direct improvement on the \textbf{kthread} approach is to use \textbf{uthread}.
    2254 These threads offer most of the same features that the operating system already provides but can be used on a much larger scale.
    2255 This 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.
    2256 The 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.
    2257 These 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 
    2259 Examples 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}
    2262 A popular variant of \textbf{uthread} is what is often referred to as \textbf{fiber}.
    2263 However, \textbf{fiber} do not present meaningful semantic differences with \textbf{uthread}.
    2264 The significant difference between \textbf{uthread} and \textbf{fiber} is the lack of \textbf{preemption} in the latter.
    2265 Advocates 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.
    2266 Therefore this proposal largely ignores fibers.
    2267 
    2268 An example of a language that uses fibers is Go~\cite{Go}
    2269 
    2270 \subsection{Jobs and Thread Pools}
    2271 An approach on the opposite end of the spectrum is to base parallelism on \textbf{pool}.
    2272 Indeed, \textbf{pool} offer limited flexibility but at the benefit of a simpler user interface.
    2273 In \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.
    2274 This approach means users need not worry about concurrency but significantly limit the interaction that can occur among jobs.
    2275 Indeed, any \textbf{job} that blocks also block the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably.
    2276 It can be argued that a solution to this problem is to use more workers than available cores.
    2277 However, 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 
    2279 The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
    2280 
    2281 \subsection{Paradigm Performance}
    2282 While 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.
    2283 Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload.
    2284 Having 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).
    2285 However, interactions among jobs can easily exacerbate contention.
    2286 User-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.
    2287 Finally, 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}
    2290 A \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}.
    2291 It 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.
    2292 A \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.
    2295 Currently \CFA only supports one \textbf{cfacluster}, the initial one.
    2296 
    2297 \subsection{Future Work: Machine Setup}\label{machine}
    2298 While this was not done in the context of this paper, another important aspect of clusters is affinity.
    2299 While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heterogeneous setups.
    2300 For example, a system using \textbf{numa} configurations may benefit from users being able to tie clusters and/or kernel threads to certain CPU cores.
    2301 OS 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}
    2304 Given these building blocks, it is possible to reproduce all three of the popular paradigms.
    2305 Indeed, \textbf{uthread} is the default paradigm in \CFA.
    2306 However, disabling \textbf{preemption} on a cluster means threads effectively become fibers.
    2307 Since 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.
    2308 Finally, 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}
    2313 There are several challenges specific to \CFA when implementing concurrency.
    2314 These challenges are a direct result of bulk acquire and loose object definitions.
    2315 These two constraints are the root cause of most design decisions in the implementation.
    2316 Furthermore, to avoid contention from dynamically allocating memory in a concurrent environment, the internal-scheduling design is (almost) entirely free of mallocs.
    2317 This 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.
    2318 This extra goal means that memory management is a constant concern in the design of the system.
    2319 
    2320 The main memory concern for concurrency is queues.
    2321 All 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.
    2322 Since 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.
    2323 Conveniently, 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.
    2324 Since 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.
    2325 The 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 
    2327 Note 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 
    2335 The first step towards the monitor implementation is simple @mutex@ routines.
    2336 In the single monitor case, mutual-exclusion is done using the entry/exit procedure in listing \ref{f:entry1}.
    2337 The entry/exit procedures do not have to be extended to support multiple monitors.
    2338 Indeed it is sufficient to enter/leave monitors one-by-one as long as the order is correct to prevent deadlock~\cite{Havender68}.
    2339 In \CFA, ordering of monitor acquisition relies on memory ordering.
    2340 This 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.
    2341 When a mutex call is made, the concerned monitors are aggregated into a variable-length pointer array and sorted based on pointer values.
    2342 This array persists for the entire duration of the mutual-exclusion and its ordering reused extensively.
    2343 \begin{figure}
    2344 \begin{multicols}{2}
    2345 Entry
    2346 \begin{cfa}
    2347 if monitor is free
    2348         enter
    2349 elif already own the monitor
    2350         continue
    2351 else
    2352         block
    2353 increment recursions
    2354 \end{cfa}
    2355 \columnbreak
    2356 Exit
    2357 \begin{cfa}
    2358 decrement recursion
    2359 if 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}
    2366 \end{figure}
    2367 
    2368 \subsection{Details: Interaction with polymorphism}
    2369 Depending 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.
    2370 However, it is shown that entry-point locking solves most of the issues.
    2371 
    2372 First of all, interaction between @otype@ polymorphism (see Section~\ref{s:ParametricPolymorphism}) and monitors is impossible since monitors do not support copying.
    2373 Therefore, the main question is how to support @dtype@ polymorphism.
    2374 It 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.
    2375 For example:
     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}
     2495Note, 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
     2501Table~\ref{t:ObjectPropertyComposition} shows how the \CFA high-level constructs cover 3 fundamental execution properties: thread, stateful function, and mutual exclusion.
     2502Case 1 is a basic object, with none of the new execution properties.
     2503Case 2 allows @mutex@ calls to Case 1 to protect shared data.
     2504Case 3 allows stateful functions to suspend/resume but restricts operations because the state is stackless.
     2505Case 4 allows @mutex@ calls to Case 3 to protect shared data.
     2506Cases 5 and 6 are the same as 3 and 4 without restriction because the state is stackful.
     2507Cases 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.
     2508Cases 9 and 10 have a stackful thread without and with @mutex@ calls.
     2509For situations where threads do not require direct communication, case 9 provides faster creation/destruction by eliminating @mutex@ setup.
     2510
    23762511\begin{table}
    2377 \begin{center}
    2378 \begin{tabular}{|c|c|c|}
    2379 Mutex & \textbf{callsite-locking} & \textbf{entry-point-locking} \\
    2380 call & cfa-code & cfa-code \\
     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} \\
    23812519\hline
    2382 \begin{cfa}[tabsize=3]
    2383 void foo(monitor& mutex a){
    2384 
    2385         // Do Work
    2386         //...
    2387 
    2388 }
    2389 
    2390 void main() {
    2391         monitor a;
    2392 
    2393         foo(a);
    2394 
    2395 }
    2396 \end{cfa} & \begin{cfa}[tabsize=3]
    2397 foo(& a) {
    2398 
    2399         // Do Work
    2400         //...
    2401 
    2402 }
    2403 
    2404 main() {
    2405         monitor a;
    2406         acquire(a);
    2407         foo(a);
    2408         release(a);
    2409 }
    2410 \end{cfa} & \begin{cfa}[tabsize=3]
    2411 foo(& a) {
    2412         acquire(a);
    2413         // Do Work
    2414         //...
    2415         release(a);
    2416 }
    2417 
    2418 main() {
    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 
    2431 Note 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
    2434 forall(dtype T)
    2435 void foo(T * mutex t);
    2436 
    2437 // Correct: this routine only works on monitors (any monitor)
    2438 forall(dtype T | is_monitor(T))
    2439 void bar(T * mutex t));
    2440 \end{cfa}
    2441 
    2442 Both entry point and \textbf{callsite-locking} are feasible implementations.
    2443 The 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.
    2444 It 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.
    2445 For example, the monitor call can appear in the middle of an expression.
    2446 Furthermore, 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 
    2454 Figure \ref{fig:system1} shows a high-level picture if the \CFA runtime system in regards to concurrency.
    2455 Each component of the picture is explained in detail in the flowing sections.
    2456 
    2457 \begin{figure}
    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}
    2466 Parallelism 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.
    2467 Indeed, any parallelism must go through operating-system libraries.
    2468 However, \textbf{uthread} are still the main source of concurrency, processors are simply the underlying source of parallelism.
    2469 Indeed, processor \textbf{kthread} simply fetch a \textbf{uthread} from the scheduler and run it; they are effectively executers for user-threads.
    2470 The 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.
    2471 Processors internally use coroutines to take advantage of the existing context-switching semantics.
    2472 
    2473 \subsection{Stack Management}
    2474 One of the challenges of this system is to reduce the footprint as much as possible.
    2475 Specifically, all @pthread@s created also have a stack created with them, which should be used as much as possible.
    2476 Normally, 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.
    2477 The exception to this rule is the Main Processor, \ie the initial \textbf{kthread} that is given to any program.
    2478 In 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}
    2481 As 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.
    2482 To improve performance and simplicity, context-switching is implemented using the following assumption: all context-switches happen inside a specific routine call.
    2483 This 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.
    2484 Note that the instruction pointer can be left untouched since the context-switch is always inside the same routine
    2485 Threads, however, do not context-switch between each other directly.
    2486 They context-switch to the scheduler.
    2487 This 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.
    2488 Obviously, this doubles the context-switch cost because threads must context-switch to an intermediate stack.
    2489 The alternative 1-step context-switch uses the stack of the ``from'' thread to schedule and then context-switches directly to the ``to'' thread.
    2490 However, the performance of the 2-step context-switch is still superior to a @pthread_yield@ (see section \ref{results}).
    2491 Additionally, 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).
    2492 This option is not currently present in \CFA, but the changes required to add it are strictly additive.
    2493 
    2494 \subsection{Preemption} \label{preemption}
    2495 Finally, an important aspect for any complete threading system is preemption.
    2496 As 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.
    2497 Indeed, preemption is desirable because it adds a degree of isolation among threads.
    2498 In 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.
    2499 Obviously, preemption is not optimal for every workload.
    2500 However any preemptive system can become a cooperative system by making the time slices extremely large.
    2501 Therefore, \CFA uses a preemptive threading system.
    2502 
    2503 Preemption in \CFA\footnote{Note that the implementation of preemption is strongly tied with the underlying threading system.
    2504 For 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.
    2505 Every processor keeps track of the current time and registers an expiration time with the preemption system.
    2506 When 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.
    2507 These timers use the Linux signal {\tt SIGALRM}, which is delivered to the process rather than the kernel-thread.
    2508 This 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}
    2510 A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked.
    2511 If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.
    2512 SIGNAL(7) - Linux Programmer's Manual
    2513 \end{quote}
    2514 For 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 
    2516 Now because of how involuntary context-switches are handled, the kernel thread handling {\tt SIGALRM} cannot also be a processor thread.
    2517 Hence, 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.
    2518 This 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.
    2519 As a result, a signal handler can start on one kernel thread and terminate on a second kernel thread (but the same user thread).
    2520 It 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.
    2521 This 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}.
    2522 However, since the kernel thread handling preemption requires a different signal mask, executing user threads on the kernel-alarm thread can cause deadlocks.
    2523 For this reason, the alarm thread is in a tight loop around a system call to @sigwaitinfo@, requiring very little CPU time for preemption.
    2524 One final detail about the alarm thread is how to wake it when additional communication is required (\eg on thread termination).
    2525 This unblocking is also done using {\tt SIGALRM}, but sent through the @pthread_sigqueue@.
    2526 Indeed, @sigwait@ can differentiate signals sent from @pthread_sigqueue@ from signals sent from alarms or the kernel.
    2527 
    2528 \subsection{Scheduler}
    2529 Finally, an aspect that was not mentioned yet is the scheduling algorithm.
    2530 Currently, the \CFA scheduler uses a single ready queue for all processors, which is the simplest approach to scheduling.
    2531 Further discussion on scheduling is present in section \ref{futur:sched}.
    2532 
    2533 % ======================================================================
    2534 % ======================================================================
    2535 \section{Internal Scheduling} \label{impl:intsched}
    2536 % ======================================================================
    2537 % ======================================================================
    2538 The 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 
    2547 This picture has several components, the two most important being the entry queue and the AS-stack.
    2548 The 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 
    2550 For \CFA, this picture does not have support for blocking multiple monitors on a single condition.
    2551 To support bulk acquire two changes to this picture are required.
    2552 First, it is no longer helpful to attach the condition to \emph{a single} monitor.
    2553 Secondly, 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 
    2563 This picture and the proper entry and leave algorithms (see listing \ref{f:entry2}) is the fundamental implementation of internal scheduling.
    2564 Note 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.
    2565 The thread is woken up when all the pieces have popped from the AS-stacks and made active.
    2566 In this picture, the threads are split into halves but this is only because there are two monitors.
    2567 For a specific signalling operation every monitor needs a piece of thread on its AS-stack.
    2568 
    2569 \begin{figure}
    2570 \begin{multicols}{2}
    2571 Entry
    2572 \begin{cfa}
    2573 if monitor is free
    2574         enter
    2575 elif already own the monitor
    2576         continue
    2577 else
    2578         block
    2579 increment recursion
    2580 
    2581 \end{cfa}
    2582 \columnbreak
    2583 Exit
    2584 \begin{cfa}
    2585 decrement recursion
    2586 if 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 
    2600 The solution discussed in \ref{s:InternalScheduling} can be seen in the exit routine of listing \ref{f:entry2}.
    2601 Basically, 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.
    2602 This solution is deadlock safe as well as preventing any potential barging.
    2603 The 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 
    2613 Figure \ref{fig:structs} shows a high-level representation of these data structures.
    2614 The main idea behind them is that, a thread cannot contain an arbitrary number of intrusive ``next'' pointers for linking onto monitors.
    2615 The @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.
    2616 Once 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 % ======================================================================
    2623 Similarly 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}.
    2624 For 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).
    2625 However, in the case of external scheduling, there is no equivalent object which is associated with @waitfor@ statements.
    2626 This absence means the queues holding the waiting threads must be stored inside at least one of the monitors that is acquired.
    2627 These monitors being the only objects that have sufficient lifetime and are available on both sides of the @waitfor@ statement.
    2628 This requires an algorithm to choose which monitor holds the relevant queue.
    2629 It is also important that said algorithm be independent of the order in which users list parameters.
    2630 The 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.
    2631 This assumes that the lock acquiring order is static for the lifetime of all concerned objects but that is a reasonable constraint.
    2632 
    2633 This 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.
    2636 These queues need to contain a set of monitors for each of the waiting threads.
    2637 Therefore, 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.
    2639 Indeed, 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}
    2641 Therefore, 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.
    2644 The @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.
    2646 This mask contains for each acceptable routine, a routine pointer and an array of monitors to go with it.
    2647 It also needs storage to keep track of which routine was accepted.
    2648 Since this information is not specific to any monitor, the monitors actually contain a pointer to an integer on the stack of the waiting thread.
    2649 Note 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.
    2650 This 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}
    2655 Finally, to support the ordering inversion of destructors, the code generation needs to be modified to use a special entry routine.
    2656 This routine is needed because of the storage requirements of the call order inversion.
    2657 Indeed, 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.
    2658 For 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.
    2659 The @waitfor@ semantics can then be adjusted correspondingly, as seen in listing \ref{f:entry-dtor}
    2660 
    2661 \begin{figure}
    2662 \begin{multicols}{2}
    2663 Entry
    2664 \begin{cfa}
    2665 if monitor is free
    2666         enter
    2667 elif already own the monitor
    2668         continue
    2669 elif matches waitfor mask
    2670         push criteria to AS-stack
    2671         continue
    2672 else
    2673         block
    2674 increment recursion
    2675 \end{cfa}
    2676 \columnbreak
    2677 Exit
    2678 \begin{cfa}
    2679 decrement recursion
    2680 if 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}
    2699 Destructor Entry
    2700 \begin{cfa}
    2701 if monitor is free
    2702         enter
    2703 elif already own the monitor
    2704         increment recursion
    2705         return
    2706 create wait context
    2707 if matches waitfor mask
    2708         reset mask
    2709         push self to AS-stack
    2710         baton pass
    2711 else
    2712         wait
    2713 increment recursion
    2714 \end{cfa}
    2715 \columnbreak
    2716 Waitfor
    2717 \begin{cfa}
    2718 if 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
    2727 endif
    2728 if non-blocking
    2729         Unlock all monitors
    2730         Return
    2731 endif
    2732 
    2733 push self to AS-stack
    2734 set waitfor mask
    2735 block
    2736 return
    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}
    2752 As 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.
    2753 For 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
    2757 thread Renderer {} renderer;
    2758 Frame * simulate( Simulator & this );
    2759 
    2760 // Simulation declaration
    2761 thread Simulator{} simulator;
    2762 void render( Renderer & this );
    2763 
    2764 // Blocking call used as communication
    2765 void draw( Renderer & mutex this, Frame * frame );
    2766 
    2767 // Simulation loop
    2768 void main( Simulator & this ) {
    2769         while( true ) {
    2770                 Frame * frame = simulate( this );
    2771                 draw( renderer, frame );
    2772         }
    2773 }
    2774 
    2775 // Rendering loop
    2776 void main( Renderer & this ) {
    2777         while( true ) {
    2778                 waitfor( draw, this );
    2779                 render( this );
    2780         }
    2781 }
    2782 \end{cfa}
    2783 \end{figure}
    2784 One 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.
    2785 Luckily, 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
    2789 thread Renderer {} renderer;
    2790 Frame * simulate( Simulator & this );
    2791 
    2792 // Simulation declaration
    2793 thread Simulator{} simulator;
    2794 void render( Renderer & this );
    2795 
    2796 // Blocking call used as communication
    2797 void draw( Renderer & mutex this, Frame * frame );
    2798 
    2799 // Simulation loop
    2800 void 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
    2811 void main( Renderer & this ) {
    2812         while( true ) {
    2813                    waitfor( draw, this );
    2814                 or waitfor( ^?{}, this ) {
    2815                         // Add an exit condition
    2816                         break;
    2817                 }
    2818 
    2819                 render( this );
    2820         }
    2821 }
    2822 
    2823 // Call destructor for simulator once simulator finishes
    2824 // Call destructor for renderer to signify shutdown
    2825 \end{cfa}
    2826 \end{figure}
    2827 
    2828 \section{Fibers \& Threads}
    2829 As mentioned in section \ref{preemption}, \CFA uses preemptive threads by default but can use fibers on demand.
    2830 Currently, using fibers is done by adding the following line of code to the program~:
    2831 \begin{cfa}
    2832 unsigned int default_preemption() {
    2833         return 0;
    2834 }
    2835 \end{cfa}
    2836 This routine is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, \ie no preemption.
    2837 However, 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
    2842 struct cluster;
    2843 
    2844 // Processor forward declaration
    2845 struct processor;
    2846 
    2847 // Construct clusters with a preemption rate
    2848 void ?{}(cluster& this, unsigned int rate);
    2849 // Construct processor and add it to cluster
    2850 void ?{}(processor& this, cluster& cluster);
    2851 // Construct thread and schedule it on cluster
    2852 void ?{}(thread& this, cluster& cluster);
    2853 
    2854 // Declare two clusters
    2855 cluster thread_cluster = { 10`ms };                     // Preempt every 10 ms
    2856 cluster fibers_cluster = { 0 };                         // Never preempt
    2857 
    2858 // Construct 4 processors
    2859 processor 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
    2869 thread UThread {};
    2870 void ?{}(UThread& this) {
    2871         // Construct underlying thread to automatically
    2872         // be scheduled on the thread cluster
    2873         (this){ thread_cluster }
    2874 }
    2875 
    2876 void main(UThread & this);
    2877 
    2878 // Declares fibers
    2879 thread Fiber {};
    2880 void ?{}(Fiber& this) {
    2881         // Construct underlying thread to automatically
    2882         // be scheduled on the fiber cluster
    2883         (this.__thread){ fibers_cluster }
    2884 }
    2885 
    2886 void 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}
    2897 Table \ref{tab:machine} shows the characteristics of the machine used to run the benchmarks.
    2898 All tests were made on this machine.
    2899 \begin{table}
    2900 \begin{center}
    2901 \begin{tabular}{| l | r | l | r |}
    2902 \hline
    2903 Architecture            & x86\_64                       & NUMA node(s)  & 8 \\
    2904 \hline
    2905 CPU op-mode(s)          & 32-bit, 64-bit                & Model name    & AMD Opteron\texttrademark  Processor 6380 \\
    2906 \hline
    2907 Byte Order                      & Little Endian                 & CPU Freq              & 2.5\si{\giga\hertz} \\
    2908 \hline
    2909 CPU(s)                  & 64                            & L1d cache     & \SI{16}{\kibi\byte} \\
    2910 \hline
    2911 Thread(s) per core      & 2                             & L1i cache     & \SI{64}{\kibi\byte} \\
    2912 \hline
    2913 Core(s) per socket      & 8                             & L2 cache              & \SI{2048}{\kibi\byte} \\
    2914 \hline
    2915 Socket(s)                       & 4                             & L3 cache              & \SI{6144}{\kibi\byte} \\
     2520thread  & stateful                              & \multicolumn{1}{c|}{No} & \multicolumn{1}{c}{Yes} \\
    29162521\hline
    29172522\hline
    2918 Operating system                & Ubuntu 16.04.3 LTS    & Kernel                & Linux 4.4-97-generic \\
     2523No              & No                                    & \textbf{1}\ \ \ aggregate type                & \textbf{2}\ \ \ @monitor@ aggregate type \\
    29192524\hline
    2920 Compiler                        & GCC 6.3               & Translator    & CFA 1 \\
     2525No              & Yes (stackless)               & \textbf{3}\ \ \ @generator@                   & \textbf{4}\ \ \ @monitor@ @generator@ \\
    29212526\hline
    2922 Java version            & OpenJDK-9             & Go version    & 1.9.2 \\
     2527No              & Yes (stackful)                & \textbf{5}\ \ \ @coroutine@                   & \textbf{6}\ \ \ @monitor@ @coroutine@ \\
    29232528\hline
     2529Yes             & No / Yes (stackless)  & \textbf{7}\ \ \ {\color{red}rejected} & \textbf{8}\ \ \ {\color{red}rejected} \\
     2530\hline
     2531Yes             & Yes (stackful)                & \textbf{9}\ \ \ @thread@                              & \textbf{10}\ \ @monitor@ @thread@ \\
    29242532\end{tabular}
    2925 \end{center}
    2926 \caption{Machine setup used for the tests}
    2927 \label{tab:machine}
    29282533\end{table}
    29292534
    2930 \section{Micro Benchmarks}
    2931 All benchmarks are run using the same harness to produce the results, seen as the @BENCH()@ macro in the following examples.
    2932 This 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}
    2940 The method used to get time is @clock_gettime(CLOCK_THREAD_CPUTIME_ID);@.
    2941 Each benchmark is using many iterations of a simple call to measure the cost of the call.
    2942 The specific number of iterations depends on the specific benchmark.
    2943 
    2944 \subsection{Context-Switching}
    2945 The first interesting benchmark is to measure how long context-switches take.
    2946 The simplest approach to do this is to yield on a thread, which executes a 2-step context switch.
    2947 Yielding 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).
    2948 In 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.
    2949 Figure~\ref{f:ctx-switch} shows the code for coroutines and threads with the results in table \ref{tab:ctx-switch}.
    2950 All omitted tests are functionally identical to one of these tests.
    2951 The difference between coroutines and threads can be attributed to the cost of scheduling.
     2535
     2536\subsection{Low-level Locks}
     2537
     2538For 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.
     2539Some 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
     2570In 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.
     2571If the jobs are dependent, \ie interact, there is an implicit/explicit dependency graph that ties them together.
     2572While removing direct concurrency, and hence the amount of context switching, thread pools significantly limit the interaction that can occur among jobs.
     2573Indeed, jobs should not block because that also blocks the underlying thread, which effectively means the CPU utilization, and therefore throughput, suffers.
     2574While 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.
     2575As well, concurrency errors return, which threads pools are suppose to mitigate.
     2576
    29522577\begin{figure}
     2578\centering
     2579\begin{tabular}{@{}l|l@{}}
     2580\begin{cfa}
     2581struct Adder {
     2582    int * row, cols;
     2583};
     2584int operator()() {
     2585        subtotal = 0;
     2586        for ( int c = 0; c < cols; c += 1 )
     2587                subtotal += row[c];
     2588        return subtotal;
     2589}
     2590void ?{}( 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}
     2600int 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}
     2617\end{tabular}
     2618\caption{Executor}
     2619\end{figure}
     2620\end{comment}
     2621
     2622
     2623\section{Runtime Structure}
     2624\label{s:CFARuntimeStructure}
     2625
     2626Figure~\ref{f:RunTimeStructure} illustrates the runtime structure of a \CFA program.
     2627In 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.
     2628An executing thread is illustrated by its containment in a processor.
     2629
     2630\begin{figure}
     2631\centering
     2632\input{RunTimeStructure}
     2633\caption{\CFA Runtime structure}
     2634\label{f:RunTimeStructure}
     2635\end{figure}
     2636
     2637
     2638\subsection{Cluster}
     2639\label{s:RuntimeStructureCluster}
     2640
     2641A \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).
     2642The purpose of a cluster is to control the amount of parallelism that is possible among threads, plus scheduling and other execution defaults.
     2643The default cluster-scheduler is single-queue multi-server, which provides automatic load-balancing of threads on processors.
     2644However, the design allows changing the scheduler, \eg multi-queue multi-server with work-stealing/sharing across the virtual processors.
     2645If several clusters exist, both threads and virtual processors, can be explicitly migrated from one cluster to another.
     2646No automatic load balancing among clusters is performed by \CFA.
     2647
     2648When 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.
     2649The user cluster is created to contain the application user-threads.
     2650Having all threads execute on the one cluster often maximizes utilization of processors, which minimizes runtime.
     2651However, 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
     2657A 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.
     2658Programs may use more virtual processors than hardware processors.
     2659On 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.)
     2661The \CFA runtime attempts to block unused processors and unblock processors as the system load increases;
     2662balancing the workload with processors is difficult because it requires future knowledge, \ie what will the applicaton workload do next.
     2663Preemption occurs on virtual processors rather than user threads, via operating-system interrupts.
     2664Thus virtual processors execute user threads, where preemption frequency applies to a virtual processor, so preemption occurs randomly across the executed user threads.
     2665Turning off preemption transforms user threads into fibres.
     2666
     2667
     2668\begin{comment}
     2669\section{Implementation}
     2670\label{s:Implementation}
     2671
     2672A primary implementation challenge is avoiding contention from dynamically allocating memory because of bulk acquire, \eg the internal-scheduling design is (almost) free of allocations.
     2673All 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.
     2674Furthermore, several bulk-acquire operations need a variable amount of memory.
     2675This 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
     2677In \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.
     2678When a mutex call is made, pointers to the concerned monitors are aggregated into a variable-length array and sorted.
     2679This array persists for the entire duration of the mutual exclusion and is used extensively for synchronization operations.
     2680
     2681To 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;
     2682the corresponding registers are then restored for the other context.
     2683Note, the instruction pointer is untouched since the context switch is always inside the same function.
     2684Experimental 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
     2686All kernel threads (@pthreads@) created a stack.
     2687Each \CFA virtual processor is implemented as a coroutine and these coroutines run directly on the kernel-thread stack, effectively stealing this stack.
     2688The exception to this rule is the program main, \ie the initial kernel thread that is given to any program.
     2689In 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
     2695Nondeterministic 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.
     2696This atomic reliance can fail on multi-core machines, because execution across cores is nondeterministic.
     2697A 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).
     2698Preemption is normally handled by setting a countdown timer on each virtual processor.
     2699When 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.
     2700Multiple signal handlers may be pending.
     2701When 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.
     2702The 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;
     2703therefore, the same signal mask is required for all virtual processors in a cluster.
     2704Because preemption frequency is usually long (1 millisecond) performance cost is negligible.
     2705
     2706Linux switched a decade ago from specific to arbitrary process signal-delivery for applications with multiple kernel threads.
     2707\begin{cquote}
     2708A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked.
     2709If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which it will deliver the signal.
     2710SIGNAL(7) - Linux Programmer's Manual
     2711\end{cquote}
     2712Hence, 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).
     2713To 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.
     2714Virtual processors register an expiration time with the discrete-event simulator, which is inserted in sorted order.
     2715The 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.
     2716Processing 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
     2721There are two versions of the \CFA runtime kernel: debug and non-debug.
     2722The 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.
     2723After 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
     2729To 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.
     2730For 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.
     2731The 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
     2733All benchmarks are run using the following harness. (The Java harness is augmented to circumvent JIT issues.)
     2734\begin{cfa}
     2735unsigned int N = 10_000_000;
     2736#define BENCH( `run` ) Time before = getTimeNsec();  `run;`  Duration result = (getTimeNsec() - before) / N;
     2737\end{cfa}
     2738The method used to get time is @clock_gettime( CLOCK_REALTIME )@.
     2739Each benchmark is performed @N@ times, where @N@ varies depending on the benchmark;
     2740the total time is divided by @N@ to obtain the average time for a benchmark.
     2741Each benchmark experiment is run 31 times.
     2742All 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
     2747Object creation is measured by creating/deleting the specific kind of concurrent object.
     2748Figure~\ref{f:creation} shows the code for \CFA, with results in Table~\ref{tab:creation}.
     2749The 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
    29532751\begin{multicols}{2}
    2954 \CFA Coroutines
    2955 \begin{cfa}
    2956 coroutine GreatSuspender {};
    2957 void main(GreatSuspender& this) {
    2958         while(true) { suspend(); }
    2959 }
     2752\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     2753\begin{cfa}
     2754@thread@ MyThread {};
     2755void @main@( MyThread & ) {}
    29602756int main() {
    2961         GreatSuspender s;
    2962         resume(s);
     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          \\
     2777Goroutine                               & 4068.0        & 4113.1        & 414.55        \\
     2778Java Thread                             & 103848.5      & 104295.4      & 2637.57       \\
     2779Pthreads                                & 33112.6       & 33127.1       & 165.90
     2780\end{tabular}
     2781\end{multicols}
     2782
     2783
     2784\paragraph{Context-Switching}
     2785
     2786In 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.)
     2788Similarly, when modularization extends to coroutines/tasks, the time for a context switch becomes a relevant factor.
     2789The coroutine test is from resumer to suspender and from suspender to resumer, which is two context switches.
     2790The thread test is using yield to enter and return from the runtime kernel, which is two context switches.
     2791The difference in performance between coroutine and thread context-switch is the cost of scheduling for threads, whereas coroutines are self-scheduling.
     2792Figure~\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;
     2798void main( C & ) { for ( ;; ) { @suspend;@ } }
     2799int main() { // coroutine test
     2800        BENCH( for ( N ) { @resume( c );@ } )
     2801        sout | result`ns;
     2802}
     2803int 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} \\
     2818C 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  \\
     2824Goroutine               & 141.0 & 141.3 & 3.39  \\
     2825Java Thread             & 374.0 & 375.8 & 10.38 \\
     2826Pthreads Thread & 361.0 & 365.3 & 13.19
     2827\end{tabular}
     2828\end{multicols}
     2829
     2830
     2831\paragraph{Mutual-Exclusion}
     2832
     2833Uncontented mutual exclusion, which frequently occurs, is measured by entering/leaving a critical section.
     2834For monitors, entering and leaving a monitor function is measured.
     2835To 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.
     2836Figure~\ref{f:mutex} shows the code for \CFA with all results in Table~\ref{tab:mutex}.
     2837Note, 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*/;
     2843void __attribute__((noinline))
     2844do_call( M & @mutex m/*, m2, m3, m4*/@ ) {}
     2845int main() {
    29632846        BENCH(
    2964                 for(size_t i=0; i<n; i++) {
    2965                         resume(s);
    2966                 },
    2967                 result
     2847                for( N ) do_call( m1/*, m2, m3, m4*/ );
    29682848        )
    2969         printf("%llu\n", result);
    2970 }
    2971 \end{cfa}
     2849        sout | result`ns;
     2850}
     2851\end{cfa}
     2852\captionof{figure}{\CFA acquire/release mutex benchmark}
     2853\label{f:mutex}
     2854
    29722855\columnbreak
    2973 \CFA Threads
    2974 \begin{cfa}
    2975 
    2976 
    2977 
    2978 
    2979 int 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}
     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} \\
     2862test 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  \\
     2867Java synchronized method                & 31.0  & 31.1  & 0.50  \\
     2868Pthreads Mutex Lock                             & 33.6  & 32.6  & 1.14
     2869\end{tabular}
    29912870\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} \\
    3001 \hline
    3002 Kernel 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 \\
    3007 Goroutine               & 150           & 149.96        & 3.16 \\
    3008 Java Thread             & 289           & 290.68        & 8.72 \\
    3009 \hline
    3010 \end{tabular}
    3011 \end{center}
    3012 \caption{Context Switch comparison.
    3013 All numbers are in nanoseconds(\si{\nano\second})}
    3014 \label{tab:ctx-switch}
    3015 \end{table}
    3016 
    3017 \subsection{Mutual-Exclusion}
    3018 The next interesting benchmark is to measure the overhead to enter/leave a critical-section.
    3019 For monitors, the simplest approach is to measure how long it takes to enter and leave a monitor routine.
    3020 Figure~\ref{f:mutex} shows the code for \CFA.
    3021 To 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.
    3022 The results can be shown in table \ref{tab:mutex}.
    3023 
    3024 \begin{figure}
    3025 \begin{cfa}[caption={\CFA benchmark code used to measure mutex routines.},label={f:mutex}]
    3026 monitor M {};
    3027 void __attribute__((noinline)) call( M & mutex m /*, m2, m3, m4*/ ) {}
    3028 
    3029 int main() {
    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
    3048 C routine                                               & 2             & 2             & 0    \\
    3049 FetchAdd + FetchSub                             & 26            & 26            & 0    \\
    3050 Pthreads 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 \\
    3055 Java synchronized routine                       & 27            & 28.57 & 2.6  \\
    3056 \hline
    3057 \end{tabular}
    3058 \end{center}
    3059 \caption{Mutex routine comparison.
    3060 All numbers are in nanoseconds(\si{\nano\second})}
    3061 \label{tab:mutex}
    3062 \end{table}
    3063 
    3064 \subsection{Internal Scheduling}
    3065 The internal-scheduling benchmark measures the cost of waiting on and signalling a condition variable.
    3066 Figure~\ref{f:int-sched} shows the code for \CFA, with results table \ref{tab:int-sched}.
    3067 As 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}]
     2871
     2872
     2873\paragraph{External Scheduling}
     2874
     2875External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement.
     2876Figure~\ref{f:ext-sched} shows the code for \CFA, with results in Table~\ref{tab:ext-sched}.
     2877Note, 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}
    30712883volatile int go = 0;
    3072 condition c;
    3073 monitor M {};
    3074 M m1;
    3075 
    3076 void __attribute__((noinline)) do_call( M & mutex a1 ) { signal(c); }
    3077 
     2884@monitor@ M {} m;
    30782885thread T {};
    3079 void ^?{}( T & mutex this ) {}
    3080 void main( T & this ) {
    3081         while(go == 0) { yield(); }
    3082         while(go == 1) { do_call(m1); }
    3083 }
    3084 int  __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;
     2886void __attribute__((noinline))
     2887do_call( M & @mutex@ ) {}
     2888void main( T & ) {
     2889        while ( go == 0 ) { yield(); }
     2890        while ( go == 1 ) { do_call( m ); }
     2891}
     2892int __attribute__((noinline))
     2893do_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;
    30952898}
    30962899int main() {
    30972900        T t;
    3098         return do_wait(m1);
    3099 }
    3100 \end{cfa}
    3101 \end{figure}
    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
    3109 Pthreads 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  \\
    3114 Java @notify@                           & 13831.5       & 15698.21      & 4782.3 \\
    3115 \hline
     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
    31162918\end{tabular}
    3117 \end{center}
    3118 \caption{Internal scheduling comparison.
    3119 All numbers are in nanoseconds(\si{\nano\second})}
    3120 \label{tab:int-sched}
    3121 \end{table}
    3122 
    3123 \subsection{External Scheduling}
    3124 The Internal scheduling benchmark measures the cost of the @waitfor@ statement (@_Accept@ in \uC).
    3125 Figure~\ref{f:ext-sched} shows the code for \CFA, with results in table \ref{tab:ext-sched}.
    3126 As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
    3127 
    3128 \begin{figure}
    3129 \begin{cfa}[caption={Benchmark code for external scheduling},label={f:ext-sched}]
     2919\end{multicols}
     2920
     2921
     2922\paragraph{Internal Scheduling}
     2923
     2924Internal scheduling is measured using a cycle of two threads signalling and waiting.
     2925Figure~\ref{f:int-sched} shows the code for \CFA, with results in Table~\ref{tab:int-sched}.
     2926Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
     2927Java 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}
    31302932volatile int go = 0;
    3131 monitor M {};
    3132 M m1;
     2933@monitor@ M { @condition c;@ } m;
     2934void __attribute__((noinline))
     2935do_call( M & @mutex@ a1 ) { @signal( c );@ }
    31332936thread T {};
    3134 
    3135 void __attribute__((noinline)) do_call( M & mutex a1 ) {}
    3136 
    3137 void ^?{}( T & mutex this ) {}
    31382937void main( T & this ) {
    3139         while(go == 0) { yield(); }
    3140         while(go == 1) { do_call(m1); }
    3141 }
    3142 int  __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;
     2938        while ( go == 0 ) { yield(); }
     2939        while ( go == 1 ) { do_call( m ); }
     2940}
     2941int  __attribute__((noinline))
     2942do_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;
    31532947}
    31542948int main() {
    31552949        T t;
    3156         return do_wait(m1);
    3157 }
    3158 \end{cfa}
    3159 \end{figure}
    3160 
    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
     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          \\
     2969Java @notify@                           & 10160.5       & 10169.4       & 267.71        \\
     2970Pthreads Cond. Variable         & 4949.6        & 5065.2        & 363
    31722971\end{tabular}
    3173 \end{center}
    3174 \caption{External scheduling comparison.
    3175 All numbers are in nanoseconds(\si{\nano\second})}
    3176 \label{tab:ext-sched}
    3177 \end{table}
    3178 
    3179 
    3180 \subsection{Object Creation}
    3181 Finally, the last benchmark measures the cost of creation for concurrent objects.
    3182 Figure~\ref{f:creation} shows the code for @pthread@s and \CFA threads, with results shown in table \ref{tab:creation}.
    3183 As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
    3184 The 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}
    3190 int main() {
    3191         BENCH(
    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
    3205         )
    3206         printf("%llu\n", result);
    3207 }
    3208 \end{cfa}
    3209 
    3210 
    3211 
    3212 \CFA Threads
    3213 \begin{cfa}
    3214 int 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
    3235 Pthreads                        & 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   \\
    3241 Goroutine                       & 2520.5        & 2530.93       & 61,56  \\
    3242 Java Thread                     & 91114.5       & 92272.79      & 961.58 \\
    3243 \hline
    3244 \end{tabular}
    3245 \end{center}
    3246 \caption{Creation comparison.
    3247 All numbers are in nanoseconds(\si{\nano\second}).}
    3248 \label{tab:creation}
    3249 \end{table}
    3250 
     2972\end{multicols}
    32512973
    32522974
    32532975\section{Conclusion}
    3254 This paper has achieved a minimal concurrency \textbf{api} that is simple, efficient and usable as the basis for higher-level features.
    3255 The approach presented is based on a lightweight thread-system for parallelism, which sits on top of clusters of processors.
    3256 This M:N model is judged to be both more efficient and allow more flexibility for users.
    3257 Furthermore, this document introduces monitors as the main concurrency tool for users.
    3258 This paper also offers a novel approach allowing multiple monitors to be accessed simultaneously without running into the Nested Monitor Problem~\cite{Lister77}.
    3259 It 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 % ======================================================================
     2976
     2977Advanced control-flow will always be difficult, especially when there is temporal ordering and nondeterminism.
     2978However, many systems exacerbate the difficulty through their presentation mechanisms.
     2979This 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.
     2980Eliminated 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@.
     2982Extending these mechanisms to handle high-level deadlock-free bulk acquire across both mutual exclusion and synchronization is a unique contribution.
     2983The \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.
     2984The M:N model is judged to be efficient and provide greater flexibility than a 1:1 threading model.
     2985These 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.
     2986Performance 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.
     2987C 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
    32642990\section{Future Work}
    3265 % ======================================================================
    3266 % ======================================================================
    3267 
    3268 \subsection{Performance} \label{futur:perf}
    3269 This paper presents a first implementation of the \CFA concurrency runtime.
    3270 Therefore, there is still significant work to improve performance.
    3271 Many of the data structures and algorithms may change in the future to more efficient versions.
    3272 For example, the number of monitors in a single bulk acquire is only bound by the stack size, this is probably unnecessarily generous.
    3273 It may be possible that limiting the number helps increase performance.
    3274 However, it is not obvious that the benefit would be significant.
    3275 
    3276 \subsection{Flexible Scheduling} \label{futur:sched}
     2991
     2992While 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
    32772997An important part of concurrency is scheduling.
    32782998Different scheduling algorithms can affect performance (both in terms of average and variation).
    32792999However, no single scheduler is optimal for all workloads and therefore there is value in being able to change the scheduler for given programs.
    3280 One solution is to offer various tweaking options to users, allowing the scheduler to be adjusted to the requirements of the workload.
    3281 However, in order to be truly flexible, it would be interesting to allow users to add arbitrary data and arbitrary scheduling algorithms.
    3282 For 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.
    3283 This path of flexible schedulers will be explored for \CFA.
    3284 
    3285 \subsection{Non-Blocking I/O} \label{futur:nbio}
    3286 While 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).
    3287 These types of workloads often require significant engineering around amortizing costs of blocking IO operations.
    3288 At 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.
    3289 In this context, the role of the language makes Non-Blocking IO easily available and with low overhead.
    3290 The 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.
    3291 However, 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}
    3294 While monitors offer a flexible and powerful concurrent core for \CFA, other concurrency tools are also necessary for a complete multi-paradigm concurrency package.
    3295 Examples of such tools can include simple locks and condition variables, futures and promises~\cite{promises}, executors and actors.
    3296 These 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}
    3299 Simpler applications can benefit greatly from having implicit parallelism.
    3300 That is, parallelism that does not rely on the user to write concurrency.
    3301 This type of parallelism can be achieved both at the language level and at the library level.
    3302 The canonical example of implicit parallelism is parallel for loops, which are the simplest example of a divide and conquer algorithms~\cite{uC++book}.
    3303 Table \ref{f:parfor} shows three different code examples that accomplish point-wise sums of large arrays.
    3304 Note 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|}
    3309 Sequential & Library Parallel & Language Parallel \\
    3310 \begin{cfa}[tabsize=3]
    3311 void 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 
    3329 int* a[10000];
    3330 int* b[10000];
    3331 int* c[10000];
    3332 //... fill in a & b
    3333 big_sum(a,b,c,10000);
    3334 \end{cfa} &\begin{cfa}[tabsize=3]
    3335 void 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 
    3353 int* a[10000];
    3354 int* b[10000];
    3355 int* c[10000];
    3356 //... fill in a & b
    3357 big_sum(a,b,c,10000);
    3358 \end{cfa}&\begin{cfa}[tabsize=3]
    3359 void 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 
    3377 int* a[10000];
    3378 int* b[10000];
    3379 int* c[10000];
    3380 //... fill in a & b
    3381 big_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 
    3389 Implicit parallelism is a restrictive solution and therefore has its limitations.
    3390 However, 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 % -------------------------------
     3000One solution is to offer various tuning options, allowing the scheduler to be adjusted to the requirements of the workload.
     3001However, to be truly flexible, a pluggable scheduler is necessary.
     3002Currently, 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
     3007Many modern workloads are not bound by computation but IO operations, a common case being web servers and XaaS~\cite{XaaS} (anything as a service).
     3008These types of workloads require significant engineering to amortizing costs of blocking IO-operations.
     3009At 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.
     3010Current 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.
     3011However, these solutions lead to code that is hard to create, read and maintain.
     3012A 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.
     3013A non-blocking I/O library is currently under development for \CFA.
     3014
     3015\paragraph{Other Concurrency Tools}
     3016\label{futur:tools}
     3017
     3018While monitors offer flexible and powerful concurrency for \CFA, other concurrency tools are also necessary for a complete multi-paradigm concurrency package.
     3019Examples of such tools can include futures and promises~\cite{promises}, executors and actors.
     3020These additional features are useful for applications that can be constructed without shared data and direct blocking.
     3021As 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
     3026Basic 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.
     3027This type of concurrency can be achieved both at the language level and at the library level.
     3028The canonical example of implicit concurrency is concurrent nested @for@ loops, which are amenable to divide and conquer algorithms~\cite{uC++book}.
     3029The \CFA language features should make it possible to develop a reasonable number of implicit concurrency mechanism to solve basic HPC data-concurrency problems.
     3030However, implicit concurrency is a restrictive solution with significant limitations, so it can never replace explicit concurrent programming.
     3031
     3032
    33953033\section{Acknowledgements}
    33963034
    3397 Thanks 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.
    3398 Partial 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}
     3035The 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.
     3036Funding 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%
    34043040\bibliography{pl,local}
    3405 
     3041}%
    34063042
    34073043\end{document}
  • doc/papers/concurrency/annex/local.bib

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

    r7951100 rb067d9b  
    88-2
    991200 2
    10 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 3450.000 3150 3150 2850 3450 3150 3750
    11 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 3150.000 4350.000 3150 4050 2850 4350 3150 4650
    12 6 5850 1950 6150 2250
    13 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2100 105 105 6000 2100 6105 2205
    14 4 1 -1 0 0 0 10 0.0000 2 105 90 6000 2160 d\001
     105 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 3600.000 1500 3300 1200 3600 1500 3900
     115 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 4500.000 1500 4200 1200 4500 1500 4800
     126 4200 2100 4500 2400
     131 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2250 105 105 4350 2250 4455 2355
     144 1 -1 0 0 0 10 0.0000 2 105 90 4350 2310 d\001
    1515-6
    16 6 5100 2100 5400 2400
    17 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
    18 4 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
     166 4200 1800 4500 2100
     171 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1950 105 105 4350 1950 4455 2055
     184 1 -1 0 0 0 10 0.0000 2 105 90 4350 2010 b\001
    1919-6
    20 6 5100 1800 5400 2100
    21 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 1950 105 105 5250 1950 5355 1950
    22 4 1 -1 0 0 0 10 0.0000 2 105 120 5250 2010 Y\001
     206 1420 5595 5625 5805
     211 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1500 5700 80 80 1500 5700 1580 5780
     221 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 5700 105 105 2850 5700 2955 5805
     231 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4350 5700 105 105 4350 5700 4455 5805
     244 0 -1 0 0 0 12 0.0000 2 135 1035 3075 5775 blocked task\001
     254 0 -1 0 0 0 12 0.0000 2 135 870 1650 5775 active task\001
     264 0 -1 0 0 0 12 0.0000 2 135 1050 4575 5775 routine mask\001
    2327-6
    24 6 5850 1650 6150 1950
    25 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
    26 4 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
     286 3450 1950 3750 2550
     291 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3600 2100 105 105 3600 2100 3705 2100
     302 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
     324 1 4 0 0 0 10 0.0000 2 105 120 3600 2160 Y\001
    2733-6
    28 6 3070 5445 7275 5655
    29 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3150 5550 80 80 3150 5550 3230 5630
    30 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4500 5550 105 105 4500 5550 4605 5655
    31 1 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 6000 5550 105 105 6000 5550 6105 5655
    32 4 0 -1 0 0 0 12 0.0000 2 135 1035 4725 5625 blocked task\001
    33 4 0 -1 0 0 0 12 0.0000 2 135 870 3300 5625 active task\001
    34 4 0 -1 0 0 0 12 0.0000 2 135 1050 6225 5625 routine mask\001
     346 3450 2250 3750 2550
     351 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3600 2400 105 105 3600 2400 3705 2400
     364 1 4 0 0 0 10 0.0000 2 105 120 3600 2445 X\001
    3537-6
    36 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3300 3600 105 105 3300 3600 3405 3705
    37 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3600 3600 105 105 3600 3600 3705 3705
    38 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6600 3900 105 105 6600 3900 6705 4005
    39 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6900 3900 105 105 6900 3900 7005 4005
    40 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2700 105 105 6000 2700 6105 2805
    41 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 2400 105 105 6000 2400 6105 2505
    42 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 5100 4575 80 80 5100 4575 5180 4655
     381 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1650 3750 105 105 1650 3750 1755 3855
     391 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1950 3750 105 105 1950 3750 2055 3855
     401 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 4050 105 105 4950 4050 5055 4155
     411 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5250 4050 105 105 5250 4050 5355 4155
     421 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2850 105 105 4350 2850 4455 2955
     431 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2550 105 105 4350 2550 4455 2655
     441 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 4725 80 80 3450 4725 3530 4805
    43452 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    44          4050 2925 5475 2925 5475 3225 4050 3225 4050 2925
     46         2400 3075 3825 3075 3825 3375 2400 3375 2400 3075
    45472 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
     48         1500 3900 2100 3900 2100 4200 1500 4200
    47492 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    48          3150 3450 3750 3450 3900 3675
     50         1500 3600 2100 3600 2250 3825
    49512 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    50          3750 3150 3600 3375
     52         2100 3300 1950 3525
    51532 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    52          3150 4350 3750 4350 3900 4575
     54         1500 4500 2100 4500 2250 4725
    53552 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    54          3750 4050 3600 4275
     56         2100 4200 1950 4425
    55572 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
     58         1500 4800 2100 4800 2100 5100 3300 5100
    57592 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    58          6450 3750 6300 3975
     60         4800 3900 4650 4125
    59612 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    60          4950 4950 5175 5100
     62         3300 5100 3525 5250
    61632 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
     64         3600 5100 4800 5100 4800 4200 5400 4200 5400 3900 4800 3900
     65         4800 3000 4500 3000 4500 1800
    64662 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
    66 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
     67         4200 4350 4200 3450 2700 3450 2700 4350 4200 4350
     682 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    6769        1 1 1.00 60.00 120.00
    68         7 1 1.00 60.00 120.00
    69          5250 3150 5250 2400
     70         3600 3225 3600 2550
     712 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
     72         4050 3000 4500 3150
    70732 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
    72 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
    73          5700 2850 6150 3000
    74 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    75          5100 1800 5400 1800 5400 2400 5100 2400 5100 1800
    76 4 1 -1 0 0 0 10 0.0000 2 75 75 6000 2745 a\001
    77 4 1 -1 0 0 0 10 0.0000 2 75 75 6000 2445 c\001
    78 4 1 -1 0 0 0 12 0.0000 2 135 315 5100 5325 exit\001
    79 4 1 -1 0 0 0 12 0.0000 2 135 135 3300 3075 A\001
    80 4 1 -1 0 0 0 12 0.0000 2 135 795 3300 4875 condition\001
    81 4 1 -1 0 0 0 12 0.0000 2 135 135 3300 5100 B\001
    82 4 0 -1 0 0 0 12 0.0000 2 135 420 6600 3675 stack\001
    83 4 0 -1 0 0 0 12 0.0000 2 180 750 6600 3225 acceptor/\001
    84 4 0 -1 0 0 0 12 0.0000 2 180 750 6600 3450 signalled\001
    85 4 1 -1 0 0 0 12 0.0000 2 135 795 3300 2850 condition\001
    86 4 1 -1 0 0 0 12 0.0000 2 165 420 6000 1350 entry\001
    87 4 1 -1 0 0 0 12 0.0000 2 135 495 6000 1575 queue\001
    88 4 0 -1 0 0 0 12 0.0000 2 135 525 6300 2400 arrival\001
    89 4 0 -1 0 0 0 12 0.0000 2 135 630 6300 2175 order of\001
    90 4 1 -1 0 0 0 12 0.0000 2 135 525 5100 3675 shared\001
    91 4 1 -1 0 0 0 12 0.0000 2 135 735 5100 3975 variables\001
    92 4 0 0 50 -1 0 11 0.0000 2 165 855 4275 3150 Acceptables\001
    93 4 0 0 50 -1 0 11 0.0000 2 120 165 5775 2700 W\001
    94 4 0 0 50 -1 0 11 0.0000 2 120 135 5775 2400 X\001
    95 4 0 0 50 -1 0 11 0.0000 2 120 105 5775 2100 Z\001
    96 4 0 0 50 -1 0 11 0.0000 2 120 135 5775 1800 Y\001
     74         1500 3300 2100 3300 2100 3000 4050 3000 4050 1800
     754 1 -1 0 0 0 10 0.0000 2 75 75 4350 2895 a\001
     764 1 -1 0 0 0 10 0.0000 2 75 75 4350 2595 c\001
     774 1 -1 0 0 0 12 0.0000 2 135 315 3450 5475 exit\001
     784 1 -1 0 0 0 12 0.0000 2 135 135 1650 3225 A\001
     794 1 -1 0 0 0 12 0.0000 2 135 795 1650 5025 condition\001
     804 1 -1 0 0 0 12 0.0000 2 135 135 1650 5250 B\001
     814 0 -1 0 0 0 12 0.0000 2 135 420 4950 3825 stack\001
     824 0 -1 0 0 0 12 0.0000 2 180 750 4950 3375 acceptor/\001
     834 0 -1 0 0 0 12 0.0000 2 180 750 4950 3600 signalled\001
     844 1 -1 0 0 0 12 0.0000 2 135 795 1650 3000 condition\001
     854 0 -1 0 0 0 12 0.0000 2 135 525 4650 2550 arrival\001
     864 0 -1 0 0 0 12 0.0000 2 135 630 4650 2325 order of\001
     874 1 -1 0 0 0 12 0.0000 2 135 525 3450 3825 shared\001
     884 1 -1 0 0 0 12 0.0000 2 135 735 3450 4125 variables\001
     894 0 4 50 -1 0 11 0.0000 2 120 135 4075 2025 X\001
     904 0 4 50 -1 0 11 0.0000 2 120 135 4075 2325 Y\001
     914 0 4 50 -1 0 11 0.0000 2 120 135 4075 2625 Y\001
     924 0 4 50 -1 0 11 0.0000 2 120 135 4075 2925 X\001
     934 0 -1 0 0 3 12 0.0000 2 150 540 4950 4425 urgent\001
     944 1 0 50 -1 0 11 0.0000 2 165 600 3075 3300 accepted\001
     954 1 -1 0 0 0 12 0.0000 2 165 960 4275 1725 entry queue\001
  • doc/papers/concurrency/figures/monitor.fig

    r7951100 rb067d9b  
    88-2
    991200 2
    10 5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 2700.000 1500 2400 1200 2700 1500 3000
    11 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
    12 6 4200 1200 4500 1500
    13 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1350 105 105 4350 1350 4455 1455
    14 4 1 -1 0 0 0 10 0.0000 2 105 90 4350 1410 d\001
     105 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 3300.000 1500 3000 1200 3300 1500 3600
     115 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 1500.000 4200.000 1500 3900 1200 4200 1500 4500
     126 1350 5250 5325 5550
     131 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1500 5400 80 80 1500 5400 1580 5480
     141 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 5400 105 105 2850 5400 2955 5505
     151 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4350 5400 105 105 4350 5400 4455 5505
     164 0 -1 0 0 0 12 0.0000 2 180 765 4575 5475 duplicate\001
     174 0 -1 0 0 0 12 0.0000 2 135 1035 3075 5475 blocked task\001
     184 0 -1 0 0 0 12 0.0000 2 135 870 1650 5475 active task\001
    1519-6
    16 6 4200 900 4500 1200
    17 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1050 105 105 4350 1050 4455 1155
    18 4 1 -1 0 0 0 10 0.0000 2 105 90 4350 1110 b\001
     206 4200 1800 4500 2100
     211 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1950 105 105 4350 1950 4455 2055
     224 1 -1 0 0 0 10 0.0000 2 105 90 4350 2010 d\001
    1923-6
    20 6 2400 1500 2700 1800
    21 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 2550 1650 105 105 2550 1650 2655 1650
    22 4 1 -1 0 0 0 10 0.0000 2 105 90 2550 1710 b\001
     246 4200 1500 4500 1800
     251 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1650 105 105 4350 1650 4455 1755
     264 1 -1 0 0 0 10 0.0000 2 105 90 4350 1710 b\001
    2327-6
    24 6 2400 1800 2700 2100
    25 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 2550 1950 105 105 2550 1950 2655 1950
    26 4 1 -1 0 0 0 10 0.0000 2 75 75 2550 1995 a\001
    27 -6
    28 6 3300 1500 3600 1800
    29 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3450 1650 105 105 3450 1650 3555 1650
    30 4 1 -1 0 0 0 10 0.0000 2 105 90 3450 1710 d\001
    31 -6
    32 6 1350 4650 5325 4950
    33 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 1500 4800 80 80 1500 4800 1580 4880
    34 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 2850 4800 105 105 2850 4800 2955 4905
    35 1 3 0 1 -1 -1 0 0 4 0.000 1 0.0000 4350 4800 105 105 4350 4800 4455 4905
    36 4 0 -1 0 0 0 12 0.0000 2 180 765 4575 4875 duplicate\001
    37 4 0 -1 0 0 0 12 0.0000 2 135 1035 3075 4875 blocked task\001
    38 4 0 -1 0 0 0 12 0.0000 2 135 870 1650 4875 active task\001
    39 -6
    40 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1650 2850 105 105 1650 2850 1755 2955
    41 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1950 2850 105 105 1950 2850 2055 2955
    42 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 3150 105 105 4950 3150 5055 3255
    43 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5250 3150 105 105 5250 3150 5355 3255
    44 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1950 105 105 4350 1950 4455 2055
    45 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 1650 105 105 4350 1650 4455 1755
    46 1 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 3825 80 80 3450 3825 3530 3905
    47 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 3450 1950 105 105 3450 1950 3555 1950
     281 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1650 3450 105 105 1650 3450 1755 3555
     291 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 1950 3450 105 105 1950 3450 2055 3555
     301 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4950 3750 105 105 4950 3750 5055 3855
     311 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 5250 3750 105 105 5250 3750 5355 3855
     321 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3450 4425 80 80 3450 4425 3530 4505
     331 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2550 105 105 4350 2550 4455 2655
     341 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4350 2250 105 105 4350 2250 4455 2355
     352 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
     372 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
     392 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
     40         1500 3300 2100 3300 2250 3525
    48412 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    49          2400 2100 2625 2250
     42         2100 3000 1950 3225
     432 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
     44         1500 4200 2100 4200 2250 4425
    50452 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    51          3300 2100 3525 2250
     46         2100 3900 1950 4125
     472 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
    52492 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    53          4200 2100 4425 2250
    54 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 5
    55          1500 2400 2100 2400 2100 2100 2400 2100 2400 1500
     50         4800 3600 4650 3825
     512 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
     52         3300 4800 3525 4950
     532 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
    56552 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    57          1500 3000 2100 3000 2100 3300 1500 3300
    58 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    59          1500 2700 2100 2700 2250 2925
    60 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    61          2100 2400 1950 2625
    62 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    63          1500 3600 2100 3600 2250 3825
    64 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    65          2100 3300 1950 3525
    66 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    67          1500 3900 2100 3900 2100 4200 3300 4200
    68 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    69          4800 3000 4650 3225
    70 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    71          3300 4200 3525 4350
    72 2 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
    74 2 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
     56         3600 2100 3600 2700 4050 2700 4050 1500
    76572 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
    79 2 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    80          4200 3450 4200 2550 2700 2550 2700 3450 4200 3450
    81 4 1 -1 0 0 0 10 0.0000 2 75 75 4350 1995 a\001
    82 4 1 -1 0 0 0 10 0.0000 2 75 75 4350 1695 c\001
    83 4 1 -1 0 0 0 12 0.0000 2 135 315 3450 4575 exit\001
    84 4 1 -1 0 0 0 12 0.0000 2 135 135 1650 2325 A\001
    85 4 1 -1 0 0 0 12 0.0000 2 135 795 1650 4125 condition\001
    86 4 1 -1 0 0 0 12 0.0000 2 135 135 1650 4350 B\001
    87 4 0 -1 0 0 0 12 0.0000 2 135 420 4950 2925 stack\001
    88 4 0 -1 0 0 0 12 0.0000 2 180 750 4950 2475 acceptor/\001
    89 4 0 -1 0 0 0 12 0.0000 2 180 750 4950 2700 signalled\001
    90 4 1 -1 0 0 0 12 0.0000 2 135 795 1650 2100 condition\001
    91 4 1 -1 0 0 0 12 0.0000 2 135 135 2550 1425 X\001
    92 4 1 -1 0 0 0 12 0.0000 2 135 135 3450 1425 Y\001
    93 4 1 -1 0 0 0 12 0.0000 2 165 420 4350 600 entry\001
    94 4 1 -1 0 0 0 12 0.0000 2 135 495 4350 825 queue\001
    95 4 0 -1 0 0 0 12 0.0000 2 135 525 4650 1650 arrival\001
    96 4 0 -1 0 0 0 12 0.0000 2 135 630 4650 1425 order of\001
    97 4 1 -1 0 0 0 12 0.0000 2 135 525 3450 2925 shared\001
    98 4 1 -1 0 0 0 12 0.0000 2 135 735 3450 3225 variables\001
    99 4 1 -1 0 0 0 12 0.0000 2 120 510 3000 975 mutex\001
    100 4 1 -1 0 0 0 10 0.0000 2 75 75 3450 1995 c\001
    101 4 1 -1 0 0 0 12 0.0000 2 135 570 3000 1200 queues\001
     58         3600 4800 4800 4800 4800 3900 5400 3900 5400 3600 4800 3600
     59         4800 2700 4500 2700 4500 1500
     602 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
     61         4050 2700 4500 2850
     624 1 -1 0 0 0 12 0.0000 2 135 315 3450 5175 exit\001
     634 1 -1 0 0 0 12 0.0000 2 135 795 1650 4725 condition\001
     644 1 -1 0 0 0 12 0.0000 2 135 135 1650 4950 B\001
     654 0 -1 0 0 0 12 0.0000 2 135 420 4950 3525 stack\001
     664 0 -1 0 0 0 12 0.0000 2 180 750 4950 3075 acceptor/\001
     674 0 -1 0 0 0 12 0.0000 2 180 750 4950 3300 signalled\001
     684 1 -1 0 0 0 12 0.0000 2 135 525 3450 3525 shared\001
     694 1 -1 0 0 0 12 0.0000 2 135 735 3450 3825 variables\001
     704 0 -1 0 0 3 12 0.0000 2 150 540 4950 4125 urgent\001
     714 1 -1 0 0 0 10 0.0000 2 75 75 4350 2595 a\001
     724 1 -1 0 0 0 10 0.0000 2 75 75 4350 2295 c\001
     734 0 -1 0 0 0 12 0.0000 2 135 525 4650 2250 arrival\001
     744 0 -1 0 0 0 12 0.0000 2 135 630 4650 2025 order of\001
     754 0 4 50 -1 0 11 0.0000 2 120 135 4075 1725 X\001
     764 0 4 50 -1 0 11 0.0000 2 120 135 4075 2025 Y\001
     774 0 4 50 -1 0 11 0.0000 2 120 135 4075 2325 Y\001
     784 0 4 50 -1 0 11 0.0000 2 120 135 4075 2625 X\001
     794 1 -1 0 0 0 12 0.0000 2 165 960 4275 1425 entry queue\001
  • doc/papers/general/.gitignore

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

    r7951100 rb067d9b  
    44Figures = figures
    55Macros = ../AMA/AMA-stix/ama
    6 TeXLIB = .:${Macros}:${Build}:../../bibliography:
     6TeXLIB = .:${Macros}:${Build}:
    77LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    8 BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
     8BibTeX = BIBINPUTS=../../bibliography: && export BIBINPUTS && bibtex
    99
    1010MAKEFLAGS = --no-print-directory # --silent
     
    4646
    4747Paper.zip :
    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
     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
    4950
    5051evaluation.zip :
    51         zip -x evaluation/.gitignore  -x evaluation/timing.xlsx -x evaluation/timing.dat -r evaluation.zip evaluation
     52        zip -x evaluation/.gitignore -x evaluation/timing.xlsx -x evaluation/timing.dat -r evaluation.zip evaluation
    5253
    5354# File Dependencies #
     
    5960        dvips ${Build}/$< -o $@
    6061
    61 ${BASE}.dvi : Makefile ${Build} ${BASE}.out.ps WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    62                 ../../bibliography/pl.bib
     62${BASE}.dvi : Makefile ${BASE}.out.ps ${Macros}/WileyNJD-v2.cls WileyNJD-AMA.bst ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     63                ../../bibliography/pl.bib | ${Build}
    6364        # Must have *.aux file containing citations for bibtex
    6465        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
     
    7576        mkdir -p ${Build}
    7677
    77 ${BASE}.out.ps : ${Build}
     78${BASE}.out.ps : | ${Build}
    7879        ln -fs ${Build}/Paper.out.ps .
    7980
     
    8485        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    8586
    86 %.tex : %.fig ${Build}
     87%.tex : %.fig | ${Build}
    8788        fig2dev -L eepic $< > ${Build}/$@
    8889
    89 %.ps : %.fig ${Build}
     90%.ps : %.fig | ${Build}
    9091        fig2dev -L ps $< > ${Build}/$@
    9192
    92 %.pstex : %.fig ${Build}
     93%.pstex : %.fig | ${Build}
    9394        fig2dev -L pstex $< > ${Build}/$@
    9495        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/general/Paper.tex

    r7951100 rb067d9b  
    11\documentclass[AMA,STIX1COL]{WileyNJD-v2}
     2\setlength\typewidth{170mm}
     3\setlength\textwidth{170mm}
    24
    35\articletype{RESEARCH ARTICLE}%
    46
    5 \received{26 April 2016}
    6 \revised{6 June 2016}
    7 \accepted{6 June 2016}
    8 
     7\received{12 March 2018}
     8\revised{8 May 2018}
     9\accepted{28 June 2018}
     10
     11\setlength\typewidth{168mm}
     12\setlength\textwidth{168mm}
    913\raggedbottom
    1014
     
    187191}
    188192
    189 \title{\texorpdfstring{\protect\CFA : Adding Modern Programming Language Features to C}{Cforall : Adding Modern Programming Language Features to C}}
     193\title{\texorpdfstring{\protect\CFA : Adding modern programming language features to C}{Cforall : Adding modern programming language features to C}}
    190194
    191195\author[1]{Aaron Moss}
    192196\author[1]{Robert Schluntz}
    193 \author[1]{Peter A. Buhr*}
     197\author[1]{Peter A. Buhr}
    194198\authormark{MOSS \textsc{et al}}
    195199
    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}}
     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}}
    199203
    200204\fundingInfo{Natural Sciences and Engineering Research Council of Canada}
    201205
    202206\abstract[Summary]{
    203 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.
    204 This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    205 Nevertheless, C, first standardized almost forty years ago, lacks many features that make programming in more modern languages safer and more productive.
    206 
    207 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 backwards compatibility with C and its programmers.
    208 Prior projects have attempted similar goals but failed to honour C programming-style;
    209 for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers.
    210 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.
    211 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.
    212 Finally, experimental results are presented to validate several of the new features.
     207The 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.
     208This installation base and the programmers producing it represent a massive software engineering investment spanning decades and likely to continue for decades more.
     209Nevertheless, C, which was first standardized almost 30 years ago, lacks many features that make programming in more modern languages safer and more productive.
     210The 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.
     211Prior projects have attempted similar goals but failed to honor the C programming style;
     212for instance, adding object-oriented or functional programming with garbage collection is a nonstarter for many C developers.
     213Specifically, \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.
     214This paper presents a quick tour of \CFA features, showing how their design avoids shortcomings of similar features in C and other C-like languages.
     215Experimental results are presented to validate several of the new features.
    213216}%
    214217
    215 \keywords{generic types, tuple types, variadic types, polymorphic functions, C, Cforall}
     218\keywords{C, Cforall, generic types, polymorphic functions, tuple types, variadic types}
    216219
    217220
    218221\begin{document}
    219 \linenumbers                                            % comment out to turn off line numbering
     222%\linenumbers                                            % comment out to turn off line numbering
    220223
    221224\maketitle
    222225
    223226
     227\vspace*{-10pt}
    224228\section{Introduction}
    225229
    226 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.
    227 This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    228 The 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.
    229 The top 3 rankings over the past 30 years are:
     230The 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.
     231This installation base and the programmers producing it represent a massive software engineering investment spanning decades and likely to continue for decades more.
     232The 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.
     233The top three rankings over the past 30 years are as follows.
    230234\begin{center}
    231235\setlength{\tabcolsep}{10pt}
    232 \lstDeleteShortInline@%
    233 \begin{tabular}{@{}rccccccc@{}}
    234                 & 2018  & 2013  & 2008  & 2003  & 1998  & 1993  & 1988  \\ \hline
    235 Java    & 1             & 2             & 1             & 1             & 18    & -             & -             \\
     236\fontsize{9bp}{11bp}\selectfont
     237\lstDeleteShortInline@%
     238\begin{tabular}{@{}cccccccc@{}}
     239                & 2018  & 2013  & 2008  & 2003  & 1998  & 1993  & 1988  \\
     240Java    & 1             & 2             & 1             & 1             & 18    & --    & --    \\
    236241\Textbf{C}& \Textbf{2} & \Textbf{1} & \Textbf{2} & \Textbf{2} & \Textbf{1} & \Textbf{1} & \Textbf{1} \\
    237242\CC             & 3             & 4             & 3             & 3             & 2             & 2             & 5             \\
     
    241246Love it or hate it, C is extremely popular, highly used, and one of the few systems languages.
    242247In many cases, \CC is often used solely as a better C.
    243 Nevertheless, 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.
    246 The 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.
    251 These 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 
    254 All languages features discussed in this paper are working, except some advanced exception-handling features.
    255 Not discussed in this paper are the integrated concurrency-constructs and user-level threading-library~\cite{Delisle18}.
     248Nevertheless, 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.
     251The 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.
     256These 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
     259All language features discussed in this paper are working, except some advanced exception-handling features.
     260Not discussed in this paper are the integrated concurrency constructs and user-level threading library~\cite{Delisle18}.
    256261\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).
    257 Ultimately, a compiler is necessary for advanced features and optimal performance.
    258262% @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
    259263% -------------------------------------------------------------------------------
     
    270274% SUM:                           223           8203           8263          46479
    271275% -------------------------------------------------------------------------------
    272 The \CFA translator is 200+ files and 46,000+ lines of code written in C/\CC.
    273 Starting 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.
    274 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.
    275 At the heart of the translator is the type resolver, which handles the polymorphic function/type overload-resolution.
     276The \CFA translator is 200+ files and 46\,000+ lines of code written in C/\CC.
     277A 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;
     278ultimately, 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.
     280Two 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.
     281Details 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.
    276282% @plg2[8]% cd cfa-cc/src; cloc libcfa
    277283% -------------------------------------------------------------------------------
     
    288294% SUM:                           100           1895           2785          11763
    289295% -------------------------------------------------------------------------------
    290 The \CFA runtime system is 100+ files and 11,000+ lines of code, written in \CFA.
     296The \CFA runtime system is 100+ files and 11\,000+ lines of code, written in \CFA.
    291297Currently, the \CFA runtime is the largest \emph{user} of \CFA providing a vehicle to test the language features and implementation.
    292298% @plg2[6]% cd cfa-cc/src; cloc tests examples benchmark
     
    305311% SUM:                           290          13175           3400          27776
    306312% -------------------------------------------------------------------------------
    307 The \CFA tests are 290+ files and 27,000+ lines of code.
    308 The tests illustrate syntactic and semantic features in \CFA, plus a growing number of runtime benchmarks.
    309 The tests check for correctness and are used for daily regression testing of 3800+ commits.
    310 
    311 Finally, it is impossible to describe a programming language without usages before definitions.
    312 Therefore, syntax and semantics appear before explanations, and related work (Section~\ref{s:RelatedWork}) is deferred until \CFA is presented;
    313 hence, patience is necessary until details are discussed.
    314 
    315 
     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
     317Finally, it is impossible to describe a programming language without usage before definition.
     318Therefore, syntax and semantics appear before explanations;
     319hence, patience is necessary until sufficient details are presented and discussed.
     320Similarly, a detailed comparison with other programming languages is postponed until Section~\ref{s:RelatedWork}.
     321
     322
     323\vspace*{-6pt}
    316324\section{Polymorphic Functions}
    317325
    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}.
    319 Shortcomings are identified in existing approaches to generic and variadic data types in C-like languages and how these shortcomings are avoided in \CFA.
    320 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.
     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}.
     327Shortcomings are identified in the existing approaches to generic and variadic data types in C-like languages and how these shortcomings are avoided in \CFA.
     328Specifically, 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.
    321329The new constructs are empirically compared with C and \CC approaches via performance experiments in Section~\ref{sec:eval}.
    322330
    323331
    324 \subsection{Name Overloading}
     332\vspace*{-6pt}
     333\subsection{Name overloading}
    325334\label{s:NameOverloading}
    326335
    327336\begin{quote}
    328 There are only two hard things in Computer Science: cache invalidation and \emph{naming things} -- Phil Karlton
     337``There are only two hard things in Computer Science: cache invalidation and \emph{naming things}.''---Phil Karlton
    329338\end{quote}
    330339\vspace{-9pt}
    331 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.
     340C 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.
    332341\CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable;
    333342Section~\ref{sec:libraries} includes a number of examples of how this overloading simplifies \CFA programming relative to C.
    334343Code 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.
    335 As an example:
     344
     345\newpage
    336346\begin{cfa}
    337347int max = 2147483647;                                           $\C[4in]{// (1)}$
     
    339349int max( int a, int b ) { return a < b ? b : a; }  $\C{// (3)}$
    340350double max( double a, double b ) { return a < b ? b : a; }  $\C{// (4)}\CRT$
    341 max( 7, -max );                                         $\C{// uses (3) and (1), by matching int from constant 7}$
     351max( 7, -max );                                         $\C[3in]{// uses (3) and (1), by matching int from constant 7}$
    342352max( max, 3.14 );                                       $\C{// uses (4) and (2), by matching double from constant 3.14}$
    343353max( max, -max );                                       $\C{// ERROR, ambiguous}$
    344 int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}$
     354int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}\CRT$
    345355\end{cfa}
    346356
     
    348358In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction.
    349359In the above, the name @max@ has a consistent meaning, and a programmer only needs to remember the single concept: maximum.
    350 To 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).
     360To 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).
    351361As 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.
    352362
    353 \Celeven added @_Generic@ expressions~\cite[\S~6.5.1.1]{C11}, which is used with preprocessor macros to provide ad-hoc polymorphism;
     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;
    354364however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading.
    355 The 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@.
     365The 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@.
    357366Ergonomic 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.
    358 \CFA supports @_Generic@ expressions for backwards compatibility, but it is an unnecessary mechanism. \TODO{actually implement that}
     367\CFA supports @_Generic@ expressions for backward compatibility, but it is an unnecessary mechanism.
    359368
    360369% http://fanf.livejournal.com/144696.html
     
    363372
    364373
    365 \subsection{\texorpdfstring{\protect\lstinline{forall} Functions}{forall Functions}}
     374\vspace*{-10pt}
     375\subsection{\texorpdfstring{\protect\lstinline{forall} functions}{forall functions}}
    366376\label{sec:poly-fns}
    367377
    368 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):
     378The 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).
    369379\begin{cfa}
    370380`forall( otype T )` T identity( T val ) { return val; }
     
    373383This @identity@ function can be applied to any complete \newterm{object type} (or @otype@).
    374384The 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.
    375 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.
    376 If this extra information is not needed, \eg for a pointer, the type parameter can be declared as a \newterm{data type} (or @dtype@).
    377 
    378 In \CFA, the polymorphic runtime-cost is spread over each polymorphic call, because more arguments are passed to polymorphic functions;
    379 the experiments in Section~\ref{sec:eval} show this overhead is similar to \CC virtual-function calls.
    380 A design advantage is that, unlike \CC template-functions, \CFA polymorphic-functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat.
    381 
    382 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.
    383 For example, the function @twice@ can be defined using the \CFA syntax for operator overloading:
     385The \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.
     386If 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
     388In \CFA, the polymorphic runtime cost is spread over each polymorphic call, because more arguments are passed to polymorphic functions;
     389the experiments in Section~\ref{sec:eval} show this overhead is similar to \CC virtual function calls.
     390A design advantage is that, unlike \CC template functions, \CFA polymorphic functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat.
     391
     392Since 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.
     393For example, the function @twice@ can be defined using the \CFA syntax for operator overloading.
    384394\begin{cfa}
    385395forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x `+` x; }  $\C{// ? denotes operands}$
    386396int val = twice( twice( 3.7 ) );  $\C{// val == 14}$
    387397\end{cfa}
    388 which works for any type @T@ with a matching addition operator.
    389 The 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@.
    390 There 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.
    391 The 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.
     398This works for any type @T@ with a matching addition operator.
     399The 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@.
     400There 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.
     401The 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;
     403hence, it selects the first approach, which corresponds with C programmer intuition.
    393404
    394405Crucial to the design of a new programming language are the libraries to access thousands of external software features.
    395 Like \CC, \CFA inherits a massive compatible library-base, where other programming languages must rewrite or provide fragile inter-language communication with C.
    396 A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array:
     406Like \CC, \CFA inherits a massive compatible library base, where other programming languages must rewrite or provide fragile interlanguage communication with C.
     407A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array.
    397408\begin{cfa}
    398409void * bsearch( const void * key, const void * base, size_t nmemb, size_t size,
     
    404415double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); $\C{// search sorted array}$
    405416\end{cfa}
    406 which can be augmented simply with generalized, type-safe, \CFA-overloaded wrappers:
     417This can be augmented simply with generalized, type-safe, \CFA-overloaded wrappers.
    407418\begin{cfa}
    408419forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
     
    418429\end{cfa}
    419430The nested function @comp@ provides the hidden interface from typed \CFA to untyped (@void *@) C, plus the cast of the result.
    420 Providing a hidden @comp@ function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
    421 As 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@.
     431% FIX
     432Providing a hidden @comp@ function in \CC is awkward as lambdas do not use C calling conventions and template declarations cannot appear in block scope.
     433In 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@.
    423435
    424436\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}).
     
    430442\end{cfa}
    431443
    432 Call-site inferencing and nested functions provide a localized form of inheritance.
     444Call site inferencing and nested functions provide a localized form of inheritance.
    433445For example, the \CFA @qsort@ only sorts in ascending order using @<@.
    434 However, it is trivial to locally change this behaviour:
     446However, it is trivial to locally change this behavior.
    435447\begin{cfa}
    436448forall( otype T | { int ?<?( T, T ); } ) void qsort( const T * arr, size_t size ) { /* use C qsort */ }
    437449int main() {
    438         int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behaviour}$
     450        int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behavior}$
    439451        qsort( vals, 10 );                                                      $\C{// descending sort}$
    440452}
    441453\end{cfa}
    442454The local version of @?<?@ performs @?>?@ overriding the built-in @?<?@ so it is passed to @qsort@.
    443 Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types.
    444 
    445 To 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}).
     455Therefore, programmers can easily form local environments, adding and modifying appropriate functions, to maximize the reuse of other existing functions and types.
     456
     457To 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}).
    446458\begin{cfa}
    447459forall( otype `T` ) {                                                   $\C{// distribution block, add forall qualifier to declarations}$
     
    454466
    455467
    456 \vspace*{-2pt}
    457468\subsection{Traits}
    458469
    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 
     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.
    461471\begin{cquote}
    462472\lstDeleteShortInline@%
     
    485495\end{cquote}
    486496
    487 Note, the @sumable@ trait does not include a copy constructor needed for the right side of @?+=?@ and return;
    488 it is provided by @otype@, which is syntactic sugar for the following trait:
     497Note that the @sumable@ trait does not include a copy constructor needed for the right side of @?+=?@ and return;
     498it is provided by @otype@, which is syntactic sugar for the following trait.
    489499\begin{cfa}
    490500trait otype( dtype T | sized(T) ) {  // sized is a pseudo-trait for types with known size and alignment
     
    495505};
    496506\end{cfa}
    497 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.
    498 
    499 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.
     507Given 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
     509In 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.
    500510Hence, trait names play no part in type equivalence;
    501511the names are simply macros for a list of polymorphic assertions, which are expanded at usage sites.
    502 Nevertheless, trait names form a logical subtype-hierarchy with @dtype@ at the top, where traits often contain overlapping assertions, \eg operator @+@.
    503 Traits are used like interfaces in Java or abstract base-classes in \CC, but without the nominal inheritance-relationships.
    504 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 Go~\cite{Go} interfaces.
    505 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.
     512Nevertheless, trait names form a logical subtype hierarchy with @dtype@ at the top, where traits often contain overlapping assertions, \eg operator @+@.
     513Traits are used like interfaces in Java or abstract base classes in \CC, but without the nominal inheritance relationships.
     514Instead, 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.
     515Hence, 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.
    506516% (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.)
    507517
     
    534544
    535545A significant shortcoming of standard C is the lack of reusable type-safe abstractions for generic data structures and algorithms.
    536 Broadly speaking, there are three approaches to implement abstract data-structures in C.
    537 One approach is to write bespoke data-structures for each context in which they are needed.
    538 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.
    539 A 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.
    540 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 not otherwise needed.
    541 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.
     546Broadly speaking, there are three approaches to implement abstract data structures in C.
     547One approach is to write bespoke data structures for each context in which they are needed.
     548While 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.
     549A 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.
     550However, 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.
     551A 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.
    542552Furthermore, writing and using preprocessor macros is unnatural and inflexible.
    543553
    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.
     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.
    546556However, for known concrete parameters, the generic-type definition can be inlined, like \CC templates.
    547557
    548 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:
     558A 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.
    549559\begin{cquote}
    550560\lstDeleteShortInline@%
     
    574584
    575585\CFA classifies generic types as either \newterm{concrete} or \newterm{dynamic}.
    576 Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters.
     586Concrete types have a fixed memory layout regardless of type parameters, whereas dynamic types vary in memory layout depending on their type parameters.
    577587A \newterm{dtype-static} type has polymorphic parameters but is still concrete.
    578588Polymorphic pointers are an example of dtype-static types;
    579 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.
    580 
    581 \CFA generic types also allow checked argument-constraints.
    582 For example, the following declaration of a sorted set-type ensures the set key supports equality and relational comparison:
     589given 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.
     592For example, the following declaration of a sorted set type ensures the set key supports equality and relational comparison.
    583593\begin{cfa}
    584594forall( otype Key | { _Bool ?==?(Key, Key); _Bool ?<?(Key, Key); } ) struct sorted_set;
     
    586596
    587597
    588 \subsection{Concrete Generic-Types}
    589 
    590 The \CFA translator template-expands concrete generic-types into new structure types, affording maximal inlining.
    591 To 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.
    592 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.
    593 For example, the concrete instantiation for @pair( const char *, int )@ is:
     598\subsection{Concrete generic types}
     599
     600The \CFA translator template expands concrete generic types into new structure types, affording maximal inlining.
     601To 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.
     602A 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.
     603For example, the concrete instantiation for @pair( const char *, int )@ is
    594604\begin{cfa}
    595605struct _pair_conc0 {
     
    598608\end{cfa}
    599609
    600 A concrete generic-type with dtype-static parameters is also expanded to a structure type, but this type is used for all matching instantiations.
    601 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:
     610A concrete generic type with dtype-static parameters is also expanded to a structure type, but this type is used for all matching instantiations.
     611In 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.
    602612\begin{cfa}
    603613struct _pair_conc1 {
     
    607617
    608618
    609 \subsection{Dynamic Generic-Types}
    610 
    611 Though \CFA implements concrete generic-types efficiently, it also has a fully general system for dynamic generic types.
    612 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.
    613 Dynamic generic-types also have an \newterm{offset array} containing structure-member offsets.
    614 A dynamic generic-@union@ needs no such offset array, as all members are at offset 0, but size and alignment are still necessary.
    615 Access 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.
     619\subsection{Dynamic generic types}
     620
     621Though \CFA implements concrete generic types efficiently, it also has a fully general system for dynamic generic types.
     622As 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.
     623Dynamic generic types also have an \newterm{offset array} containing structure-member offsets.
     624A dynamic generic @union@ needs no such offset array, as all members are at offset 0, but size and alignment are still necessary.
     625Access to members of a dynamic structure is provided at runtime via base displacement addressing
     626% FIX
     627using the structure pointer and the member offset (similar to the @offsetof@ macro), moving a compile-time offset calculation to runtime.
    616628
    617629The offset arrays are statically generated where possible.
    618 If 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;
     630If 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;
    619631if 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.
    620 As an example, the body of the second @value@ function is implemented as:
     632As an example, the body of the second @value@ function is implemented as
    621633\begin{cfa}
    622634_assign_T( _retval, p + _offsetof_pair[1] ); $\C{// return *p.second}$
    623635\end{cfa}
    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:
     636\newpage
     637\noindent
     638Here, @_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@;
     640this array is generated at the call site as
    626641\begin{cfa}
    627642size_t _offsetof_pair[] = { offsetof( _pair_conc0, first ), offsetof( _pair_conc0, second ) }
    628643\end{cfa}
    629644
    630 In some cases the offset arrays cannot be statically generated.
    631 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.
    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.
     645In some cases, the offset arrays cannot be statically generated.
     646For 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.
    633648The \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.
    634649These 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).
     
    640655Whether a type is concrete, dtype-static, or dynamic is decided solely on the @forall@'s type parameters.
    641656This 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.
    642 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}.), but preserving separate compilation (and the associated C compatibility) in the existing design is judged to be an appropriate trade-off.
     657If 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}.);
     658however, preserving separate compilation (and the associated C compatibility) in the existing design is judged to be an appropriate trade-off.
    643659
    644660
     
    653669}
    654670\end{cfa}
    655 Since @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 
    657 Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \newterm{tag-structures}.
    658 Sometimes information is only used for type-checking and can be omitted at runtime, \eg:
     671Since @pair( T *, T * )@ is a concrete type, there are no implicit parameters passed to @lexcmp@;
     672hence, 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
     674Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \newterm{tag structures}.
     675Sometimes, information is only used for type checking and can be omitted at runtime.
    659676\begin{cquote}
    660677\lstDeleteShortInline@%
     
    675692                                                        half_marathon;
    676693scalar(litres) two_pools = pool + pool;
    677 `marathon + pool;`      // ERROR, mismatched types
     694`marathon + pool;` // ERROR, mismatched types
    678695\end{cfa}
    679696\end{tabular}
    680697\lstMakeShortInline@%
    681698\end{cquote}
    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 @?+?@.
     699Here, @scalar@ is a dtype-static type;
     700hence, all uses have a single structure definition, containing @unsigned long@, and can share the same implementations of common functions like @?+?@.
    683701These implementations may even be separately compiled, unlike \CC template functions.
    684 However, the \CFA type-checker ensures matching types are used by all calls to @?+?@, preventing nonsensical computations like adding a length to a volume.
     702However, the \CFA type checker ensures matching types are used by all calls to @?+?@, preventing nonsensical computations like adding a length to a volume.
    685703
    686704
     
    688706\label{sec:tuples}
    689707
    690 In many languages, functions can return at most one value;
     708In many languages, functions can return, at most, one value;
    691709however, many operations have multiple outcomes, some exceptional.
    692710Consider C's @div@ and @remquo@ functions, which return the quotient and remainder for a division of integer and float values, respectively.
     
    699717double r = remquo( 13.5, 5.2, &q );                     $\C{// return remainder, alias quotient}$
    700718\end{cfa}
    701 @div@ aggregates the quotient/remainder in a structure, while @remquo@ aliases a parameter to an argument.
     719Here, @div@ aggregates the quotient/remainder in a structure, whereas @remquo@ aliases a parameter to an argument.
    702720Both approaches are awkward.
    703 Alternatively, a programming language can directly support returning multiple values, \eg in \CFA:
     721% FIX
     722Alternatively, a programming language can directly support returning multiple values, \eg \CFA provides the following.
    704723\begin{cfa}
    705724[ int, int ] div( int num, int den );           $\C{// return two integers}$
     
    712731This approach is straightforward to understand and use;
    713732therefore, why do few programming languages support this obvious feature or provide it awkwardly?
    714 To answer, there are complex consequences that cascade through multiple aspects of the language, especially the type-system.
    715 This section show these consequences and how \CFA handles them.
     733To answer, there are complex consequences that cascade through multiple aspects of the language, especially the type system.
     734This section shows these consequences and how \CFA handles them.
    716735
    717736
    718737\subsection{Tuple Expressions}
    719738
    720 The addition of multiple-return-value functions (MRVF) are \emph{useless} without a syntax for accepting multiple values at the call-site.
     739The addition of multiple-return-value functions (MRVFs) is \emph{useless} without a syntax for accepting multiple values at the call site.
    721740The simplest mechanism for capturing the return values is variable assignment, allowing the values to be retrieved directly.
    722741As 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}.
    723742
    724 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 (SRVF), \eg:
     743However, 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.
    725744\begin{cfa}
    726745printf( "%d %d\n", div( 13, 5 ) );                      $\C{// return values seperated into arguments}$
    727746\end{cfa}
    728747Here, the values returned by @div@ are composed with the call to @printf@ by flattening the tuple into separate arguments.
    729 However, the \CFA type-system must support significantly more complex composition:
     748However, the \CFA type-system must support significantly more complex composition.
    730749\begin{cfa}
    731750[ int, int ] foo$\(_1\)$( int );                        $\C{// overloaded foo functions}$
     
    734753`bar`( foo( 3 ), foo( 3 ) );
    735754\end{cfa}
    736 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.
    737 No combination of @foo@s are an exact match with @bar@'s parameters, so the resolver applies C conversions.
     755The 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.
     756No combination of @foo@s is an exact match with @bar@'s parameters;
     757thus, the resolver applies C conversions.
     758% FIX
    738759The 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.
    739760
    740761
    741 \subsection{Tuple Variables}
     762\subsection{Tuple variables}
    742763
    743764An important observation from function composition is that new variable names are not required to initialize parameters from an MRVF.
    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:
     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
    745767\begin{cfa}
    746768[ int, int ] qr = div( 13, 5 );                         $\C{// tuple-variable declaration and initialization}$
    747769[ double, double ] qr = div( 13.5, 5.2 );
    748770\end{cfa}
    749 where the tuple variable-name serves the same purpose as the parameter name(s).
     771Here, the tuple variable name serves the same purpose as the parameter name(s).
    750772Tuple variables can be composed of any types, except for array types, since array sizes are generally unknown in C.
    751773
    752 One way to access the tuple-variable components is with assignment or composition:
     774One way to access the tuple variable components is with assignment or composition.
    753775\begin{cfa}
    754776[ q, r ] = qr;                                                          $\C{// access tuple-variable components}$
    755777printf( "%d %d\n", qr );
    756778\end{cfa}
    757 \CFA also supports \newterm{tuple indexing} to access single components of a tuple expression:
     779\CFA also supports \newterm{tuple indexing} to access single components of a tuple expression.
    758780\begin{cfa}
    759781[int, int] * p = &qr;                                           $\C{// tuple pointer}$
     
    766788
    767789
    768 \subsection{Flattening and Restructuring}
     790\subsection{Flattening and restructuring}
    769791
    770792In function call contexts, tuples support implicit flattening and restructuring conversions.
    771793Tuple flattening recursively expands a tuple into the list of its basic components.
    772 Tuple structuring packages a list of expressions into a value of tuple type, \eg:
     794Tuple structuring packages a list of expressions into a value of tuple type.
    773795\begin{cfa}
    774796int f( int, int );
     
    781803h( x, y );                                                                      $\C{// flatten and structure}$
    782804\end{cfa}
    783 In the call to @f@, @x@ is implicitly flattened so the components of @x@ are passed as the two arguments.
     805In the call to @f@, @x@ is implicitly flattened so the components of @x@ are passed as two arguments.
    784806In 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@.
    785807Finally, 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]@.
    786 The 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 
     808The 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}
    791814An assignment where the left side is a tuple type is called \newterm{tuple assignment}.
    792 There 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.
     815There 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.
    793816\begin{cfa}
    794817int x = 10;
     
    800823[y, x] = 3.14;                                                          $\C{// mass assignment}$
    801824\end{cfa}
    802 Both kinds of tuple assignment have parallel semantics, so that each value on the left and right side is evaluated before any assignments occur.
     825Both kinds of tuple assignment have parallel semantics, so that each value on the left and right sides is evaluated before any assignments occur.
    803826As 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]@.
    804827This 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.
    805 For example, @[y, x] = 3.14@ performs the assignments @y = 3.14@ and @x = 3.14@, yielding @y == 3.14@ and @x == 3@;
    806 whereas, C cascading assignment @y = x = 3.14@ performs the assignments @x = 3.14@ and @y = x@, yielding @3@ in @y@ and @x@.
     828For 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@.
    807829Finally, 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.
    808 This example shows mass, multiple, and cascading assignment used in one expression:
     830This example shows mass, multiple, and cascading assignment used in one expression.
    809831\begin{cfa}
    810832[void] f( [int, int] );
     
    813835
    814836
    815 \subsection{Member Access}
    816 
    817 It is also possible to access multiple members from a single expression using a \newterm{member-access}.
    818 The result is a single tuple-valued expression whose type is the tuple of the types of the members, \eg:
     837\subsection{Member access}
     838
     839It is also possible to access multiple members from a single expression using a \newterm{member access}.
     840The result is a single tuple-valued expression whose type is the tuple of the types of the members.
    819841\begin{cfa}
    820842struct S { int x; double y; char * z; } s;
     
    830852[int, int, int] y = x.[2, 0, 2];                        $\C{// duplicate: [y.0, y.1, y.2] = [x.2, x.0.x.2]}$
    831853\end{cfa}
    832 It is also possible for a member access to contain other member accesses, \eg:
     854It is also possible for a member access to contain other member accesses.
    833855\begin{cfa}
    834856struct A { double i; int j; };
     
    897919
    898920Tuples also integrate with \CFA polymorphism as a kind of generic type.
    899 Due 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:
     921Due to the implicit flattening and structuring conversions involved in argument passing, @otype@ and @dtype@ parameters are restricted to matching only with nontuple types.
    900922\begin{cfa}
    901923forall( otype T, dtype U ) void f( T x, U * y );
    902924f( [5, "hello"] );
    903925\end{cfa}
    904 where @[5, "hello"]@ is flattened, giving argument list @5, "hello"@, and @T@ binds to @int@ and @U@ binds to @const char@.
     926Here, @[5, "hello"]@ is flattened, giving argument list @5, "hello"@, and @T@ binds to @int@ and @U@ binds to @const char@.
    905927Tuples, however, may contain polymorphic components.
    906928For example, a plus operator can be written to sum two triples.
     
    920942g( 5, 10.21 );
    921943\end{cfa}
     944\newpage
    922945Hence, function parameter and return lists are flattened for the purposes of type unification allowing the example to pass expression resolution.
    923946This relaxation is possible by extending the thunk scheme described by Bilson~\cite{Bilson03}.
     
    930953
    931954
    932 \subsection{Variadic Tuples}
     955\subsection{Variadic tuples}
    933956\label{sec:variadic-tuples}
    934957
    935 To define variadic functions, \CFA adds a new kind of type parameter, @ttype@ (tuple type).
    936 Matching against a @ttype@ parameter consumes all remaining argument components and packages them into a tuple, binding to the resulting tuple of types.
    937 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.
     958To define variadic functions, \CFA adds a new kind of type parameter, \ie @ttype@ (tuple type).
     959Matching against a @ttype@ parameter consumes all the remaining argument components and packages them into a tuple, binding to the resulting tuple of types.
     960In 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.
    938961As such, @ttype@ variables are also called \newterm{argument packs}.
    939962
     
    941964Since nothing is known about a parameter pack by default, assertion parameters are key to doing anything meaningful.
    942965Unlike variadic templates, @ttype@ polymorphic functions can be separately compiled.
    943 For example, a generalized @sum@ function:
     966For example, the following is a generalized @sum@ function.
    944967\begin{cfa}
    945968int sum$\(_0\)$() { return 0; }
     
    950973\end{cfa}
    951974Since @sum@\(_0\) does not accept any arguments, it is not a valid candidate function for the call @sum(10, 20, 30)@.
    952 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]@.
     975In 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]@.
    953976The process continues until @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.
    954977Effectively, 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))@.
    955978
    956 It is reasonable to take the @sum@ function a step further to enforce a minimum number of arguments:
     979It is reasonable to take the @sum@ function a step further to enforce a minimum number of arguments.
    957980\begin{cfa}
    958981int sum( int x, int y ) { return x + y; }
     
    961984}
    962985\end{cfa}
    963 One more step permits the summation of any sumable type with all arguments of the same type:
     986One more step permits the summation of any sumable type with all arguments of the same type.
    964987\begin{cfa}
    965988trait sumable( otype T ) {
     
    9901013This example showcases a variadic-template-like decomposition of the provided argument list.
    9911014The individual @print@ functions allow printing a single element of a type.
    992 The polymorphic @print@ allows printing any list of types, where as each individual type has a @print@ function.
     1015The polymorphic @print@ allows printing any list of types, where each individual type has a @print@ function.
    9931016The individual print functions can be used to build up more complicated @print@ functions, such as @S@, which cannot be done with @printf@ in C.
    9941017This mechanism is used to seamlessly print tuples in the \CFA I/O library (see Section~\ref{s:IOLibrary}).
    9951018
    9961019Finally, it is possible to use @ttype@ polymorphism to provide arbitrary argument forwarding functions.
    997 For example, it is possible to write @new@ as a library function:
     1020For example, it is possible to write @new@ as a library function.
    9981021\begin{cfa}
    9991022forall( otype R, otype S ) void ?{}( pair(R, S) *, R, S );
     
    10041027\end{cfa}
    10051028The @new@ function provides the combination of type-safe @malloc@ with a \CFA constructor call, making it impossible to forget constructing dynamically allocated objects.
    1006 This function provides the type-safety of @new@ in \CC, without the need to specify the allocated type again, thanks to return-type inference.
     1029This function provides the type safety of @new@ in \CC, without the need to specify the allocated type again, due to return-type inference.
    10071030
    10081031
     
    10101033
    10111034Tuples are implemented in the \CFA translator via a transformation into \newterm{generic types}.
    1012 For each $N$, the first time an $N$-tuple is seen in a scope a generic type with $N$ type parameters is generated, \eg:
     1035For each $N$, the first time an $N$-tuple is seen in a scope, a generic type with $N$ type parameters is generated.
     1036For example, the following
    10131037\begin{cfa}
    10141038[int, int] f() {
     
    10171041}
    10181042\end{cfa}
    1019 is transformed into:
     1043is transformed into
    10201044\begin{cfa}
    10211045forall( dtype T0, dtype T1 | sized(T0) | sized(T1) ) struct _tuple2 {
     
    10831107
    10841108The various kinds of tuple assignment, constructors, and destructors generate GNU C statement expressions.
    1085 A 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.
     1109A 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.
    10861110The 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.
    10871111However, 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.
     
    10911115\section{Control Structures}
    10921116
    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 
    1098 The @if@ expression allows declarations, similar to @for@ declaration expression:
     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
     1122The @if@ expression allows declarations, similar to the @for@ declaration expression.
    10991123\begin{cfa}
    11001124if ( int x = f() ) ...                                          $\C{// x != 0}$
     
    11031127\end{cfa}
    11041128Unless 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.}
    1105 The 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}}
     1129The 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}}
    11091133
    11101134There 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.
    11111135
    1112 C 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:
     1136C 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:
    11141138\begin{cquote}
    11151139\lstDeleteShortInline@%
     
    11261150\lstMakeShortInline@%
    11271151\end{cquote}
    1128 for 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.}
     1152for a contiguous list:\footnote{gcc has the same mechanism but awkward syntax, \lstinline@2 ...42@, as a space is required after a number;
     1153otherwise, the first period is a decimal point.}
    11291154\begin{cquote}
    11301155\lstDeleteShortInline@%
     
    11571182}
    11581183\end{cfa}
    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 
    1161 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour:
     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
     1186C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in an undefined behavior.
    11621187\begin{cfa}
    11631188switch ( x ) {
     
    11761201
    11771202C @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};
    1178 @case@ clauses are made disjoint by the @break@ statement.
     1203@case@ clauses are made disjoint by the @break@
     1204\newpage
     1205\noindent
     1206statement.
    11791207While 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.
    1180 For 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.
     1208For 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.
    11811209
    11821210\begin{figure}
    11831211\centering
     1212\fontsize{9bp}{11bp}\selectfont
    11841213\lstDeleteShortInline@%
    11851214\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     
    12181247\end{tabular}
    12191248\lstMakeShortInline@%
    1220 \caption{\lstinline|choose| versus \lstinline|switch| Statements}
     1249\caption{\lstinline|choose| versus \lstinline|switch| statements}
    12211250\label{f:ChooseSwitchStatements}
     1251\vspace*{-11pt}
    12221252\end{figure}
    12231253
    1224 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.
     1254Finally, 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.
    12251255The 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;
    12261256the target label may be case @default@, but only associated with the current @switch@/@choose@ statement.
     
    12281258\begin{figure}
    12291259\centering
     1260\fontsize{9bp}{11bp}\selectfont
    12301261\lstDeleteShortInline@%
    12311262\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     
    12561287\end{tabular}
    12571288\lstMakeShortInline@%
    1258 \caption{\lstinline|fallthrough| Statement}
     1289\caption{\lstinline|fallthrough| statement}
    12591290\label{f:FallthroughStatement}
     1291\vspace*{-11pt}
    12601292\end{figure}
    12611293
    12621294
    1263 \subsection{\texorpdfstring{Labelled \protect\lstinline{continue} / \protect\lstinline{break}}{Labelled continue / break}}
     1295\vspace*{-8pt}
     1296\subsection{\texorpdfstring{Labeled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labeled continue / break}}
    12641297
    12651298While C provides @continue@ and @break@ statements for altering control flow, both are restricted to one level of nesting for a particular control structure.
    1266 Unfortunately, this restriction forces programmers to use @goto@ to achieve the equivalent control-flow for more than one level of nesting.
    1267 To 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.
     1299Unfortunately, this restriction forces programmers to use @goto@ to achieve the equivalent control flow for more than one level of nesting.
     1300To 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.
    12681301For both @continue@ and @break@, the target label must be directly associated with a @for@, @while@ or @do@ statement;
    12691302for @break@, the target label can also be associated with a @switch@, @if@ or compound (@{}@) statement.
    1270 Figure~\ref{f:MultiLevelExit} shows @continue@ and @break@ indicating the specific control structure, and the corresponding C program using only @goto@ and labels.
    1271 The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 nested control-structures.
     1303Figure~\ref{f:MultiLevelExit} shows @continue@ and @break@ indicating the specific control structure and the corresponding C program using only @goto@ and labels.
     1304The innermost loop has seven exit points, which cause a continuation or termination of one or more of the seven nested control structures.
    12721305
    12731306\begin{figure}
     1307\fontsize{9bp}{11bp}\selectfont
    12741308\lstDeleteShortInline@%
    12751309\begin{tabular}{@{\hspace{\parindentlnth}}l|@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     
    13361370\end{tabular}
    13371371\lstMakeShortInline@%
    1338 \caption{Multi-level Exit}
     1372\caption{Multilevel exit}
    13391373\label{f:MultiLevelExit}
     1374\vspace*{-5pt}
    13401375\end{figure}
    13411376
    1342 With respect to safety, both labelled @continue@ and @break@ are a @goto@ restricted in the following ways:
    1343 \begin{itemize}
     1377With 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}
    13441379\item
    13451380They cannot create a loop, which means only the looping constructs cause looping.
     
    13471382\item
    13481383They cannot branch into a control structure.
    1349 This restriction prevents missing declarations and/or initializations at the start of a control structure resulting in undefined behaviour.
    1350 \end{itemize}
    1351 The 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.
    1352 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 occurring in the body of the control structure.
     1384This restriction prevents missing declarations and/or initializations at the start of a control structure resulting in an undefined behavior.
     1385\end{list}
     1386The 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.
     1387Furthermore, the location of the label at the \emph{beginning} of the target control structure informs the reader (eye candy) that complex control flow is
     1388occurring in the body of the control structure.
    13531389With @goto@, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader.
    1354 Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs.
     1390Finally, 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.
    13551391Otherwise, the implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed.
    13561392
    13571393
    1358 \subsection{Exception Handling}
    1359 
    1360 The following framework for \CFA exception-handling is in place, excluding some runtime type-information and virtual functions.
     1394\vspace*{-5pt}
     1395\subsection{Exception handling}
     1396
     1397The following framework for \CFA exception handling is in place, excluding some runtime type information and virtual functions.
    13611398\CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling})~\cite{Buhr92b,Buhr00a}.
    1362 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.
     1399Both 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.
    13631400\CFA restricts exception types to those defined by aggregate type @exception@.
    13641401The 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@).
    1365 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation.
     1402If @resume@ or @throw@ has no exception type, it is a reresume/rethrow, which means that the current exception continues propagation.
    13661403If there is no current exception, the reresume/rethrow results in a runtime error.
    13671404
    13681405\begin{figure}
     1406\fontsize{9bp}{11bp}\selectfont
     1407\lstDeleteShortInline@%
    13691408\begin{cquote}
    1370 \lstDeleteShortInline@%
    13711409\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
    13721410\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{Resumption}}   & \multicolumn{1}{c@{}}{\textbf{Termination}}   \\
     
    13991437\end{cfa}
    14001438\end{tabular}
    1401 \lstMakeShortInline@%
    14021439\end{cquote}
    1403 \caption{\CFA Exception Handling}
     1440\lstMakeShortInline@%
     1441\caption{\CFA exception handling}
    14041442\label{f:CFAExceptionHandling}
     1443\vspace*{-5pt}
    14051444\end{figure}
    14061445
    1407 The set of exception types in a list of catch clause may include both a resumption and termination handler:
     1446The set of exception types in a list of catch clauses may include both a resumption and a termination handler.
    14081447\begin{cfa}
    14091448try {
     
    14191458The termination handler is available because the resumption propagation did not unwind the stack.
    14201459
    1421 An additional feature is conditional matching in a catch clause:
     1460An additional feature is conditional matching in a catch clause.
    14221461\begin{cfa}
    14231462try {
     
    14281467   catch ( IOError err ) { ... }                        $\C{// handler error from other files}$
    14291468\end{cfa}
    1430 where the throw inserts the failing file-handle into the I/O exception.
    1431 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..
    1432 
    1433 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}:
     1469Here, the throw inserts the failing file handle into the I/O exception.
     1470Conditional 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
     1472The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}.
    14341473\begin{cfa}
    14351474resume( $\emph{exception-type}$, $\emph{alternate-stack}$ )
     
    14391478Nonlocal 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.
    14401479
    1441 To facilitate nonlocal raise, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation.
    1442 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks:
     1480To facilitate nonlocal raise, \CFA provides dynamic enabling and disabling of nonlocal exception propagation.
     1481The constructs for controlling propagation of nonlocal exceptions are the @enable@ and @disable@ blocks.
    14431482\begin{cquote}
    14441483\lstDeleteShortInline@%
     
    14461485\begin{cfa}
    14471486enable $\emph{exception-type-list}$ {
    1448         // allow non-local raise
     1487        // allow nonlocal raise
    14491488}
    14501489\end{cfa}
     
    14521491\begin{cfa}
    14531492disable $\emph{exception-type-list}$ {
    1454         // disallow non-local raise
     1493        // disallow nonlocal raise
    14551494}
    14561495\end{cfa}
     
    14601499The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively.
    14611500Specifying no exception type is shorthand for specifying all exception types.
    1462 Both @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.
    1463 Coroutines and tasks start with non-local exceptions disabled, allowing handlers to be put in place, before non-local exceptions are explicitly enabled.
     1501Both @enable@ and @disable@ blocks can be nested;
     1502turning propagation on/off on entry and on exit, the specified exception types are restored to their prior state.
     1503Coroutines and tasks start with nonlocal exceptions disabled, allowing handlers to be put in place, before nonlocal exceptions are explicitly enabled.
    14641504\begin{cfa}
    14651505void main( mytask & t ) {                                       $\C{// thread starts here}$
    1466         // non-local exceptions disabled
    1467         try {                                                                   $\C{// establish handles for non-local exceptions}$
    1468                 enable {                                                        $\C{// allow non-local exception delivery}$
     1506        // nonlocal exceptions disabled
     1507        try {                                                                   $\C{// establish handles for nonlocal exceptions}$
     1508                enable {                                                        $\C{// allow nonlocal exception delivery}$
    14691509                        // task body
    14701510                }
     
    14741514\end{cfa}
    14751515
    1476 Finally, \CFA provides a Java like  @finally@ clause after the catch clauses:
     1516Finally, \CFA provides a Java-like  @finally@ clause after the catch clauses.
    14771517\begin{cfa}
    14781518try {
     
    14831523}
    14841524\end{cfa}
    1485 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised.
     1525The finally clause is always executed, \ie, if the try block ends normally or if an exception is raised.
    14861526If an exception is raised and caught, the handler is run before the finally clause.
    14871527Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.
    1488 Mimicking 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}}
     1528Mimicking 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}}
    14921532\label{s:WithStatement}
    14931533
    1494 Heterogeneous data is often aggregated into a structure/union.
    1495 To 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.
     1534Heterogeneous data are often aggregated into a structure/union.
     1535To 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.
    14961536\begin{cquote}
    14971537\vspace*{-\baselineskip}%???
     
    15211561Object-oriented programming languages only provide implicit qualification for the receiver.
    15221562
    1523 In detail, the @with@ statement has the form:
     1563In detail, the @with@ statement has the form
    15241564\begin{cfa}
    15251565$\emph{with-statement}$:
     
    15271567\end{cfa}
    15281568and may appear as the body of a function or nested within a function body.
    1529 Each expression in the expression-list provides a type and object.
     1569Each expression in the expression list provides a type and object.
    15301570The type must be an aggregate type.
    15311571(Enumerations are already opened.)
    1532 The object is the implicit qualifier for the open structure-members.
     1572The object is the implicit qualifier for the open structure members.
    15331573
    15341574All 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.
    1535 The difference between parallel and nesting occurs for members with the same name and type:
     1575The difference between parallel and nesting occurs for members with the same name and type.
    15361576\begin{cfa}
    15371577struct S { int `i`; int j; double m; } s, w;    $\C{// member i has same type in structure types S and T}$
     
    15471587}
    15481588\end{cfa}
    1549 For parallel semantics, both @s.i@ and @t.i@ are visible, so @i@ is ambiguous without qualification;
    1550 for nested semantics, @t.i@ hides @s.i@, so @i@ implies @t.i@.
     1589For parallel semantics, both @s.i@ and @t.i@ are visible and, therefore, @i@ is ambiguous without qualification;
     1590for nested semantics, @t.i@ hides @s.i@ and, therefore, @i@ implies @t.i@.
    15511591\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.
    15521592Qualification or a cast is used to disambiguate.
    15531593
    1554 There is an interesting problem between parameters and the function-body @with@, \eg:
     1594There is an interesting problem between parameters and the function body @with@.
    15551595\begin{cfa}
    15561596void ?{}( S & s, int i ) with ( s ) {           $\C{// constructor}$
     
    15581598}
    15591599\end{cfa}
    1560 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@.
    1561 To solve this problem, parameters are treated like an initialized aggregate:
     1600Here, 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@.
     1601To solve this problem, parameters are treated like an initialized aggregate
    15621602\begin{cfa}
    15631603struct Params {
     
    15661606} params;
    15671607\end{cfa}
    1568 and implicitly opened \emph{after} a function-body open, to give them higher priority:
     1608\newpage
     1609and implicitly opened \emph{after} a function body open, to give them higher priority
    15691610\begin{cfa}
    15701611void ?{}( S & s, int `i` ) with ( s ) `{` `with( $\emph{\color{red}params}$ )` {
     
    15721613} `}`
    15731614\end{cfa}
    1574 Finally, a cast may be used to disambiguate among overload variables in a @with@ expression:
     1615Finally, a cast may be used to disambiguate among overload variables in a @with@ expression
    15751616\begin{cfa}
    15761617with ( w ) { ... }                                                      $\C{// ambiguous, same name and no context}$
    15771618with ( (S)w ) { ... }                                           $\C{// unambiguous, cast}$
    15781619\end{cfa}
    1579 and @with@ expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate:
     1620and @with@ expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate
    15801621\begin{cfa}
    15811622struct S { int i, j; } sv;
     
    16011642\CFA attempts to correct and add to C declarations, while ensuring \CFA subjectively ``feels like'' C.
    16021643An 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.
    1603 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.
     1644Maintaining 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.
    16041645Nevertheless, some features from other approaches are undeniably convenient;
    16051646\CFA attempts to adapt these features to the C paradigm.
    16061647
    16071648
    1608 \subsection{Alternative Declaration Syntax}
     1649\subsection{Alternative declaration syntax}
    16091650
    16101651C declaration syntax is notoriously confusing and error prone.
    1611 For example, many C programmers are confused by a declaration as simple as:
     1652For example, many C programmers are confused by a declaration as simple as the following.
    16121653\begin{cquote}
    16131654\lstDeleteShortInline@%
     
    16211662\lstMakeShortInline@%
    16221663\end{cquote}
    1623 Is this an array of 5 pointers to integers or a pointer to an array of 5 integers?
     1664Is this an array of five pointers to integers or a pointer to an array of five integers?
    16241665If there is any doubt, it implies productivity and safety issues even for basic programs.
    16251666Another 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.
    1626 For example, a function returning a pointer to an array of integers is defined and used in the following way:
     1667For example, a function returning a pointer to an array of integers is defined and used in the following way.
    16271668\begin{cfa}
    16281669int `(*`f`())[`5`]` {...};                                      $\C{// definition}$
     
    16321673While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
    16331674
    1634 \CFA provides its own type, variable and function declarations, using a different syntax~\cite[pp.~856--859]{Buhr94a}.
    1635 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right.
     1675\newpage
     1676\CFA provides its own type, variable, and function declarations, using a different syntax~\cite[pp.~856--859]{Buhr94a}.
     1677The new declarations place qualifiers to the left of the base type, whereas C declarations place qualifiers to the right.
    16361678The qualifiers have the same meaning but are ordered left to right to specify a variable's type.
    16371679\begin{cquote}
     
    16591701\lstMakeShortInline@%
    16601702\end{cquote}
    1661 The only exception is bit-field specification, which always appear to the right of the base type.
     1703The only exception is bit-field specification, which always appears to the right of the base type.
    16621704% 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.
    16631705However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    1664 For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as follows:
     1706For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as
    16651707\begin{cquote}
    16661708\lstDeleteShortInline@%
     
    17251767\end{comment}
    17261768
    1727 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, \eg:
     1769All 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.
    17281770\begin{cquote}
    17291771\lstDeleteShortInline@%
    17301772\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    17311773\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
    1732 \begin{cfa}
     1774\begin{cfa}[basicstyle=\linespread{0.9}\fontsize{9bp}{12bp}\selectfont\sf]
    17331775extern const * const int x;
    17341776static const * [5] const int y;
    17351777\end{cfa}
    17361778&
    1737 \begin{cfa}
     1779\begin{cfa}[basicstyle=\linespread{0.9}\fontsize{9bp}{12bp}\selectfont\sf]
    17381780int extern const * const x;
    17391781static const int (* const y)[5]
    17401782\end{cfa}
    17411783&
    1742 \begin{cfa}
     1784\begin{cfa}[basicstyle=\linespread{0.9}\fontsize{9bp}{12bp}\selectfont\sf]
    17431785// external const pointer to const int
    17441786// internal const pointer to array of 5 const int
     
    17481790\end{cquote}
    17491791Specifiers must appear at the start of a \CFA function declaration\footnote{\label{StorageClassSpecifier}
    1750 The 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}}.
     1792The 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}).}.
    17511793
    17521794The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-function @sizeof@:
     
    17691811
    17701812The syntax of the new function-prototype declaration follows directly from the new function-definition syntax;
    1771 as well, parameter names are optional, \eg:
     1813also, parameter names are optional.
    17721814\begin{cfa}
    17731815[ int x ] f ( /* void */ );             $\C[2.5in]{// returning int with no parameters}$
     
    17771819[ * int, int ] j ( int );               $\C{// returning pointer to int and int with int parameter}$
    17781820\end{cfa}
    1779 This syntax allows a prototype declaration to be created by cutting and pasting source text from the function-definition header (or vice versa).
    1780 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, \eg:
     1821This syntax allows a prototype declaration to be created by cutting and pasting the source text from the function-definition header (or vice versa).
     1822Like 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.
    17811823\begin{cquote}
    17821824\lstDeleteShortInline@%
     
    17931835\lstMakeShortInline@%
    17941836\end{cquote}
    1795 where \CFA allows the last function in the list to define its body.
    1796 
    1797 The syntax for pointers to \CFA functions specifies the pointer name on the right, \eg:
     1837Here, \CFA allows the last function in the list to define its body.
     1838
     1839The syntax for pointers to \CFA functions specifies the pointer name on the right.
    17981840\begin{cfa}
    17991841* [ int x ] () fp;                              $\C{// pointer to function returning int with no parameters}$
     
    18021844* [ * int, int ] ( int ) jp;    $\C{// pointer to function returning pointer to int and int with int parameter}\CRT$
    18031845\end{cfa}
    1804 Note, the name of the function pointer is specified last, as for other variable declarations.
    1805 
    1806 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
    1807 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    1808 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems.
     1846\newpage
     1847\noindent
     1848Note that the name of the function pointer is specified last, as for other variable declarations.
     1849
     1850Finally, new \CFA declarations may appear together with C declarations in the same program block but cannot be mixed within a specific declaration.
     1851Therefore, a programmer has the option of either continuing to use traditional C declarations or taking advantage of the new style.
     1852Clearly, both styles need to be supported for some time due to existing C-style header files, particularly for UNIX-like systems.
    18091853
    18101854
     
    18141858All variables in C have an \newterm{address}, a \newterm{value}, and a \newterm{type};
    18151859at 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.
    1816 The C type-system does not always track the relationship between a value and its address;
    1817 a 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'').
    1818 For 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.
    1819 Despite 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.
     1860The C type system does not always track the relationship between a value and its address;
     1861a 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'').
     1862For 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.
     1863Despite 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.
    18201864
    18211865Within a lexical scope, lvalue expressions have an \newterm{address interpretation} for writing a value or a \newterm{value interpretation} to read a value.
    1822 For example, in @x = y@, @x@ has an address interpretation, while @y@ has a value interpretation.
     1866For example, in @x = y@, @x@ has an address interpretation, whereas @y@ has a value interpretation.
    18231867While 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.
    18241868In C, for any type @T@ there is a pointer type @T *@, the value of which is the address of a value of type @T@.
    1825 A 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 
     1869A 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 @&?@.
    18271870\begin{cfa}
    18281871int x = 1, y = 2, * p1, * p2, ** p3;
     
    18321875*p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15);
    18331876\end{cfa}
    1834 
    18351877Unfortunately, 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.
    18361878For 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.
    1837 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.
     1879However, 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.
    18381880To solve these problems, \CFA introduces reference types @T &@;
    1839 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:
    1840 
     1881a @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.
    18411882\begin{cfa}
    18421883int x = 1, y = 2, & r1, & r2, && r3;
     
    18461887r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15);       $\C{// implicit dereferencing}$
    18471888\end{cfa}
    1848 
    18491889Except for auto-dereferencing by the compiler, this reference example is exactly the same as the previous pointer example.
    1850 Hence, 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.
    1851 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, so the previous example implicitly acts like:
    1852 
     1890Hence, 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.
     1891One 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;
     1892thus, the previous example implicitly acts like the following.
    18531893\begin{cfa}
    18541894`*`r2 = ((`*`r1 + `*`r2) * (`**`r3 - `*`r1)) / (`**`r3 - 15);
    18551895\end{cfa}
    1856 
    18571896References in \CFA are similar to those in \CC, with important improvements, which can be seen in the example above.
    18581897Firstly, \CFA does not forbid references to references.
    1859 This provides a much more orthogonal design for library implementors, obviating the need for workarounds such as @std::reference_wrapper@.
     1898This provides a much more orthogonal design for library \mbox{implementors}, obviating the need for workarounds such as @std::reference_wrapper@.
    18601899Secondly, \CFA references are rebindable, whereas \CC references have a fixed address.
    1861 Rebinding allows \CFA references to be default-initialized (\eg to a null pointer\footnote{
    1862 While 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.
     1900Rebinding allows \CFA references to be default initialized (\eg to a null pointer\footnote{
     1901While 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.
    18631902Rebinding is accomplished by extending the existing syntax and semantics of the address-of operator in C.
    18641903
    1865 In 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.
    1866 In \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.
     1904In 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.
     1905In \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.
    18671906The 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.
    18681907This rebinding occurs to an arbitrary depth of reference nesting;
    18691908loosely speaking, nested address-of operators produce a nested lvalue pointer up to the depth of the reference.
    18701909These 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@.
    1871 More precisely:
     1910The precise rules are
    18721911\begin{itemize}
    18731912\item
    1874 if @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        
     1913If @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).
    18761914\item
    1877 if @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).
     1915If @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).
    18781916\end{itemize}
    1879 Since 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.
     1917Since pointers and references share the same internal representation, code using either is equally performant;
     1918in 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.
    18801919
    18811920By analogy to pointers, \CFA references also allow cv-qualifiers such as @const@:
     
    18921931There are three initialization contexts in \CFA: declaration initialization, argument/parameter binding, and return/temporary binding.
    18931932In each of these contexts, the address-of operator on the target lvalue is elided.
    1894 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@.
    1895 
    1896 More 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;
     1933The 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
     1935More 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;
    18971936this conversion is used in any context in \CFA where an implicit conversion is allowed.
    1898 Similarly, 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.
    1899 The final reference conversion included in \CFA is ``rvalue-to-reference'' conversion, implemented by means of an implicit temporary.
     1937Similarly, 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.
     1938The final reference conversion included in \CFA is an ``rvalue-to-reference'' conversion, implemented by means of an implicit temporary.
    19001939When 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.
    19011940\begin{cfa}
     
    19051944f( 3, x + y, (S){ 1.0, 7.0 }, (int [3]){ 1, 2, 3 } ); $\C{// pass rvalue to lvalue \(\Rightarrow\) implicit temporary}$
    19061945\end{cfa}
    1907 This 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 
    1913 Nested 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@).
    1914 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, meaning there is no need for type qualification.
    1915 Since \CFA in not object-oriented, adopting dynamic scoping does not make sense;
    1916 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}).
     1946This 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
     1952Nested 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@).
     1953Java 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.
     1954Since \CFA in not object oriented, adopting dynamic scoping does not make sense;
     1955instead, \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}).
     1956In the C left example, types @C@, @U@ and @T@ are implicitly hoisted outside of type @S@ into the containing block scope.
     1957In the \CFA right example, the types are not hoisted and accessible.
     1958
    19171959\begin{figure}
    19181960\centering
     1961\fontsize{9bp}{11bp}\selectfont\sf
    19191962\lstDeleteShortInline@%
    19201963\begin{tabular}{@{}l@{\hspace{3em}}l|l@{}}
     
    19782021\end{tabular}
    19792022\lstMakeShortInline@%
    1980 \caption{Type Nesting / Qualification}
     2023\caption{Type nesting / qualification}
    19812024\label{f:TypeNestingQualification}
     2025\vspace*{-8pt}
    19822026\end{figure}
    1983 In the C left example, types @C@, @U@ and @T@ are implicitly hoisted outside of type @S@ into the containing block scope.
    1984 In the \CFA right example, the types are not hoisted and accessible.
    1985 
    1986 
    1987 \subsection{Constructors and Destructors}
     2027
     2028
     2029\vspace*{-8pt}
     2030\subsection{Constructors and destructors}
    19882031\label{s:ConstructorsDestructors}
    19892032
    1990 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.
     2033One 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.
    19912034However, this manual approach is verbose, and it is useful to manage resources other than memory (\eg file handles) using the same mechanism as memory.
    1992 \CC addresses these issues using Resource Aquisition Is Initialization (RAII), implemented by means of \newterm{constructor} and \newterm{destructor} functions;
     2035\CC addresses these issues using RAII, implemented by means of \newterm{constructor} and \newterm{destructor} functions;
    19932036\CFA adopts constructors and destructors (and @finally@) to facilitate RAII.
    1994 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.
    1995 Specifically, \CFA constructors and destructors are denoted by name and first parameter-type versus name and nesting in an aggregate type.
     2037While 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.
     2038Specifically, \CFA constructors and destructors are denoted by name and first parameter type versus name and nesting in an aggregate type.
    19962039Constructor 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.
    19972040
     
    20022045The constructor and destructor have return type @void@, and the first parameter is a reference to the object type to be constructed or destructed.
    20032046While the first parameter is informally called the @this@ parameter, as in object-oriented languages, any variable name may be used.
    2004 Both constructors and destructors allow additional parameters after the @this@ parameter for specifying values for initialization/de-initialization\footnote{
    2005 Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}.
    2006 \begin{cfa}
     2047Both constructors and destructors allow additional parameters after the @this@ parameter for specifying values for initialization/deinitialization\footnote{
     2048Destruction 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]
    20072050struct VLA { int size, * data; };                       $\C{// variable length array of integers}$
    20082051void ?{}( VLA & vla ) with ( vla ) { size = 10;  data = alloc( size ); }  $\C{// default constructor}$
     
    20132056\end{cfa}
    20142057@VLA@ is a \newterm{managed type}\footnote{
    2015 A 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.
     2058A 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.
    20162059A 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.
    2017 For 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}:
     2060For 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}.
    20202063\begin{cfa}
    20212064void ?{}( VLA & vla, int size, char fill = '\0' ) {  $\C{// initialization}$
     
    20262069}
    20272070\end{cfa}
    2028 (Note, the example is purposely simplified using shallow-copy semantics.)
    2029 An 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).
     2071(Note that the example is purposely simplified using shallow-copy semantics.)
     2072An 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).
    20302073\begin{cfa}
    20312074VLA va = `{` 20, 0 `}`,  * arr = alloc()`{` 5, 0 `}`;
    20322075\end{cfa}
    2033 Note, the use of a \newterm{constructor expression} to initialize the storage from the dynamic storage-allocation.
     2076Note the use of a \newterm{constructor expression} to initialize the storage from the dynamic storage allocation.
    20342077Like \CC, the copy constructor has two parameters, the second of which is a value parameter with the same type as the first parameter;
    20352078appropriate care is taken to not recursively call the copy constructor when initializing the second parameter.
     
    20372080\CFA constructors may be explicitly called, like Java, and destructors may be explicitly called, like \CC.
    20382081Explicit 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.
    2039 Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls:
     2082Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls.
    20402083\begin{cfa}
    20412084{
     
    20532096To 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.
    20542097These default functions can be overridden by user-generated versions.
    2055 For 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;
    2056 if default zero-initialization is desired, the default constructors can be overridden.
     2098For 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;
     2099if default zero initialization is desired, the default constructors can be overridden.
    20572100For user-generated types, the four functions are also automatically generated.
    20582101@enum@ types are handled the same as their underlying integral type, and unions are also bitwise copied and no-op initialized and destructed.
    20592102For compatibility with C, a copy constructor from the first union member type is also defined.
    2060 For @struct@ types, each of the four functions are implicitly defined to call their corresponding functions on each member of the struct.
    2061 To better simulate the behaviour of C initializers, a set of \newterm{member constructors} is also generated for structures.
    2062 A 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.
     2103For @struct@ types, each of the four functions is implicitly defined to call their corresponding functions on each member of the struct.
     2104To better simulate the behavior of C initializers, a set of \newterm{member constructors} is also generated for structures.
     2105A 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.
    20632106To 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;
    2064 similarly, the generated default constructor is hidden upon declaration of any constructor.
     2107similarly, the generated default constructor is hidden upon the declaration of any constructor.
    20652108These semantics closely mirror the rule for implicit declaration of constructors in \CC\cite[p.~186]{ANSI98:C++}.
    20662109
    2067 In some circumstance programmers may not wish to have implicit constructor and destructor generation and calls.
    2068 In these cases, \CFA provides the initialization syntax \lstinline|S x `@=` {}|, and the object becomes unmanaged, so implicit constructor and destructor calls are not generated.
     2110In some circumstance, programmers may not wish to have implicit constructor and destructor generation and calls.
     2111In these cases, \CFA provides the initialization syntax \lstinline|S x `@=` {}|, and the object becomes unmanaged;
     2112hence, implicit \mbox{constructor} and destructor calls are not generated.
    20692113Any C initializer can be the right-hand side of an \lstinline|@=| initializer, \eg \lstinline|VLA a @= { 0, 0x0 }|, with the usual C initialization semantics.
    20702114The same syntax can be used in a compound literal, \eg \lstinline|a = (VLA)`@`{ 0, 0x0 }|, to create a C-style literal.
    2071 The 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.
     2115The 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.
    20722116
    20732117
     
    20772121\section{Literals}
    20782122
    2079 C 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.
    2080 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 backwards-compatible semantics.
     2123C 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.
     2124In 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.
    20812125
    20822126A 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.
    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.
     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.
    20842128
    20852129
     
    21242168
    21252169In C, @0@ has the special property that it is the only ``false'' value;
    2126 by the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true.
    2127 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.
     2170by the standard, any value that compares equal to @0@ is false, whereas any value that compares unequal to @0@ is true.
     2171As 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.
    21282172Operator 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.
    21292173To 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);
     
    21312175With 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 )@.
    21322176\CC makes types truthy by adding a conversion to @bool@;
    2133 prior to the addition of explicit cast operators in \CCeleven, this approach had the pitfall of making truthy types transitively convertable to any numeric type;
     2177prior to the addition of explicit cast operators in \CCeleven, this approach had the pitfall of making truthy types transitively convertible into any numeric type;
    21342178\CFA avoids this issue.
    21352179
     
    21422186
    21432187
    2144 \subsection{User Literals}
     2188\subsection{User literals}
    21452189
    21462190For readability, it is useful to associate units to scale literals, \eg weight (stone, pound, kilogram) or time (seconds, minutes, hours).
    2147 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.
     2191The 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.
    21482192The backquote is a small character, making the unit (function name) predominate.
    2149 For examples, the multi-precision integer-type in Section~\ref{s:MultiPrecisionIntegers} has user literals:
     2193For examples, the multiprecision integer type in Section~\ref{s:MultiPrecisionIntegers} has the following user literals.
    21502194{\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    21512195\begin{cfa}
     
    21532197y = "12345678901234567890123456789"|`mp| + "12345678901234567890123456789"|`mp|;
    21542198\end{cfa}
    2155 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.
     2199Because \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.
    21562200}%
    21572201\begin{cquote}
     
    21952239\end{cquote}
    21962240
    2197 The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call-syntax.
     2241The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call syntax.
    21982242However, \CC restricts the types, \eg @unsigned long long int@ and @long double@ to represent integral and floating literals.
    21992243After which, user literals must match (no conversions);
     
    22022246\begin{figure}
    22032247\centering
     2248\fontsize{9bp}{11bp}\selectfont
    22042249\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    22052250\lstDeleteShortInline@%
     
    22572302\end{tabular}
    22582303\lstMakeShortInline@%
    2259 \caption{User Literal}
     2304\caption{User literal}
    22602305\label{f:UserLiteral}
    22612306\end{figure}
     
    22652310\label{sec:libraries}
    22662311
    2267 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 inter-language communication with C.
     2312As 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.
    22682313\CFA has replacement libraries condensing hundreds of existing C names into tens of \CFA overloaded names, all without rewriting the actual computations.
    2269 In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime.
     2314In many cases, the interface is an inline wrapper providing overloading during compilation but of zero cost at runtime.
    22702315The following sections give a glimpse of the interface reduction to many C libraries.
    22712316In 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.
     
    22752320
    22762321C library @limits.h@ provides lower and upper bound constants for the basic types.
    2277 \CFA name overloading is used to condense these typed constants, \eg:
     2322\CFA name overloading is used to condense these typed constants.
    22782323\begin{cquote}
    22792324\lstDeleteShortInline@%
     
    22942339\lstMakeShortInline@%
    22952340\end{cquote}
    2296 The result is a significant reduction in names to access typed constants, \eg:
     2341The result is a significant reduction in names to access typed constants.
    22972342\begin{cquote}
    22982343\lstDeleteShortInline@%
     
    23202365
    23212366C library @math.h@ provides many mathematical functions.
    2322 \CFA function overloading is used to condense these mathematical functions, \eg:
     2367\CFA function overloading is used to condense these mathematical functions.
    23232368\begin{cquote}
    23242369\lstDeleteShortInline@%
     
    23392384\lstMakeShortInline@%
    23402385\end{cquote}
    2341 The result is a significant reduction in names to access math functions, \eg:
     2386The result is a significant reduction in names to access math functions.
    23422387\begin{cquote}
    23432388\lstDeleteShortInline@%
     
    23582403\lstMakeShortInline@%
    23592404\end{cquote}
    2360 While \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).
     2405While \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).
    23612406For example, it is impossible to overload @atan@ for both one and two arguments;
    2362 instead the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}).
    2363 The 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.
     2407instead, the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}).
     2408The 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.
    23642409
    23652410
     
    23672412
    23682413C library @stdlib.h@ provides many general functions.
    2369 \CFA function overloading is used to condense these utility functions, \eg:
     2414\CFA function overloading is used to condense these utility functions.
    23702415\begin{cquote}
    23712416\lstDeleteShortInline@%
     
    23862431\lstMakeShortInline@%
    23872432\end{cquote}
    2388 The result is a significant reduction in names to access utility functions, \eg:
     2433The result is a significant reduction in names to access the utility functions.
    23892434\begin{cquote}
    23902435\lstDeleteShortInline@%
     
    24052450\lstMakeShortInline@%
    24062451\end{cquote}
    2407 In additon, there are polymorphic functions, like @min@ and @max@, that work on any type with operators @?<?@ or @?>?@.
     2452In addition, there are polymorphic functions, like @min@ and @max@, that work on any type with operator @?<?@ or @?>?@.
    24082453
    24092454The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety.
    2410 C/\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]
     2455C/\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}
    24122457\item[fill]
    24132458an allocation with a specified character.
    24142459\item[resize]
    24152460an existing allocation to decrease or increase its size.
    2416 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 is copied.
     2461In 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.
    24172462For an increase in storage size, new storage after the copied data may be filled.
     2463\newpage
    24182464\item[align]
    24192465an allocation on a specified memory boundary, \eg, an address multiple of 64 or 128 for cache-line purposes.
     
    24212467allocation with a specified number of elements.
    24222468An array may be filled, resized, or aligned.
    2423 \end{description}
    2424 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.
    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.
    2426 Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation performing the same operations with the same type safety.
     2469\end{list}
     2470Table~\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.
     2472Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage allocation performing the same operations with the same type safety.
    24272473
    24282474\begin{table}
    2429 \caption{Storage-Management Operations}
     2475\caption{Storage-management operations}
    24302476\label{t:StorageManagementOperations}
    24312477\centering
    24322478\lstDeleteShortInline@%
    24332479\lstMakeShortInline~%
    2434 \begin{tabular}{@{}r|r|l|l|l|l@{}}
    2435 \multicolumn{1}{c}{}&           & \multicolumn{1}{c|}{fill}     & resize        & align & array \\
    2436 \hline
     2480\begin{tabular}{@{}rrllll@{}}
     2481\multicolumn{1}{c}{}&           & \multicolumn{1}{c}{fill}      & resize        & align & array \\
    24372482C               & ~malloc~                      & no                    & no            & no            & no    \\
    24382483                & ~calloc~                      & yes (0 only)  & no            & no            & yes   \\
     
    24402485                & ~memalign~            & no                    & no            & yes           & no    \\
    24412486                & ~posix_memalign~      & no                    & no            & yes           & no    \\
    2442 \hline
    24432487C11             & ~aligned_alloc~       & no                    & no            & yes           & no    \\
    2444 \hline
    24452488\CFA    & ~alloc~                       & yes/copy              & no/yes        & no            & yes   \\
    24462489                & ~align_alloc~         & yes                   & no            & yes           & yes   \\
     
    24522495\begin{figure}
    24532496\centering
     2497\fontsize{9bp}{11bp}\selectfont
    24542498\begin{cfa}[aboveskip=0pt,xleftmargin=0pt]
    24552499size_t  dim = 10;                                                       $\C{// array dimension}$
     
    24892533\end{tabular}
    24902534\lstMakeShortInline@%
    2491 \caption{\CFA versus C Storage-Allocation}
     2535\caption{\CFA versus C storage allocation}
    24922536\label{f:StorageAllocation}
    24932537\end{figure}
    24942538
    24952539Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization.
    2496 Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor, \eg:
     2540Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor.
    24972541\begin{cfa}
    24982542struct S { int i, j; };
     
    25012545S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
    25022546\end{cfa}
    2503 Note, \CC can only initialize array elements via the default constructor.
    2504 
    2505 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.
     2547Note that \CC can only initialize array elements via the default constructor.
     2548
     2549Finally, the \CFA memory allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
    25062550When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character.
    25072551
     
    25102554\label{s:IOLibrary}
    25112555
    2512 The goal of \CFA I/O is to simplify the common cases, while fully supporting polymorphism and user defined types in a consistent way.
     2556The goal of \CFA I/O is to simplify the common cases, while fully supporting polymorphism and user-defined types in a consistent way.
    25132557The approach combines ideas from \CC and Python.
    25142558The \CFA header file for the I/O library is @fstream@.
     
    25392583\lstMakeShortInline@%
    25402584\end{cquote}
    2541 The \CFA form has half the characters of the \CC form, and is similar to Python I/O with respect to implicit separators.
     2585The \CFA form has half the characters of the \CC form and is similar to Python I/O with respect to implicit separators.
    25422586Similar simplification occurs for tuple I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
    25432587\begin{cfa}
     
    25722616\lstMakeShortInline@%
    25732617\end{cquote}
    2574 There 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.
     2618There 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.
    25752619\begin{comment}
    25762620The implicit separator character (space/blank) is a separator not a terminator.
     
    25932637\end{itemize}
    25942638\end{comment}
    2595 There 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}
     2639There 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}
    25992643\label{s:MultiPrecisionIntegers}
    26002644
    2601 \CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP.
    2602 The \CFA interface wraps GMP functions into operator functions to make programming with multi-precision integers identical to using fixed-sized integers.
    2603 The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@.
    2604 Figure~\ref{f:GMPInterface} shows a multi-precision factorial-program contrasting the GMP interface in \CFA and C.
    2605 
    2606 \begin{figure}
     2645\CFA has an interface to the GNU multiple precision (GMP) signed integers~\cite{GMP}, similar to the \CC interface provided by GMP.
     2646The \CFA interface wraps GMP functions into operator functions to make programming with multiprecision integers identical to using fixed-sized integers.
     2647The \CFA type name for multiprecision signed integers is @Int@ and the header file is @gmp@.
     2648Figure~\ref{f:GMPInterface} shows a multiprecision factorial program contrasting the GMP interface in \CFA and C.
     2649
     2650\begin{figure}[b]
    26072651\centering
     2652\fontsize{9bp}{11bp}\selectfont
    26082653\lstDeleteShortInline@%
    26092654\begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
     
    26362681\end{tabular}
    26372682\lstMakeShortInline@%
    2638 \caption{GMP Interface \CFA versus C}
     2683\caption{GMP interface \CFA versus C}
    26392684\label{f:GMPInterface}
    26402685\end{figure}
    26412686
    26422687
     2688\vspace{-4pt}
    26432689\section{Polymorphism Evaluation}
    26442690\label{sec:eval}
     
    26492695% Though \CFA provides significant added functionality over C, these features have a low runtime penalty.
    26502696% In fact, it is shown that \CFA's generic programming can enable faster runtime execution than idiomatic @void *@-based C code.
    2651 The experiment is a set of generic-stack micro-benchmarks~\cite{CFAStackEvaluation} in C, \CFA, and \CC (see implementations in Appendix~\ref{sec:BenchmarkStackImplementations}).
     2697The experiment is a set of generic-stack microbenchmarks~\cite{CFAStackEvaluation} in C, \CFA, and \CC (see implementations in Appendix~\ref{sec:BenchmarkStackImplementations}).
    26522698Since 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.
    26532699A more illustrative comparison measures the costs of idiomatic usage of each language's features.
    2654 Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list.
     2700Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked list.
    26552701The benchmark test is similar for the other languages.
    26562702The 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.
    26572703
    26582704\begin{figure}
     2705\fontsize{9bp}{11bp}\selectfont
    26592706\begin{cfa}[xleftmargin=3\parindentlnth,aboveskip=0pt,belowskip=0pt]
    26602707int main() {
     
    26762723}
    26772724\end{cfa}
    2678 \caption{\protect\CFA Benchmark Test}
     2725\caption{\protect\CFA benchmark test}
    26792726\label{fig:BenchmarkTest}
     2727\vspace*{-10pt}
    26802728\end{figure}
    26812729
    2682 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.
     2730The 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.
    26832731The \CCV variant illustrates an alternative object-oriented idiom where all objects inherit from a base @object@ class, mimicking a Java-like interface;
    2684 hence runtime checks are necessary to safely down-cast objects.
    2685 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, while C and \CCV lack such a capability and instead must store generic objects via pointers to separately-allocated objects.
    2686 Note, the C benchmark uses unchecked casts as C has no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically.
     2732hence, runtime checks are necessary to safely downcast objects.
     2733The 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.
     2734Note 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.
    26872735
    26882736Figure~\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.
    2689 The graph plots the median of 5 consecutive runs of each program, with an initial warm-up run omitted.
     2737The graph plots the median of five consecutive runs of each program, with an initial warm-up run omitted.
    26902738All code is compiled at \texttt{-O2} by gcc or g++ 6.4.0, with all \CC code compiled as \CCfourteen.
    26912739The 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.
     
    26932741\begin{figure}
    26942742\centering
    2695 \input{timing}
    2696 \caption{Benchmark Timing Results (smaller is better)}
     2743\resizebox{0.7\textwidth}{!}{\input{timing}}
     2744\caption{Benchmark timing results (smaller is better)}
    26972745\label{fig:eval}
     2746\vspace*{-10pt}
    26982747\end{figure}
    26992748
    27002749\begin{table}
     2750\vspace*{-10pt}
    27012751\caption{Properties of benchmark code}
    27022752\label{tab:eval}
    27032753\centering
     2754\vspace*{-4pt}
    27042755\newcommand{\CT}[1]{\multicolumn{1}{c}{#1}}
    2705 \begin{tabular}{rrrrr}
    2706                                                                         & \CT{C}        & \CT{\CFA}     & \CT{\CC}      & \CT{\CCV}             \\ \hline
    2707 maximum memory usage (MB)                       & 10,001        & 2,502         & 2,503         & 11,253                \\
     2756\begin{tabular}{lrrrr}
     2757                                                                        & \CT{C}        & \CT{\CFA}     & \CT{\CC}      & \CT{\CCV}             \\
     2758maximum memory usage (MB)                       & 10\,001       & 2\,502        & 2\,503        & 11\,253               \\
    27082759source code size (lines)                        & 201           & 191           & 125           & 294                   \\
    27092760redundant type annotations (lines)      & 27            & 0                     & 2                     & 16                    \\
    27102761binary size (KB)                                        & 14            & 257           & 14            & 37                    \\
    27112762\end{tabular}
     2763\vspace*{-16pt}
    27122764\end{table}
    27132765
    2714 The 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;
     2766\enlargethispage{-10pt}
     2767The 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;
    27152768this inefficiency is exacerbated by the second level of generic types in the pair benchmarks.
    2716 By 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@);
     2769By 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@).
    27182771The outlier for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code.
    27192772The gcc compiler is unable to optimize some dead code and condense nested calls;
     
    27212774Finally, the binary size for \CFA is larger because of static linking with the \CFA libraries.
    27222775
    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.
     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.
    27242777The 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.
    2725 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.
    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;
     2778On 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;
    27272780with their omission, the \CCV line count is similar to C.
    27282781We 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.
    27292782
    2730 Line-count is a fairly rough measure of code complexity;
    2731 another important factor is how much type information the programmer must specify manually, especially where that information is not compiler-checked.
    2732 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.
     2783Line count is a fairly rough measure of code complexity;
     2784another important factor is how much type information the programmer must specify manually, especially where that information is not compiler checked.
     2785Such 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.
    27332786To 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.
    2734 The \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.
     2787The \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.
    27352788The \CFA benchmark is able to eliminate all redundant type annotations through use of the polymorphic @alloc@ function discussed in Section~\ref{sec:libraries}.
    27362789
    2737 We conjecture these results scale across most generic data-types as the underlying polymorphism implement is constant.
    2738 
    2739 
     2790We conjecture that these results scale across most generic data types as the underlying polymorphism implement is constant.
     2791
     2792
     2793\vspace*{-8pt}
    27402794\section{Related Work}
    27412795\label{s:RelatedWork}
     
    27532807\CC provides three disjoint polymorphic extensions to C: overloading, inheritance, and templates.
    27542808The 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.
    2755 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.
     2809In 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.
    27562810The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed type properties.
    2757 Until \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;
     2811Until \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;
    27582812furthermore, \CC concepts are restricted to template polymorphism.
    27592813
    27602814Cyclone~\cite{Grossman06} also provides capabilities for polymorphic functions and existential types, similar to \CFA's @forall@ functions and generic types.
    2761 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, a tedious and potentially error-prone process.
     2815Cyclone 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.
    27622816Furthermore, 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@.
    27632817In \CFA terms, all Cyclone polymorphism must be dtype-static.
    27642818While 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.
    2765 Smith 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.
     2819Smith and Volpano~\cite{Smith98} present Polymorphic C, an ML dialect with polymorphic functions, C-like syntax, and pointer types;
     2820it lacks many of C's features, most notably structure types, and hence, is not a practical C replacement.
    27662821
    27672822Objective-C~\cite{obj-c-book} is an industrially successful extension to C.
    2768 However, Objective-C is a radical departure from C, using an object-oriented model with message-passing.
     2823However, Objective-C is a radical departure from C, using an object-oriented model with message passing.
    27692824Objective-C did not support type-checked generics until recently \cite{xcode7}, historically using less-efficient runtime checking of object types.
    2770 The GObject~\cite{GObject} framework also adds object-oriented programming with runtime type-checking and reference-counting garbage-collection to C;
    2771 these features are more intrusive additions than those provided by \CFA, in addition to the runtime overhead of reference-counting.
    2772 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.
    2773 Java~\cite{Java8} included generic types in Java~5, which are type-checked at compilation and type-erased at runtime, similar to \CFA's.
    2774 However, in Java, each object carries its own table of method pointers, while \CFA passes the method pointers separately to maintain a C-compatible layout.
     2825The GObject~\cite{GObject} framework also adds object-oriented programming with runtime type-checking and reference-counting garbage collection to C;
     2826these features are more intrusive additions than those provided by \CFA, in addition to the runtime overhead of reference counting.
     2827Vala~\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.
     2828Java~\cite{Java8} included generic types in Java~5, which are type checked at compilation and type erased at runtime, similar to \CFA's.
     2829However, in Java, each object carries its own table of method pointers, whereas \CFA passes the method pointers separately to maintain a C-compatible layout.
    27752830Java is also a garbage-collected, object-oriented language, with the associated resource usage and C-interoperability burdens.
    27762831
    2777 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.
     2832D~\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.
    27782833However, 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.
    27792834D and Go are garbage-collected languages, imposing the associated runtime overhead.
    27802835The necessity of accounting for data transfer between managed runtimes and the unmanaged C runtime complicates foreign-function interfaces to C.
    27812836Furthermore, 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.
    2782 D 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.
     2837D 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.
    27832838Rust also possesses much more powerful abstraction capabilities for writing generic code than Go.
    2784 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.
     2839On 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.
    27852840\CFA, with its more modest safety features, allows direct ports of C code while maintaining the idiomatic style of the original source.
    27862841
    27872842
    2788 \subsection{Tuples/Variadics}
    2789 
     2843\vspace*{-18pt}
     2844\subsection{Tuples/variadics}
     2845
     2846\vspace*{-5pt}
    27902847Many programming languages have some form of tuple construct and/or variadic functions, \eg SETL, C, KW-C, \CC, D, Go, Java, ML, and Scala.
    27912848SETL~\cite{SETL} is a high-level mathematical programming language, with tuples being one of the primary data types.
    27922849Tuples in SETL allow subscripting, dynamic expansion, and multiple assignment.
    2793 C 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.
     2850C provides variadic functions through @va_list@ objects, but the programmer is responsible for managing the number of arguments and their types;
     2851thus, the mechanism is type unsafe.
    27942852KW-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.
    27952853The main contributions of that work were adding MRVF, tuple mass and multiple assignment, and record-member access.
    2796 \CCeleven introduced @std::tuple@ as a library variadic template structure.
     2854\CCeleven introduced @std::tuple@ as a library variadic-template structure.
    27972855Tuples are a generalization of @std::pair@, in that they allow for arbitrary length, fixed-size aggregation of heterogeneous values.
    27982856Operations include @std::get<N>@ to extract values, @std::tie@ to create a tuple of references used for assignment, and lexicographic comparisons.
    2799 \CCseventeen proposes \emph{structured bindings}~\cite{Sutter15} to eliminate pre-declaring variables and use of @std::tie@ for binding the results.
    2800 This 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.
     2857\CCseventeen proposes \emph{structured bindings}~\cite{Sutter15} to eliminate predeclaring variables and the use of @std::tie@ for binding the results.
     2858This 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.
    28012859Furthermore, structured bindings are not a full replacement for @std::tie@, as it always declares new variables.
    28022860Like \CC, D provides tuples through a library variadic-template structure.
    28032861Go does not have tuples but supports MRVF.
    2804 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.
     2862Java'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.
    28052863Tuples 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.
    28062864
    28072865
     2866\vspace*{-18pt}
    28082867\subsection{C Extensions}
    28092868
    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.
    2811 Specific 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.
     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.
     2871Specific 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.
    28122872The 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.
    28132873\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.
    2814 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.
    2815 
    2816 There are several other C extension-languages with less usage and even more dramatic changes than \CC.
    2817 Objective-C and Cyclone are two other extensions to C with different design goals than \CFA, as discussed above.
     2874As 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
     2876There 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.
    28182878Other languages extend C with more focused features.
    28192879$\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;
    2820 data-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}.
    2821 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 backwards compatibility goals.
     2880data-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}.
     2881Finally, 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.
    28222882
    28232883
    28242884\section{Conclusion and Future Work}
    28252885
    2826 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.
    2827 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.
    2828 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.
    2829 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.
     2886The 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.
     2887While 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.
     2888The 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.
     2889The 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.
    28302890The work is a challenging design, engineering, and implementation exercise.
    28312891On the surface, the project may appear as a rehash of similar mechanisms in \CC.
    28322892However, 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.
    2833 All of these new features are being used by the \CFA development-team to build the \CFA runtime-system.
     2893All of these new features are being used by the \CFA development team to build the \CFA runtime system.
    28342894Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable.
    28352895
    2836 While 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.
    2837 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.
    2838 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.
    2839 Hence it may be beneficial to provide a mechanism for performance-sensitive code.
    2840 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).
    2841 These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code-bloat.
    2842 In general, we believe separate compilation, producing smaller code, works well with loaded hardware-caches, which may offset the benefit of larger inlined-code.
     2896While all examples in the paper compile and run, there are ongoing efforts to reduce compilation time, provide better debugging, and add more libraries;
     2897when this work is complete in early 2019, a public beta release will be available at \url{https://github.com/cforall/cforall}.
     2898There is also new work on a number of \CFA features, including arrays with size, runtime type information, virtual functions, user-defined conversions, and modules.
     2899While \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.
     2900Hence, it may be beneficial to provide a mechanism for performance-sensitive code.
     2901Two 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.
     2903In general, we believe separate compilation, producing smaller code, works well with loaded hardware caches, which may offset the benefit of larger inlined code.
    28432904
    28442905
    28452906\section{Acknowledgments}
    28462907
    2847 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.
    2848 Funding 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.
     2908The 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.
     2909Funding 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.
    28492910
    28502911{%
    28512912\fontsize{9bp}{12bp}\selectfont%
     2913\vspace*{-3pt}
    28522914\bibliography{pl}
    28532915}%
     
    29282990
    29292991
     2992\enlargethispage{1000pt}
    29302993\subsection{\CFA}
    29312994\label{s:CforallStack}
     
    29943057
    29953058
     3059\newpage
    29963060\subsection{\CC}
    29973061
  • doc/proposals/ctordtor/Makefile

    r7951100 rb067d9b  
    1 ## Define the appropriate configuration variables.
     1## Define the configuration variables.
    22
    3 MACROS = ../../LaTeXmacros
    4 BIB = ../../bibliography
     3Build = build
     4Figures = figures
     5Macros = ../../LaTeXmacros
     6Bib = ../../bibliography
    57
    6 TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
    7 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
     8TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
     9LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    810BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
     11
     12MAKEFLAGS = --no-print-directory # --silent
     13VPATH = ${Build} ${Figures}
    914
    1015## Define the text source files.
     
    2934
    3035DOCUMENT = ctor.pdf
     36BASE = ${basename ${DOCUMENT}}
    3137
    3238# Directives #
     39
     40.PHONY : all clean                                      # not file names
    3341
    3442all : ${DOCUMENT}
    3543
    3644clean :
    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}
     45        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    3946
    4047# File Dependencies #
    4148
    42 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     49${DOCUMENT} : ${BASE}.ps
    4350        ps2pdf $<
    4451
    45 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    46         dvips $< -o $@
     52${BASE}.ps : ${BASE}.dvi
     53        dvips ${Build}/$< -o $@
    4754
    48 ${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
    49                 $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
     55${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
    5057        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    51         if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
     58        #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
    5259        # Must have *.aux file containing citations for bibtex
    5360        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    54         -${BibTeX} ${basename $@}
    55         # Some citations reference others so run steps again to resolve these citations
     61        -${BibTeX} ${Build}/${basename $@}
     62        # Some citations reference others so run again to resolve these citations
    5663        ${LaTeX} ${basename $@}.tex
    57         -${BibTeX} ${basename $@}
     64        -${BibTeX} ${Build}/${basename $@}
    5865        # Make index from *.aux entries and input index at end of document
    59         makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
     66        #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
     67        # Run again to finish citations
    6068        ${LaTeX} ${basename $@}.tex
    6169        # Run again to get index title into table of contents
     
    6775## Define the default recipes.
    6876
    69 %.tex : %.fig
    70         fig2dev -L eepic $< > $@
     77${Build}:
     78        mkdir -p ${Build}
    7179
    72 %.ps : %.fig
    73         fig2dev -L ps $< > $@
     80%.tex : %.fig | ${Build}
     81        fig2dev -L eepic $< > ${Build}/$@
    7482
    75 %.pstex : %.fig
    76         fig2dev -L pstex $< > $@
    77         fig2dev -L pstex_t -p $@ $< > $@_t
     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
    7889
    7990# Local Variables: #
  • doc/proposals/ctordtor/ctor.tex

    r7951100 rb067d9b  
    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 
    91\documentclass[twoside,11pt]{article}
    102
     
    157\usepackage{textcomp}
    168\usepackage[latin1]{inputenc}
     9
    1710\usepackage{fullpage,times,comment}
    1811\usepackage{epic,eepic}
    19 \usepackage{upquote}                                                                    % switch curled `'" to straight
     12\usepackage{upquote}                                    % switch curled `'" to straight
    2013\usepackage{calc}
    2114\usepackage{xspace}
    2215\usepackage{graphicx}
    23 \usepackage{varioref}                                                                   % extended references
    24 \usepackage{listings}                                                                   % format program code
    25 \usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
     16\usepackage{varioref}                                   % extended references
     17\usepackage{listings}                                   % format program code
     18\usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
    2619\usepackage{latexsym}                                   % \Box glyph
    2720\usepackage{mathptmx}                                   % better math font with "times"
     
    3427\renewcommand{\UrlFont}{\small\sf}
    3528
    36 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
     29\setlength{\topmargin}{-0.45in}                         % move running title into header
    3730\setlength{\headsep}{0.25in}
    3831
     
    4336
    4437\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
    4548
    4649\title{
     
    8386\thispagestyle{plain}
    8487\pagenumbering{arabic}
    85 
    8688
    8789
  • doc/proposals/flags.md

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

    r7951100 rb067d9b  
    1 ## Define the appropriate configuration variables.
     1## Define the configuration variables.
    22
    3 MACROS = ../../LaTeXmacros
    4 BIB = ../../bibliography
     3Build = build
     4Figures = figures
     5Macros = ../../LaTeXmacros
     6Bib = ../../bibliography
    57
    6 TeXLIB = .:$(MACROS):$(MACROS)/listings:$(MACROS)/enumitem:$(BIB)/:
    7 LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error
     8TeXLIB = .:${Macros}:${MACROS}/listings:${MACROS}/enumitem:${Bib}/:
     9LaTeX  = TEXINPUTS=${TeXLIB} && export TEXINPUTS && latex -halt-on-error -output-directory=${Build}
    810BibTeX = BIBINPUTS=${TeXLIB} && export BIBINPUTS && bibtex
     11
     12MAKEFLAGS = --no-print-directory --silent #
     13VPATH = ${Build} ${Figures}
    914
    1015## Define the text source files.
     
    2934
    3035DOCUMENT = tuples.pdf
     36BASE = ${basename ${DOCUMENT}}
    3137
    3238# Directives #
     39
     40.PHONY : all clean                                      # not file names
    3341
    3442all : ${DOCUMENT}
    3543
    3644clean :
    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}
     45        @rm -frv ${DOCUMENT} ${BASE}.ps ${Build}
    3946
    4047# File Dependencies #
    4148
    42 ${DOCUMENT} : ${basename ${DOCUMENT}}.ps
     49${DOCUMENT} : ${BASE}.ps
    4350        ps2pdf $<
    4451
    45 ${basename ${DOCUMENT}}.ps : ${basename ${DOCUMENT}}.dvi
    46         dvips $< -o $@
     52${BASE}.ps : ${BASE}.dvi
     53        dvips ${Build}/$< -o $@
    4754
    48 ${basename ${DOCUMENT}}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} ${basename ${DOCUMENT}}.tex \
    49                 $(MACROS)/common.tex $(MACROS)/indexstyle $(BIB)/cfa.bib
     55${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/indexstyle ${Bib}/pl.bib | ${Build}
    5057        # Conditionally create an empty *.ind (index) file for inclusion until makeindex is run.
    51         if [ ! -r ${basename $@}.ind ] ; then touch ${basename $@}.ind ; fi
     58        #if [ ! -r ${basename $@}.ind ] ; then touch ${Build}/${basename $@}.ind ; fi
    5259        # Must have *.aux file containing citations for bibtex
    5360        if [ ! -r ${basename $@}.aux ] ; then ${LaTeX} ${basename $@}.tex ; fi
    54         -${BibTeX} ${basename $@}
    55         # Some citations reference others so run steps again to resolve these citations
     61        -${BibTeX} ${Build}/${basename $@}
     62        # Some citations reference others so run again to resolve these citations
    5663        ${LaTeX} ${basename $@}.tex
    57         -${BibTeX} ${basename $@}
     64        -${BibTeX} ${Build}/${basename $@}
    5865        # Make index from *.aux entries and input index at end of document
    59         makeindex -s $(MACROS)/indexstyle ${basename $@}.idx
     66        #makeindex -s ${Macros}/indexstyle ${Build}/${basename $@}.idx
     67        # Run again to finish citations
    6068        ${LaTeX} ${basename $@}.tex
    6169        # Run again to get index title into table of contents
     
    6775## Define the default recipes.
    6876
    69 %.tex : %.fig
    70         fig2dev -L eepic $< > $@
     77${Build}:
     78        mkdir -p ${Build}
    7179
    72 %.ps : %.fig
    73         fig2dev -L ps $< > $@
     80%.tex : %.fig | ${Build}
     81        fig2dev -L eepic $< > ${Build}/$@
    7482
    75 %.pstex : %.fig
    76         fig2dev -L pstex $< > $@
    77         fig2dev -L pstex_t -p $@ $< > $@_t
     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
    7889
    7990# Local Variables: #
  • doc/proposals/tuples/tuples.tex

    r7951100 rb067d9b  
    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 
    91\documentclass[twoside,11pt]{article}
    102
     
    157\usepackage{textcomp}
    168\usepackage[latin1]{inputenc}
     9
    1710\usepackage{fullpage,times,comment}
    1811\usepackage{epic,eepic}
    19 \usepackage{upquote}                                                                    % switch curled `'" to straight
     12\usepackage{upquote}                                    % switch curled `'" to straight
    2013\usepackage{calc}
    2114\usepackage{xspace}
    2215\usepackage{graphicx}
    23 \usepackage{varioref}                                                                   % extended references
    24 \usepackage{listings}                                                                   % format program code
    25 \usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
     16\usepackage{varioref}                                   % extended references
     17\usepackage{listings}                                   % format program code
     18\usepackage[flushmargin]{footmisc}                      % support label/reference in footnote
    2619\usepackage{latexsym}                                   % \Box glyph
    2720\usepackage{mathptmx}                                   % better math font with "times"
     
    3427\renewcommand{\UrlFont}{\small\sf}
    3528
    36 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
     29\setlength{\topmargin}{-0.45in}                         % move running title into header
    3730\setlength{\headsep}{0.25in}
    3831
     
    4235
    4336\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
    4447
    4548\title{
  • doc/proposals/user_conversions.md

    r7951100 rb067d9b  
    55There is also a set of _explicit_ conversions that are only allowed through a
    66cast expression.
    7 Based on Glen's notes on conversions [1], I propose that safe and unsafe
    8 conversions be expressed as constructor variants, though I make explicit
    9 (cast) conversions a constructor variant as well rather than a dedicated
    10 operator.
     7I propose that safe, unsafe, and explicit (cast) conversions be expressed as
     8constructor variants.
    119Throughout this article, I will use the following operator names for
    1210constructors and conversion functions from `From` to `To`:
    1311
    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 
    22 Glen's design made no distinction between constructors and unsafe implicit
     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
     18It has been suggested that all constructors would define unsafe implicit
    2319conversions; this is elegant, but interacts poorly with tuples.
    2420Essentially, without making this distinction, a constructor like the following
     
    2622multiplying the space of possible interpretations of all functions:
    2723
    28         void ?{}( Coord *this, int x, int y );
     24        void ?{}( Coord& this, int x, int y );
    2925
    3026That said, it would certainly be possible to make a multiple-argument implicit
     
    3228used infrequently:
    3329
    34         void ?{unsafe}( Coord *this, int x, int y );
     30        void ?{unsafe}( Coord& this, int x, int y );
    3531
    3632An alternate possibility would be to only count two-arg constructors
    37 `void ?{} ( To*, From )` as unsafe conversions; under this semantics, safe and
     33`void ?{} ( To&, From )` as unsafe conversions; under this semantics, safe and
    3834explicit conversions should also have a compiler-enforced restriction to
    3935ensure that they are two-arg functions (this restriction may be valuable
     
    4339is convertable to `To`.
    4440If user-defined conversions are not added to the language,
    45 `void ?{} ( To*, From )` may be a suitable representation, relying on
     41`void ?{} ( To&, From )` may be a suitable representation, relying on
    4642conversions on the argument types to account for transitivity.
    47 On the other hand, `To*` should perhaps match its target type exactly, so
    48 another assertion syntax specific to conversions may be required, e.g.
    49 `From -> To`.
     43Since `To&` should be an exact match on `To`, this should put all the implicit
     44conversions on the RHS.
     45On the other hand, under some models (like [1]), implicit conversions are not
     46allowed in assertion parameters, so another assertion syntax specific to
     47conversions may be required, e.g. `From -> To`.
     48It has also been suggested that, for programmer control, no implicit
     49conversions (except, possibly, for polymorphic specialization) should be
     50allowed in resolution of cast operators.
     51
     52[1] ../working/assertion_resolution.md
    5053
    5154### Constructor Idiom ###
     
    5356that we can use the full range of Cforall features for conversions, including
    5457polymorphism.
    55 Glen [1] defines a _constructor idiom_ that can be used to create chains of
    56 safe conversions without duplicating code; given a type `Safe` which members
    57 of another type `From` can be directly converted to, the constructor idiom
    58 allows 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 ) {
     58In an earlier version of this proposal, Glen Ditchfield defines a
     59_constructor idiom_ that can be used to create chains of safe conversions
     60without 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
     62a 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 ) {
    6266                Safe tmp = /* some expression involving that */;
    63                 *this = tmp; // uses assertion parameter
     67                this{ tmp }; // initialize from assertion parameter
    6468        }
    6569
     
    6771unsafe conversions.
    6872
     73Glen's original suggestion said the copy constructor for `To` should also be
     74accepted as a resolution for `void ?{safe}( To&, Safe )` (`Safe` == `To`),
     75allowing this same code to be used for the single-step conversion as well.
     76This proposal does come at the cost of an extra copy initialization of the
     77target value, though.
     78
     79Contrariwise, if a monomorphic conversion from `From` to `Safe` is written,
     80e.g:
     81
     82        void ?{safe}( Safe& this, From that ) {
     83                this{ /* some parameters involving that */ };
     84        }
     85
     86Then the code for a transitive conversion from `From` to any `To` type
     87convertable 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
     95Given the entirely-boilerplate nature of this code, but negative performance
     96implications of the unmodified constructor idiom, it might be fruitful to have
     97transitive and single step conversion operators, and let CFA build the
     98transitive 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
    69103What selective non-use of the constructor idiom gives us is the ability to
    70104define a conversion that may only be the *last* conversion in a chain of such.
    71 Constructing a conversion graph able to unambiguously represent the full
    72 hierarchy of implicit conversions in C is provably impossible using only
    73 single-step conversions with no additional information (see Appendix A), but
    74 this mechanism is sufficiently powerful (see [1], though the design there has
    75 some minor bugs; the general idea is to use the constructor idiom to define
    76 two chains of conversions, one among the signed integral types, another among
    77 the unsigned, and to use monomorphic conversions to allow conversions between
    78 signed and unsigned integer types).
     105One use for this is to solve the problem that `explicit` conversions were
     106added to C++ for, that of conversions to `bool` chaining to become conversions
     107to any arithmetic type.
     108Another use is to unambiguously represent the full hierarchy of implicit
     109conversions in C by making sign conversions non-transitive, allowing the
     110compiler to resolve e.g. `int -> unsigned long` as
     111`int -> long -> unsigned long` over `int -> unsigned int -> unsigned long`.
     112See [2] for more details.
     113
     114[2] ../working/glen_conversions/index.html#usual
    79115
    80116### Appendix A: Partial and Total Orders ###
     
    153189convert from `int` to `unsigned long`, so we just put in a direct conversion
    154190and make the compiler smart enough to figure out the costs" - this is the
    155 approach taken by the existing compipler, but given that in a user-defined
     191approach taken by the existing compiler, but given that in a user-defined
    156192conversion proposal the users can build an arbitrary graph of conversions,
    157193this case still needs to be handled.
     
    160196exists a chain of conversions from `a` to `b` (see Appendix A for description
    161197of preorders and related constructs).
    162 This preorder corresponds roughly to a more usual type-theoretic concept of
     198This preorder roughly corresponds to a more usual type-theoretic concept of
    163199subtyping ("if I can convert `a` to `b`, `a` is a more specific type than
    164200`b`"); however, since this graph is arbitrary, it may contain cycles, so if
     
    192228and so is considered to be the nearer type.
    193229By transitivity, then, the conversion from `X` to `Y2` should be cheaper than
    194 the conversion from `X` to `W`, but in this case the `X` and `W` are
     230the conversion from `X` to `W`, but in this case the `Y2` and `W` are
    195231incomparable by the conversion preorder, so the tie is broken by the shorter
    196232path from `X` to `W` in favour of `W`, contradicting the transitivity property
  • doc/refrat/Makefile

    r7951100 rb067d9b  
    5353        dvips ${Build}/$< -o $@
    5454
    55 ${BASE}.dvi : Makefile ${Build} ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
    56                 ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib
     55${BASE}.dvi : Makefile ${GRAPHS} ${PROGRAMS} ${PICTURES} ${FIGURES} ${SOURCES} \
     56                ${Macros}/common.tex ${Macros}/lstlang.sty ${Macros}/indexstyle ../bibliography/pl.bib | ${Build}
    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

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

    r7951100 rb067d9b  
    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 : Sun May  6 10:33:53 2018
    14 %% Update Count     : 3319
     13%% Last Modified On : Sat Jul 13 18:36:18 2019
     14%% Update Count     : 3876
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    7272
    7373% Names used in the document.
    74 \newcommand{\Version}{\input{../../version}}
     74\newcommand{\Version}{\input{build/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 parametric-polymorphic routines and types, exceptions, concurrency, and modules.
     148The primary new features include 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{}} 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, all of which requires significant effort and training to incrementally add \CC to a C-based project.
     157\Index*[C++]{\CC{}}~\cite{c++:v1} 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, requiring 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 \CFA, C, and \CC I/O mechanisms, where the programs output the same result.
    163 \begin{cquote}
     162For example, the following programs compare the C, \CFA, and \CC I/O mechanisms, where the programs output the same result.
     163\begin{center}
    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 | endl;®§\indexc{sout}§
     180        ®sout | x | y | z;®§\indexc{sout}§
    181181}
    182182\end{cfa}
     
    191191\end{cfa}
    192192\end{tabular}
    193 \end{cquote}
     193\end{center}
    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
    196197\subsection{Background}
    197198
    198199This document is a programmer reference-manual for the \CFA programming language.
    199 The manual covers the core features of the language and runtime-system, with simple examples illustrating syntax and semantics of each feature.
     200The manual covers the core features of the language and runtime-system, with simple examples illustrating syntax and semantics of features.
    200201The manual does not teach programming, \ie how to combine the new constructs to build complex programs.
    201 A 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.
     202The 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.
    202203Implementers should refer to the \CFA Programming Language Specification for details about the language syntax and semantics.
    203204Changes to the syntax and additional features are expected to be included in later revisions.
     
    206207\section{Why fix C?}
    207208
    208 The 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.
     209The 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.
    209210This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    210211Even with all its problems, C continues to be popular because it allows writing software at virtually any level in a computer system without restriction.
    211212For system programming, where direct access to hardware, storage management, and real-time issues are a requirement, C is usually the only language of choice.
    212 The 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.
    213 As well, for 30 years, C has been the number 1 and 2 most popular programming language:
     213The 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.
     214The top 3 rankings over the past 30 years are:
    214215\begin{center}
    215 \setlength{\tabcolsep}{1.5ex}
    216 \begin{tabular}{@{}r|c|c|c|c|c|c|c@{}}
    217 Ranking & 2016  & 2011  & 2006  & 2001  & 1996  & 1991  & 1986          \\
    218 \hline
    219 Java    & 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                     \\
     216\setlength{\tabcolsep}{10pt}
     217\begin{tabular}{@{}rccccccc@{}}
     218                & 2018  & 2013  & 2008  & 2003  & 1998  & 1993  & 1988  \\ \hline
     219Java    & 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             \\
    224222\end{tabular}
    225223\end{center}
    226224Hence, 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.
    227225Love it or hate it, C has been an important and influential part of computer science for 40 years and its appeal is not diminishing.
    228 Unfortunately, C has many problems and omissions that make it an unacceptable programming language for modern needs.
     226Nevertheless, C has many problems and omissions that make it an unacceptable programming language for modern needs.
    229227
    230228As stated, the goal of the \CFA project is to engineer modern language-features into C in an evolutionary rather than revolutionary way.
     
    236234These 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.
    237235As a result, there is a significant learning curve to move to these languages, and C legacy-code must be rewritten.
    238 These 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 
    240 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 containing modern language-features.
    241 Without significant extension to the C programming language, it is becoming unable to cope with the needs of modern programming problems and programmers;
     236These 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
     238The 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.
     239To achieve these goals required a significant engineering exercise, where we had to ``think inside the existing C box''.
     240Without these significant extension to C, it is unable to cope with the needs of modern programming problems and programmers;
    242241as a result, it will fade into disuse.
    243242Considering the large body of existing C code and programmers, there is significant impetus to ensure C is transformed into a modern programming language.
     
    255254\begin{lstlisting}
    256255®forall( otype T )® T identity( T val ) { return val; }
    257 int forty_two = identity( 42 );                 §\C{// T is bound to int, forty\_two == 42}§
     256int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
    258257\end{lstlisting}
    259258% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
     
    283282
    284283double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    285 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp );      §\C{// search sorted array}§
     284double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
    286285\end{lstlisting}
    287286which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
     
    292291
    293292forall( otype T | { int ?<?( T, T ); } ) unsigned int bsearch( T key, const T * arr, size_t size ) {
    294         T * result = bsearch( key, arr, size ); §\C{// call first version}§
    295         return result ? result - arr : size; }  §\C{// pointer subtraction includes sizeof(T)}§
    296 
    297 double * val = bsearch( 5.0, vals, 10 );        §\C{// selection based on return type}§
     293        T * result = bsearch( key, arr, size ); §\C{// call first version}§
     294        return result ? result - arr : size; } §\C{// pointer subtraction includes sizeof(T)}§
     295
     296double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
    298297int posn = bsearch( 5.0, vals, 10 );
    299298\end{lstlisting}
     
    307306\begin{lstlisting}
    308307forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    309 int * ip = malloc();                                    §\C{// select type and size from left-hand side}§
     308int * ip = malloc(); §\C{// select type and size from left-hand side}§
    310309double * dp = malloc();
    311310struct S {...} * sp = malloc();
     
    318317Whereas, \CFA wraps each of these routines into ones with the overloaded name ©abs©:
    319318\begin{cfa}
    320 char abs( char );
    321 ®extern "C" {® int abs( int ); ®}®              §\C{// use default C routine for int}§
    322 long int abs( long int );
    323 long long int abs( long long int );
    324 float abs( float );
    325 double abs( double );
    326 long double abs( long double );
    327 float _Complex abs( float _Complex );
    328 double _Complex abs( double _Complex );
    329 long double _Complex abs( long double _Complex );
     319char ®abs®( char );
     320extern "C" { int ®abs®( int ); } §\C{// use default C routine for int}§
     321long int ®abs®( long int );
     322long long int ®abs®( long long int );
     323float ®abs®( float );
     324double ®abs®( double );
     325long double ®abs®( long double );
     326float _Complex ®abs®( float _Complex );
     327double _Complex ®abs®( double _Complex );
     328long double _Complex ®abs®( long double _Complex );
    330329\end{cfa}
    331330The problem is the name clash between the library routine ©abs© and the \CFA names ©abs©.
    332331Hence, names appearing in an ©extern "C"© block have \newterm*{C linkage}.
    333332Then 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.
    334 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.
    335 There is no way around this problem, other than C's approach of creating unique names for each pairing of operation and type.
     333Hence, 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.
     334There is no way around this problem, other than C's approach of creating unique names for each pairing of operation and types.
    336335
    337336This example strongly illustrates a core idea in \CFA: \emph{the \Index{power of a name}}.
     
    350349\begin{description}
    351350\item
    352 \Indexc{-std=gnu99}\index{compilation option!-std=gnu99@{©-std=gnu99©}}
    353 The 1999 C standard plus GNU extensions.
    354 \item
    355 \Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline]@-fgnu89-inline@}}
    356 Use the traditional GNU semantics for inline routines in C99 mode, which allows inline routines in header files.
     351\Indexc{-std=gnu11}\index{compilation option!-std=gnu11@{©-std=gnu11©}}
     352The 2011 C standard plus GNU extensions.
     353\item
     354\Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline]$-fgnu89-inline$}}
     355Use the traditional GNU semantics for inline routines in C11 mode, which allows inline routines in header files.
    357356\end{description}
    358357The following new \CFA options are available:
     
    427426\begin{cfa}
    428427#ifndef __CFORALL__
    429 #include <stdio.h>§\indexc{stdio.h}§    §\C{// C header file}§
     428#include <stdio.h>§\indexc{stdio.h}§ §\C{// C header file}§
    430429#else
    431 #include <fstream>§\indexc{fstream}§    §\C{// \CFA header file}§
     430#include <fstream>§\indexc{fstream}§ §\C{// \CFA header file}§
    432431#endif
    433432\end{cfa}
    434 which conditionally includes the correct header file, if the program is compiled using \Indexc{gcc} or \Indexc{cfa}.
     433which conditionally includes the correct header file, if the program is compiled using \Indexc{gcc} or \Indexc{cfa}.
     434
     435The \CFA translator has multiple steps.
     436The following flags control how the tranlator works, the stages run, and printing within a stage.
     437The 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.
     512Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism:
     513\begin{cfa}
     514int ®`®otype®`® = 3; §\C{// make keyword an identifier}§
     515double ®`®forall®`® = 3.5;
     516\end{cfa}
     517
     518Existing 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©.
     520Several 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}
    435540
    436541
     
    439544Numeric constants are extended to allow \Index{underscore}s\index{constant!underscore}, \eg:
    440545\begin{cfa}
    441 2®_®147®_®483®_®648;                                    §\C{// decimal constant}§
    442 56®_®ul;                                                                §\C{// decimal unsigned long constant}§
    443 0®_®377;                                                                §\C{// octal constant}§
    444 0x®_®ff®_®ff;                                                   §\C{// hexadecimal constant}§
    445 0x®_®ef3d®_®aa5c;                                               §\C{// hexadecimal constant}§
    446 3.141®_®592®_®654;                                              §\C{// floating constant}§
    447 10®_®e®_®+1®_®00;                                               §\C{// floating constant}§
    448 0x®_®ff®_®ff®_®p®_®3;                                   §\C{// hexadecimal floating}§
    449 0x®_®1.ffff®_®ffff®_®p®_®128®_®l;               §\C{// hexadecimal floating long constant}§
    450 L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§;     §\C{// wide character constant}§
     5462®_®147®_®483®_®648; §\C{// decimal constant}§
     54756®_®ul; §\C{// decimal unsigned long constant}§
     5480®_®377; §\C{// octal constant}§
     5490x®_®ff®_®ff; §\C{// hexadecimal constant}§
     5500x®_®ef3d®_®aa5c; §\C{// hexadecimal constant}§
     5513.141®_®592®_®654; §\C{// floating constant}§
     55210®_®e®_®+1®_®00; §\C{// floating constant}§
     5530x®_®ff®_®ff®_®p®_®3; §\C{// hexadecimal floating}§
     5540x®_®1.ffff®_®ffff®_®p®_®128®_®l; §\C{// hexadecimal floating long constant}§
     555L®_®§"\texttt{\textbackslash{x}}§®_®§\texttt{ff}§®_®§\texttt{ee}"§; §\C{// wide character constant}§
    451556\end{cfa}
    452557The rules for placement of underscores are:
     
    469574
    470575
    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.
    475 Keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism:
    476 \begin{cfa}
    477 int ®`®otype®`® = 3;                    §\C{// make keyword an identifier}§
    478 double ®`®forall®`® = 3.5;
    479 \end{cfa}
    480 
    481 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.
    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©.
    483 Several common C header-files with keyword clashes are fixed in the standard \CFA header-library, so there is a seamless programming-experience.
     576\section{Exponentiation Operator}
     577
     578C, \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$.
     580The 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)©.
     581
     582As for \Index{division}, there are exponentiation operators for integral and floating types, including the builtin \Index{complex} types.
     583Integral 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).
     584Overflow from large exponents or negative exponents return zero.
     585Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the exponent cannot be negative.
     586\begin{cfa}
     587sout | 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);
     5891 1 256 -64 125 ®0® 3273344365508751233 ®0® ®0® -0.015625 18.3791736799526 0.264715-1.1922i
     590\end{cfa}
     591Note, ©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.
     592Parenthesis are necessary for complex constants or the expression is parsed as ©1.0f+®(®2.0fi \ 3.0f®)®+2.0fi©.
     593The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation version is available.
     594\begin{cfa}
     595forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } )
     596OT ?®\®?( OT ep, unsigned int y );
     597forall( otype OT | { void ?{}( OT & this, one_t ); OT ?*?( OT, OT ); } )
     598OT ?®\®?( OT ep, unsigned long int y );
     599\end{cfa}
     600The 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
     611The ©if©/©while© expression allows declarations, similar to ©for© declaration expression.
     612(Does not make sense for ©do©-©while©.)
     613\begin{cfa}
     614if ( ®int x = f()® ) ... §\C{// x != 0}§
     615if ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§
     616if ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§
     617if ( ®struct S { int i; } x = { f() }; x.i < 4® ) §\C{// relational expression}§
     618
     619while ( ®int x = f()® ) ... §\C{// x != 0}§
     620while ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§
     621while ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§
     622while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... §\C{// relational expression}§
     623\end{cfa}
     624Unless 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.}
     625The 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
     630The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
     631\begin{itemize}
     632\item
     633An empty conditional implies ©1©.
     634\item
     635The up-to range ©~©\index{~@©~©} means exclusive range [M,N).
     636\item
     637The up-to range ©~=©\index{~=@©~=©} means inclusive range [M,N].
     638\item
     639The down-to range ©-~©\index{-~@©-~©} means exclusive range [N,M).
     640\item
     641The 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
     649The up-to range uses ©+=© for increment;
     650\item
     651The down-to range uses ©-=© for decrement.
     652\item
     653The loop index is polymorphic in the type of the start value or comparison value when start is implicitly ©0©.
     654\end{itemize}
    484655
    485656\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}
     657\begin{cquote}
     658\begin{tabular}{@{}l|l@{}}
     659\multicolumn{1}{c|}{loop control} & \multicolumn{1}{c}{output} \\
     660\hline
     661\begin{cfa}
     662sout | nlOff;
     663while ®()® { sout | "empty"; break; } sout | nl;
     664do { sout | "empty"; break; } while ®()®; sout | nl;
     665for ®()® { sout | "empty"; break; } sout | nl;
     666for ( ®0® ) { sout | "A"; } sout | "zero" | nl;
     667for ( ®1® ) { sout | "A"; } sout | nl;
     668for ( ®10® ) { sout | "A"; } sout | nl;
     669for ( ®1 ~= 10 ~ 2® ) { sout | "B"; } sout | nl;
     670for ( ®10 -~= 1 ~ 2® ) { sout | "C"; } sout | nl;
     671for ( ®0.5 ~ 5.5® ) { sout | "D"; } sout | nl;
     672for ( ®5.5 -~ 0.5® ) { sout | "E"; } sout | nl;
     673for ( ®i; 10® ) { sout | i; } sout | nl;
     674for ( ®i; 1 ~= 10 ~ 2® ) { sout | i; } sout | nl;
     675for ( ®i; 10 -~= 1 ~ 2® ) { sout | i; } sout | nl;
     676for ( ®i; 0.5 ~ 5.5® ) { sout | i; } sout | nl;
     677for ( ®i; 5.5 -~ 0.5® ) { sout | i; } sout | nl;
     678for ( ®ui; 2u ~= 10u ~ 2u® ) { sout | ui; } sout | nl;
     679for ( ®ui; 10u -~= 2u ~ 2u® ) { sout | ui; } sout | nl;
     680enum { N = 10 };
     681for ( ®N® ) { sout | "N"; } sout | nl;
     682for ( ®i; N® ) { sout | i; } sout | nl;
     683for ( ®i; N -~ 0® ) { sout | i; } sout | nl;
     684const int start = 3, comp = 10, inc = 2;
     685for ( ®i; start ~ comp ~ inc + 1® ) { sout | i; } sout | nl;
     686for ( ®i; 1 ~ @® ) { if ( i > 10 ) break;
     687        sout | i; } sout | nl;
     688for ( ®i; 10 -~ @® ) { if ( i < 0 ) break;
     689        sout | i; } sout | nl;
     690for ( ®i; 2 ~ @ ~ 2® ) { if ( i > 10 ) break;
     691        sout | i; } sout | nl;
     692for ( ®i; 2.1 ~ @ ~ @® ) { if ( i > 10.5 ) break;
     693        sout | i; i += 1.7; } sout | nl;
     694for ( ®i; 10 -~ @ ~ 2® ) { if ( i < 0 ) break;
     695        sout | i; } sout | nl;
     696for ( ®i; 12.1 ~ @ ~ @® ) { if ( i < 2.5 ) break;
     697        sout | i; i -= 1.7; } sout | nl;
     698for ( ®i; 5 : j; -5 ~ @® ) { sout | i | j; } sout | nl;
     699for ( ®i; 5 : j; -5 -~ @® ) { sout | i | j; } sout | nl;
     700for ( ®i; 5 : j; -5 ~ @ ~ 2® ) { sout | i | j; } sout | nl;
     701for ( ®i; 5 : j; -5 -~ @ ~ 2® ) { sout | i | j; } sout | nl;
     702for ( ®j; -5 ~ @ : i; 5® ) { sout | i | j; } sout | nl;
     703for ( ®j; -5 -~ @ : i; 5® ) { sout | i | j; } sout | nl;
     704for ( ®j; -5 ~ @ ~ 2 : i; 5® ) { sout | i | j; } sout | nl;
     705for ( ®j; -5 -~ @ ~ 2 : i; 5® ) { sout | i | j; } sout | nl;
     706for ( ®j; -5 -~ @ ~ 2 : i; 5 : k; 1.5 ~ @® ) {
     707        sout | i | j | k; } sout | nl;
     708for ( ®j; -5 -~ @ ~ 2 : k; 1.5 ~ @ : i; 5® ) {
     709        sout | i | j | k; } sout | nl;
     710for ( ®k; 1.5 ~ @ : j; -5 -~ @ ~ 2 : i; 5® ) {
     711        sout | i | j | k; } sout | nl;
     712\end{cfa}
     713&
     714\begin{cfa}
     715
     716empty
     717empty
     718empty
     719zero
     720A
     721A A A A A A A A A A
     722B B B B B
     723C C C C C
     724D D D D D
     725E E E E E
     7260 1 2 3 4 5 6 7 8 9
     7271 3 5 7 9
     72810 8 6 4 2
     7290.5 1.5 2.5 3.5 4.5
     7305.5 4.5 3.5 2.5 1.5
     7312 4 6 8 10
     73210 8 6 4 2
     733
     734N N N N N N N N N N
     7350 1 2 3 4 5 6 7 8 9
     73610 9 8 7 6 5 4 3 2 1
     737
     7383 6 9
     739
     7401 2 3 4 5 6 7 8 9 10
     741
     74210 9 8 7 6 5 4 3 2 1 0
     743
     7442 4 6 8 10
     745
     7462.1 3.8 5.5 7.2 8.9
     747
     74810 8 6 4 2 0
     749
     75012.1 10.4 8.7 7 5.3 3.6
     7510 -5 1 -4 2 -3 3 -2 4 -1
     7520 -5 1 -6 2 -7 3 -8 4 -9
     7530 -5 1 -3 2 -1 3 1 4 3
     7540 -5 1 -7 2 -9 3 -11 4 -13
     7550 -5 1 -4 2 -3 3 -2 4 -1
     7560 -5 1 -6 2 -7 3 -8 4 -9
     7570 -5 1 -3 2 -1 3 1 4 3
     7580 -5 1 -7 2 -9 3 -11 4 -13
     759
     7600 -5 1.5 1 -7 2.5 2 -9 3.5 3 -11 4.5 4 -13 5.5
     761
     7620 -5 1.5 1 -7 2.5 2 -9 3.5 3 -11 4.5 4 -13 5.5
     763
     7640 -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}
    502770\end{figure}
    503771
    504772
    505 \section{Exponentiation Operator}
    506 
    507 C, \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.
    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$.
    509 The 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)©.
    510 
    511 As for \Index{division}, there are exponentiation operators for integral and floating types, including the builtin \Index{complex} types.
    512 Unsigned 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).
    513 Signed 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$.
    514 Hence, 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.
    515 Floating exponentiation\index{exponentiation!floating} is performed using \Index{logarithm}s\index{exponentiation!logarithm}, so the base cannot be negative.
    516 \begin{cfa}
    517 sout | 2 ®\® 8u | 4 ®\® 3u | -4 ®\® 3u | 4 ®\® -3 | -4 ®\® -3 | 4.0 ®\® 2.1 | (1.0f+2.0fi) ®\® (3.0f+2.0fi) | endl;
    518 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i
    519 \end{cfa}
    520 Parenthesis are necessary for the complex constants or the expresion is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©.
    521 The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available.
    522 For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©;
    523 for 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}}
     773%\section{\texorpdfstring{\protect\lstinline@switch@ Statement}{switch Statement}}
     774\subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}}
     775
     776C allows a number of questionable forms for the ©switch© statement:
     777\begin{enumerate}
     778\item
     779By default, the end of a ©case© clause\footnote{
     780In 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;
     782to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©:
     783\begin{cfa}
     784switch ( i ) {
     785  case 1:
     786        ...
     787        // fall-through
     788  case 2:
     789        ...
     790        break;  // exit switch statement
     791}
     792\end{cfa}
     793The 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}
     797switch ( 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
     811if ( 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}
     823In this example, case 2 is always done if case 3 is done.
     824This 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.
     825C also uses fall-through to handle multiple case-values resulting in the same action:
     826\begin{cfa}
     827switch ( 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}
     836However, this situation is handled in other languages without fall-through by allowing a list of case values.
     837While 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.
     838Hence, 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
     841It is possible to place ©case© clauses on statements nested \emph{within} the body of the ©switch© statement:
     842\begin{cfa}
     843switch ( 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}
     858The problem with this usage is branching into control structures, which is known to cause both comprehension and technical difficulties.
     859The comprehension problem occurs from the inability to determine how control reaches a particular point due to the number of branches leading to it.
     860The technical problem results from the inability to ensure declaration and initialization of variables when blocks are not entered at the beginning.
     861There are no positive arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it.
     862Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}:
     863\begin{cfa}
     864register int n = (count + 7) / 8;
     865switch ( count % 8 ) {
     866case 0: do{ *to = *from++;
     867case 7:         *to = *from++;
     868case 6:         *to = *from++;
     869case 5:         *to = *from++;
     870case 4:         *to = *from++;
     871case 3:         *to = *from++;
     872case 2:         *to = *from++;
     873case 1:         *to = *from++;
     874                } while ( --n > 0 );
     875}
     876\end{cfa}
     877which unrolls a loop N times (N = 8 above) and uses the ©switch© statement to deal with any iterations not a multiple of N.
     878While efficient, this sort of special purpose usage is questionable:
     879\begin{quote}
     880Disgusting, no? But it compiles and runs just fine. I feel a combination of pride and revulsion at this
     881discovery.~\cite{Duff83}
     882\end{quote}
     883\item
     884It is possible to place the ©default© clause anywhere in the list of labelled clauses for a ©switch© statement, rather than only at the end.
     885Virtually all programming languages with a ©switch© statement require the ©default© clause to appear last in the case-clause list.
     886The logic for this semantics is that after checking all the ©case© clauses without success, the ©default© clause is selected;
     887hence, physically placing the ©default© clause at the end of the ©case© clause list matches with this semantics.
     888This 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
     891It is possible to place unreachable code at the start of a ©switch© statement, as in:
     892\begin{cfa}
     893switch ( 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}
     904While 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.
     905Furthermore, 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.
     906As 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.
     907The 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
     910Before discussing potential language changes to deal with these problems, it is worth observing that in a typical C program:
     911\begin{itemize}
     912\item
     913the number of ©switch© statements is small,
     914\item
     915most ©switch© statements are well formed (\ie no \Index*{Duff's device}),
     916\item
     917the ©default© clause is usually written as the last case-clause,
     918\item
     919and 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}
     921These observations put into perspective the \CFA changes to the ©switch©.
     922\begin{enumerate}
     923\item
     924Eliminating default fall-through has the greatest potential for affecting existing code.
     925However, 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}
     927case 1:  case 2:  case 3: ...
     928\end{cfa}
     929still works.
     930Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments.
     931Therefore, 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}
     947Like the ©switch© statement, the ©choose© statement retains the fall-through semantics for a list of ©case© clauses;
     948An implicit ©break© is applied only at the end of the \emph{statements} following a ©case© clause.
     949An 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.
     950As 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.
     953Hence, 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
     955The 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.
     956Therefore, no change is made for this issue.
     957\item
     958Dealing 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{
     959Essentially, 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.
     960Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound.
     961\begin{cfa}
     962switch ( 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
     982C restricts the ©case© clause of a ©switch© statement to a single value.
     983For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values.
     984Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C.
     985Therefore, 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}
     990switch ( i ) {
     991  case ®1, 3, 5®:
     992        ...
     993  case ®2, 4, 6®:
     994        ...
     995}
     996\end{cfa}
     997&
     998\begin{cfa}
     999switch ( 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}
     1017In addition, subranges are allowed to specify case values.\footnote{
     1018gcc 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}
     1020switch ( 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}
     1027Lists of subranges are also allowed.
     1028\begin{cfa}
     1029case ®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}}
    5271044
    5281045While C provides ©continue© and ©break© statements for altering control flow, both are restricted to one level of nesting for a particular control structure.
    5291046Unfortunately, this restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting.
    530 To 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.
     1047To 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.
    5311048For both ©continue© and ©break©, the target label must be directly associated with a ©for©, ©while© or ©do© statement;
    5321049for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
     
    6131130\end{figure}
    6141131
    615 Both labelled ©continue© and ©break© are a ©goto©\index{goto@\lstinline@goto@!restricted} restricted in the following ways:
     1132Both labelled ©continue© and ©break© are a ©goto©\index{goto@©goto©!restricted} restricted in the following ways:
    6161133\begin{itemize}
    6171134\item
     
    6261143With ©goto©, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader.
    6271144Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs.
    628 The 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 
    633 C allows a number of questionable forms for the ©switch© statement:
    634 \begin{enumerate}
    635 \item
    636 By default, the end of a ©case© clause\footnote{
    637 In 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;
    639 to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©:
    640 \begin{cfa}
    641 switch ( i ) {
    642   case 1:
    643         ...
    644         // fall-through
    645   case 2:
    646         ...
    647         break;  // exit switch statement
    648 }
    649 \end{cfa}
    650 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:
    651 \begin{cquote}
    652 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    653 \begin{cfa}
    654 switch ( 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 
    668 if ( 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}
    680 In this example, case 2 is always done if case 3 is done.
    681 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.
    682 C also uses fall-through to handle multiple case-values resulting in the same action:
    683 \begin{cfa}
    684 switch ( 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}
    693 However, this situation is handled in other languages without fall-through by allowing a list of case values.
    694 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.
    695 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.
    696 
    697 \item
    698 It is possible to place ©case© clauses on statements nested \emph{within} the body of the ©switch© statement:
    699 \begin{cfa}
    700 switch ( 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}
    715 The problem with this usage is branching into control structures, which is known to cause both comprehension and technical difficulties.
    716 The comprehension problem occurs from the inability to determine how control reaches a particular point due to the number of branches leading to it.
    717 The technical problem results from the inability to ensure declaration and initialization of variables when blocks are not entered at the beginning.
    718 There are no positive arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it.
    719 Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}:
    720 \begin{cfa}
    721 register int n = (count + 7) / 8;
    722 switch ( count % 8 ) {
    723 case 0: do{ *to = *from++;
    724 case 7:         *to = *from++;
    725 case 6:         *to = *from++;
    726 case 5:         *to = *from++;
    727 case 4:         *to = *from++;
    728 case 3:         *to = *from++;
    729 case 2:         *to = *from++;
    730 case 1:         *to = *from++;
    731                 } while ( --n > 0 );
    732 }
    733 \end{cfa}
    734 which unrolls a loop N times (N = 8 above) and uses the ©switch© statement to deal with any iterations not a multiple of N.
    735 While efficient, this sort of special purpose usage is questionable:
    736 \begin{quote}
    737 Disgusting, no? But it compiles and runs just fine. I feel a combination of pride and revulsion at this
    738 discovery.~\cite{Duff83}
    739 \end{quote}
    740 \item
    741 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.
    742 Virtually all programming languages with a ©switch© statement require the ©default© clause to appear last in the case-clause list.
    743 The logic for this semantics is that after checking all the ©case© clauses without success, the ©default© clause is selected;
    744 hence, physically placing the ©default© clause at the end of the ©case© clause list matches with this semantics.
    745 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.
    746 
    747 \item
    748 It is possible to place unreachable code at the start of a ©switch© statement, as in:
    749 \begin{cfa}
    750 switch ( 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}
    761 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.
    762 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.
    763 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.
    764 The 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 
    767 Before discussing potential language changes to deal with these problems, it is worth observing that in a typical C program:
    768 \begin{itemize}
    769 \item
    770 the number of ©switch© statements is small,
    771 \item
    772 most ©switch© statements are well formed (\ie no \Index*{Duff's device}),
    773 \item
    774 the ©default© clause is usually written as the last case-clause,
    775 \item
    776 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.
    777 \end{itemize}
    778 These observations put into perspective the \CFA changes to the ©switch©.
    779 \begin{enumerate}
    780 \item
    781 Eliminating default fall-through has the greatest potential for affecting existing code.
    782 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:
    783 \begin{cfa}
    784 case 1:  case 2:  case 3: ...
    785 \end{cfa}
    786 still works.
    787 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.
    788 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:
    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}
    804 Like the ©switch© statement, the ©choose© statement retains the fall-through semantics for a list of ©case© clauses;
    805 An implicit ©break© is applied only at the end of the \emph{statements} following a ©case© clause.
    806 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.
    807 As 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.
    810 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.
    811 \item
    812 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.
    813 Therefore, no change is made for this issue.
    814 \item
    815 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{
    816 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.
    817 Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound.
    818 \begin{cfa}
    819 switch ( 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 
    838 C restricts the ©case© clause of a ©switch© statement to a single value.
    839 For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values.
    840 Requiring a ©case© clause for each value does not seem to be in the spirit of brevity normally associated with C.
    841 Therefore, 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}
    846 switch ( i ) {
    847   case ®1, 3, 5®:
    848         ...
    849   case ®2, 4, 6®:
    850         ...
    851 }
    852 \end{cfa}
    853 &
    854 \begin{cfa}
    855 switch ( 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}
    873 In addition, subranges are allowed to specify case values.\footnote{
    874 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.}
    875 \begin{cfa}
    876 switch ( 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}
    883 Lists of subranges are also allowed.
    884 \begin{cfa}
    885 case ®1~5, 12~21, 35~42®:
    886 \end{cfa}
    887 
    888 
    889 \section{\texorpdfstring{\protect\lstinline@with@ Statement}{with Statement}}
     1145Otherwise, 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}}
    8901150\label{s:WithStatement}
    8911151
    8921152Grouping 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:
    8931153\begin{cfa}
    894 struct S {                                                                      §\C{// aggregate}§
    895         char c;                                                                 §\C{// fields}§
     1154struct S { §\C{// aggregate}§
     1155        char c; §\C{// fields}§
    8961156        int i;
    8971157        double d;
     
    9021162\begin{cfa}
    9031163void f( S s ) {
    904         `s.`c; `s.`i; `s.`d;                                    §\C{// access containing fields}§
     1164        ®s.®c; ®s.®i; ®s.®d; §\C{// access containing fields}§
    9051165}
    9061166\end{cfa}
     
    9091169\begin{C++}
    9101170struct S {
    911         char c;                                                                 §\C{// fields}§
     1171        char c; §\C{// fields}§
    9121172        int i;
    9131173        double d;
    914         void f() {                                                              §\C{// implicit ``this'' aggregate}§
    915                 `this->`c; `this->`i; `this->`d;        §\C{// access containing fields}§
     1174        void f() { §\C{// implicit ``this'' aggregate}§
     1175                ®this->®c; ®this->®i; ®this->®d; §\C{// access containing fields}§
    9161176        }
    9171177}
    9181178\end{C++}
    919 Object-oriented nesting of member functions in a \lstinline[language=C++]@class/struct@ allows eliding \lstinline[language=C++]$this->$ because of lexical scoping.
     1179Object-oriented nesting of member functions in a \lstinline[language=C++]@class/struct@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.
    9201180However, for other aggregate parameters, qualification is necessary:
    9211181\begin{cfa}
    9221182struct T { double m, n; };
    923 int 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 
    929 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.
     1183int 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
     1189To 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.
    9301190Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block.
    9311191\begin{cfa}
    932 void f( S & this ) `with ( this )` {            §\C{// with statement}§
    933         c; i; d;                                                                §\C{\color{red}// this.c, this.i, this.d}§
     1192void f( S & this ) ®with ( this )® { §\C{// with statement}§
     1193        c; i; d; §\C{\color{red}// this.c, this.i, this.d}§
    9341194}
    9351195\end{cfa}
    9361196with the generality of opening multiple aggregate-parameters:
    9371197\begin{cfa}
    938 void 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 
    944 In detail, the @with@ statement has the form:
     1198void 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
     1204In detail, the ©with© statement has the form:
    9451205\begin{cfa}
    9461206§\emph{with-statement}§:
     
    9571217The difference between parallel and nesting occurs for fields with the same name and type:
    9581218\begin{cfa}
    959 struct S { int `i`; int j; double m; } s, w;
    960 struct T { int `i`; int k; int m; } t, w;
     1219struct S { int ®i®; int j; double m; } s, w;
     1220struct T { int ®i®; int k; int m; } t, w;
    9611221with ( s, t ) {
    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}
    971 For parallel semantics, both @s.i@ and @t.i@ are visible, so @i@ is ambiguous without qualification;
    972 for nested semantics, @t.i@ hides @s.i@, so @i@ implies @t.i@.
     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}
     1231For parallel semantics, both ©s.i© and ©t.i© are visible, so ©i© is ambiguous without qualification;
     1232for nested semantics, ©t.i© hides ©s.i©, so ©i© implies ©t.i©.
    9731233\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.
    9741234Qualification or a cast is used to disambiguate.
    9751235
    976 There is an interesting problem between parameters and the function-body @with@, \eg:
    977 \begin{cfa}
    978 void ?{}( S & s, int i ) with ( s ) {           §\C{// constructor}§
    979         `s.i = i;`  j = 3;  m = 5.5;                    §\C{// initialize fields}§
    980 }
    981 \end{cfa}
    982 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@.
     1236There is an interesting problem between parameters and the function-body ©with©, \eg:
     1237\begin{cfa}
     1238void ?{}( S & s, int i ) with ( s ) { §\C{// constructor}§
     1239        ®s.i = i;®  j = 3;  m = 5.5; §\C{// initialize fields}§
     1240}
     1241\end{cfa}
     1242Here, 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©.
    9831243To solve this problem, parameters are treated like an initialized aggregate:
    9841244\begin{cfa}
     
    9901250and implicitly opened \emph{after} a function-body open, to give them higher priority:
    9911251\begin{cfa}
    992 void ?{}( S & s, int `i` ) with ( s ) `with( §\emph{\color{red}params}§ )` {
    993         s.i = `i`; j = 3; m = 5.5;
    994 }
    995 \end{cfa}
    996 Finally, a cast may be used to disambiguate among overload variables in a @with@ expression:
    997 \begin{cfa}
    998 with ( w ) { ... }                                                      §\C{// ambiguous, same name and no context}§
    999 with ( (S)w ) { ... }                                           §\C{// unambiguous, cast}§
    1000 \end{cfa}
    1001 and @with@ expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate:
     1252void ?{}( S & s, int ®i® ) with ( s ) ®with( §\emph{\color{red}params}§ )® {
     1253        s.i = ®i®; j = 3; m = 5.5;
     1254}
     1255\end{cfa}
     1256Finally, a cast may be used to disambiguate among overload variables in a ©with© expression:
     1257\begin{cfa}
     1258with ( w ) { ... } §\C{// ambiguous, same name and no context}§
     1259with ( (S)w ) { ... } §\C{// unambiguous, cast}§
     1260\end{cfa}
     1261and ©with© expressions may be complex expressions with type reference (see Section~\ref{s:References}) to aggregate:
    10021262% \begin{cfa}
    10031263% struct S { int i, j; } sv;
    1004 % with ( sv ) {                                                         §\C{// implicit reference}§
     1264% with ( sv ) { §\C{// implicit reference}§
    10051265%       S & sr = sv;
    1006 %       with ( sr ) {                                                   §\C{// explicit reference}§
     1266%       with ( sr ) { §\C{// explicit reference}§
    10071267%               S * sp = &sv;
    1008 %               with ( *sp ) {                                          §\C{// computed reference}§
    1009 %                       i = 3; j = 4;                                   §\C{\color{red}// sp--{\textgreater}i, sp--{\textgreater}j}§
     1268%               with ( *sp ) { §\C{// computed reference}§
     1269%                       i = 3; j = 4; §\C{\color{red}// sp--{\textgreater}i, sp--{\textgreater}j}§
    10101270%               }
    1011 %               i = 2; j = 3;                                           §\C{\color{red}// sr.i, sr.j}§
     1271%               i = 2; j = 3; §\C{\color{red}// sr.i, sr.j}§
    10121272%       }
    1013 %       i = 1; j = 2;                                                   §\C{\color{red}// sv.i, sv.j}§
     1273%       i = 1; j = 2; §\C{\color{red}// sv.i, sv.j}§
    10141274% }
    10151275% \end{cfa}
     
    10191279class C {
    10201280        int i, 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}§
     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}§
    10241284        }
    10251285}
     
    10281288\begin{cfa}
    10291289struct S { int i, j; };
    1030 int mem( S & ®this® ) {                 §\C{// explicit "this" parameter}§
    1031         ®this.®i = 1;                           §\C{// "this" is not elided}§
     1290int mem( S & ®this® ) { §\C{// explicit "this" parameter}§
     1291        ®this.®i = 1; §\C{// "this" is not elided}§
    10321292        ®this.®j = 2;
    10331293}
     
    10381298\begin{cfa}
    10391299int mem( S & this ) ®with( this )® { §\C{// with clause}§
    1040         i = 1;                                          §\C{\color{red}// this.i}§
    1041         j = 2;                                          §\C{\color{red}// this.j}§
     1300        i = 1; §\C{\color{red}// this.i}§
     1301        j = 2; §\C{\color{red}// this.j}§
    10421302}
    10431303\end{cfa}
     
    10561316        struct S1 { ... } s1;
    10571317        struct S2 { ... } s2;
    1058         ®with( s1 )® {                          §\C{// with statement}§
     1318        ®with( s1 )® { §\C{// with statement}§
    10591319                // access fields of s1 without qualification
    1060                 ®with s2® {                             §\C{// nesting}§
     1320                ®with s2® { §\C{// nesting}§
    10611321                        // access fields of s1 and s2 without qualification
    10621322                }
     
    11131373Non-local transfer can cause stack unwinding, \ie non-local routine termination, depending on the kind of raise.
    11141374\begin{cfa}
    1115 exception_t E {};                               §\C{// exception type}§
     1375exception_t E {}; §\C{// exception type}§
    11161376void f(...) {
    1117         ... throw E{}; ...                      §\C{// termination}§
    1118         ... throwResume E{}; ...        §\C{// resumption}§
     1377        ... throw E{}; ... §\C{// termination}§
     1378        ... throwResume E{}; ... §\C{// resumption}§
    11191379}
    11201380try {
    11211381        f(...);
    1122 } catch( E e ; §boolean-predicate§ ) {                  §\C[8cm]{// termination handler}§
     1382} catch( E e ; §boolean-predicate§ ) {          §\C[8cm]{// termination handler}§
    11231383        // recover and continue
    1124 } catchResume( E e ; §boolean-predicate§ ) {    §\C{// resumption handler}\CRT§
     1384} catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§
    11251385        // repair and return
    11261386} finally {
     
    11821442For example, a routine returning a \Index{pointer} to an array of integers is defined and used in the following way:
    11831443\begin{cfa}
    1184 int ®(*®f®())[®5®]® {...};                              §\C{// definition}§
    1185  ... ®(*®f®())[®3®]® += 1;                              §\C{// usage}§
     1444int ®(*®f®())[®5®]® {...}; §\C{// definition}§
     1445 ... ®(*®f®())[®3®]® += 1; §\C{// usage}§
    11861446\end{cfa}
    11871447Essentially, the return type is wrapped around the routine name in successive layers (like an \Index{onion}).
    1188 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
     1448While 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}
     1450In 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}
    11891452
    11901453\CFA provides its own type, variable and routine declarations, using a different syntax.
     
    13721635*x = 3;                 // implicit dereference
    13731636int * ®const® y = (int *)104;
    1374 *y = *x;                // implicit dereference
     1637*y = *x;                        // implicit dereference
    13751638\end{cfa}
    13761639\end{tabular}
     
    13861649\hline
    13871650\begin{cfa}
    1388 lda             r1,100  // load address of x
    1389 ld               r2,(r1)          // load value of x
    1390 lda             r3,104  // load address of y
    1391 st               r2,(r3)          // store x into y
     1651lda             r1,100   // load address of x
     1652ld               r2,(r1)   // load value of x
     1653lda             r3,104   // load address of y
     1654st               r2,(r3)   // store x into y
    13921655\end{cfa}
    13931656&
    13941657\begin{cfa}
    13951658
    1396 ld              r2,(100)        // load value of x
    1397 
    1398 st              r2,(104)        // store x into y
     1659ld              r2,(100)   // load value of x
     1660
     1661st              r2,(104)   // store x into y
    13991662\end{cfa}
    14001663\end{tabular}
     
    14101673\begin{cfa}
    14111674int x, y, ®*® p1, ®*® p2, ®**® p3;
    1412 p1 = ®&®x;              // p1 points to x
    1413 p2 = p1;                // p2 points to x
    1414 p1 = ®&®y;              // p1 points to y
    1415 p3 = &p2;               // p3 points to p2
     1675p1 = ®&®x;    // p1 points to x
     1676p2 = p1;    // p2 points to x
     1677p1 = ®&®y;    // p1 points to y
     1678p3 = &p2;  // p3 points to p2
    14161679\end{cfa}
    14171680&
     
    14241687For example, \Index*{Algol68}~\cite{Algol68} infers pointer dereferencing to select the best meaning for each pointer usage
    14251688\begin{cfa}
    1426 p2 = p1 + x;                                    §\C{// compiler infers *p2 = *p1 + x;}§
     1689p2 = p1 + x; §\C{// compiler infers *p2 = *p1 + x;}§
    14271690\end{cfa}
    14281691Algol68 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.
    1429 Unfortunately, automatic dereferencing does not work in all cases, and so some mechanism is necessary to fix incorrect choices. 
     1692Unfortunately, automatic dereferencing does not work in all cases, and so some mechanism is necessary to fix incorrect choices.
    14301693
    14311694Rather than inferring dereference, most programming languages pick one implicit dereferencing semantics, and the programmer explicitly indicates the other to resolve address-duality.
    14321695In C, objects of pointer type always manipulate the pointer object's address:
    14331696\begin{cfa}
    1434 p1 = p2;                                                §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§
    1435 p2 = p1 + x;                                    §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§
     1697p1 = p2; §\C{// p1 = p2\ \ rather than\ \ *p1 = *p2}§
     1698p2 = p1 + x; §\C{// p2 = p1 + x\ \ rather than\ \ *p2 = *p1 + x}§
    14361699\end{cfa}
    14371700even though the assignment to ©p2© is likely incorrect, and the programmer probably meant:
    14381701\begin{cfa}
    1439 p1 = p2;                                                §\C{// pointer address assignment}§
    1440 ®*®p2 = ®*®p1 + x;                              §\C{// pointed-to value assignment / operation}§
     1702p1 = p2; §\C{// pointer address assignment}§
     1703®*®p2 = ®*®p1 + x; §\C{// pointed-to value assignment / operation}§
    14411704\end{cfa}
    14421705The 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©).
     
    14551718\begin{cfa}
    14561719int x, y, ®&® r1, ®&® r2, ®&&® r3;
    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}§
     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}§
    14611724r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15); §\C{// implicit dereferencing}§
    14621725\end{cfa}
     
    14741737For a \CFA reference type, the cancellation on the left-hand side of assignment leaves the reference as an address (\Index{lvalue}):
    14751738\begin{cfa}
    1476 (&®*®)r1 = &x;                                  §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§
     1739(&®*®)r1 = &x; §\C{// (\&*) cancel giving address in r1 not variable pointed-to by r1}§
    14771740\end{cfa}
    14781741Similarly, the address of a reference can be obtained for assignment or computation (\Index{rvalue}):
    14791742\begin{cfa}
    1480 (&(&®*®)®*®)r3 = &(&®*®)r2;             §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§
     1743(&(&®*®)®*®)r3 = &(&®*®)r2; §\C{// (\&*) cancel giving address in r2, (\&(\&*)*) cancel giving address in r3}§
    14811744\end{cfa}
    14821745Cancellation\index{cancellation!pointer/reference}\index{pointer!cancellation} works to arbitrary depth.
     
    14861749int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    14871750                 &r1 = x,    &&r2 = r1,   &&&r3 = r2;
    1488 ***p3 = 3;                                              §\C{// change x}§
    1489 r3 = 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}§
     1751***p3 = 3; §\C{// change x}§
     1752r3 = 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}§
    14951758\end{cfa}
    14961759Furthermore, both types are equally performant, as the same amount of dereferencing occurs for both types.
     
    14991762As for a pointer type, a reference type may have qualifiers:
    15001763\begin{cfa}
    1501 const int cx = 5;                                       §\C{// cannot change cx;}§
    1502 const int & cr = cx;                            §\C{// cannot change what cr points to}§
    1503 ®&®cr = &cx;                                            §\C{// can change cr}§
    1504 cr = 7;                                                         §\C{// error, cannot change cx}§
    1505 int & const rc = x;                                     §\C{// must be initialized}§
    1506 ®&®rc = &x;                                                     §\C{// error, cannot change rc}§
    1507 const int & const crc = cx;                     §\C{// must be initialized}§
    1508 crc = 7;                                                        §\C{// error, cannot change cx}§
    1509 ®&®crc = &cx;                                           §\C{// error, cannot change crc}§
     1764const int cx = 5; §\C{// cannot change cx;}§
     1765const int & cr = cx; §\C{// cannot change what cr points to}§
     1766®&®cr = &cx; §\C{// can change cr}§
     1767cr = 7; §\C{// error, cannot change cx}§
     1768int & const rc = x; §\C{// must be initialized}§
     1769®&®rc = &x; §\C{// error, cannot change rc}§
     1770const int & const crc = cx; §\C{// must be initialized}§
     1771crc = 7; §\C{// error, cannot change cx}§
     1772®&®crc = &cx; §\C{// error, cannot change crc}§
    15101773\end{cfa}
    15111774Hence, 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}:
    15121775\begin{cfa}
    1513 int & const cr = *0;                            §\C{// where 0 is the int * zero}§
     1776int & const cr = *0; §\C{// where 0 is the int * zero}§
    15141777\end{cfa}
    15151778Note, constant reference-types do not prevent \Index{addressing errors} because of explicit storage-management:
     
    15181781cr = 5;
    15191782free( &cr );
    1520 cr = 7;                                                         §\C{// unsound pointer dereference}§
     1783cr = 7; §\C{// unsound pointer dereference}§
    15211784\end{cfa}
    15221785
     
    15431806\begin{cfa}
    15441807int w, x, y, z, & ar[3] = { x, y, z }; §\C{// initialize array of references}§
    1545 &ar[1] = &w;                                            §\C{// change reference array element}§
    1546 typeof( ar[1] ) p;                                      §\C{// (gcc) is int, \ie the type of referenced object}§
    1547 typeof( &ar[1] ) q;                                     §\C{// (gcc) is int \&, \ie the type of reference}§
    1548 sizeof( ar[1] ) == sizeof( int );       §\C{// is true, \ie the size of referenced object}§
    1549 sizeof( &ar[1] ) == sizeof( int *)      §\C{// is true, \ie the size of a reference}§
     1808&ar[1] = &w; §\C{// change reference array element}§
     1809typeof( ar[1] ) p; §\C{// (gcc) is int, \ie the type of referenced object}§
     1810typeof( &ar[1] ) q; §\C{// (gcc) is int \&, \ie the type of reference}§
     1811sizeof( ar[1] ) == sizeof( int ); §\C{// is true, \ie the size of referenced object}§
     1812sizeof( &ar[1] ) == sizeof( int *) §\C{// is true, \ie the size of a reference}§
    15501813\end{cfa}
    15511814
     
    15641827Therefore, for pointer/reference initialization, the initializing value must be an address not a value.
    15651828\begin{cfa}
    1566 int * p = &x;                                           §\C{// assign address of x}§
    1567 ®int * p = x;®                                          §\C{// assign value of x}§
    1568 int & r = x;                                            §\C{// must have address of x}§
     1829int * p = &x; §\C{// assign address of x}§
     1830®int * p = x;® §\C{// assign value of x}§
     1831int & r = x; §\C{// must have address of x}§
    15691832\end{cfa}
    15701833Like 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).
     
    15751838Similarly, 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.
    15761839\begin{cfa}
    1577 int & f( int & r );                                     §\C{// reference parameter and return}§
    1578 z = f( x ) + f( y );                            §\C{// reference operator added, temporaries needed for call results}§
     1840int & f( int & r ); §\C{// reference parameter and return}§
     1841z = f( x ) + f( y ); §\C{// reference operator added, temporaries needed for call results}§
    15791842\end{cfa}
    15801843Within routine ©f©, it is possible to change the argument by changing the corresponding parameter, and parameter ©r© can be locally reassigned within ©f©.
     
    16031866void f( int & r );
    16041867void g( int * p );
    1605 f( 3 );                   g( ®&®3 );            §\C{// compiler implicit generates temporaries}§
    1606 f( x + y );             g( ®&®(x + y) );        §\C{// compiler implicit generates temporaries}§
     1868f( 3 );                   g( ®&®3 ); §\C{// compiler implicit generates temporaries}§
     1869f( x + y );             g( ®&®(x + y) ); §\C{// compiler implicit generates temporaries}§
    16071870\end{cfa}
    16081871Essentially, there is an implicit \Index{rvalue} to \Index{lvalue} conversion in this case.\footnote{
     
    16151878\begin{cfa}
    16161879void f( int i );
    1617 void (* fp)( int );                                     §\C{// routine pointer}§
    1618 fp = f;                                                         §\C{// reference initialization}§
    1619 fp = &f;                                                        §\C{// pointer initialization}§
    1620 fp = *f;                                                        §\C{// reference initialization}§
    1621 fp(3);                                                          §\C{// reference invocation}§
    1622 (*fp)(3);                                                       §\C{// pointer invocation}§
     1880void (* fp)( int ); §\C{// routine pointer}§
     1881fp = f; §\C{// reference initialization}§
     1882fp = &f; §\C{// pointer initialization}§
     1883fp = *f; §\C{// reference initialization}§
     1884fp(3); §\C{// reference invocation}§
     1885(*fp)(3); §\C{// pointer invocation}§
    16231886\end{cfa}
    16241887While 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.
    16251888Instead, a routine object should be referenced by a ©const© reference:
    16261889\begin{cfa}
    1627 ®const® void (®&® fr)( int ) = f;       §\C{// routine reference}§
    1628 fr = ...                                                        §\C{// error, cannot change code}§
    1629 &fr = ...;                                                      §\C{// changing routine reference}§
    1630 fr( 3 );                                                        §\C{// reference call to f}§
    1631 (*fr)(3);                                                       §\C{// error, incorrect type}§
     1890®const® void (®&® fr)( int ) = f; §\C{// routine reference}§
     1891fr = ... §\C{// error, cannot change code}§
     1892&fr = ...; §\C{// changing routine reference}§
     1893fr( 3 ); §\C{// reference call to f}§
     1894(*fr)(3); §\C{// error, incorrect type}§
    16321895\end{cfa}
    16331896because the value of the routine object is a routine literal, \ie the routine code is normally immutable during execution.\footnote{
     
    16421905\begin{itemize}
    16431906\item
    1644 if ©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
    1647 if ©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).
     1907if ©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
     1910if ©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).
    16481911\end{itemize}
    16491912The following example shows the first rule applied to different \Index{rvalue} contexts:
     
    16511914int x, * px, ** ppx, *** pppx, **** ppppx;
    16521915int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    1653 x = rrrx;               // rrrx is an lvalue with type int &&& (equivalent to x)
    1654 px = &rrrx;             // starting from rrrx, &rrrx is an rvalue with type int *&&& (&x)
    1655 ppx = &&rrrx;   // starting from &rrrx, &&rrrx is an rvalue with type int **&& (&rx)
    1656 pppx = &&&rrrx; // starting from &&rrrx, &&&rrrx is an rvalue with type int ***& (&rrx)
    1657 ppppx = &&&&rrrx; // starting from &&&rrrx, &&&&rrrx is an rvalue with type int **** (&rrrx)
     1916x = rrrx; §\C[2.0in]{// rrrx is an lvalue with type int \&\&\& (equivalent to x)}§
     1917px = &rrrx; §\C{// starting from rrrx, \&rrrx is an rvalue with type int *\&\&\& (\&x)}§
     1918ppx = &&rrrx; §\C{// starting from \&rrrx, \&\&rrrx is an rvalue with type int **\&\& (\&rx)}§
     1919pppx = &&&rrrx; §\C{// starting from \&\&rrrx, \&\&\&rrrx is an rvalue with type int ***\& (\&rrx)}§
     1920ppppx = &&&&rrrx; §\C{// starting from \&\&\&rrrx, \&\&\&\&rrrx is an rvalue with type int **** (\&rrrx)}§
    16581921\end{cfa}
    16591922The following example shows the second rule applied to different \Index{lvalue} contexts:
     
    16611924int x, * px, ** ppx, *** pppx;
    16621925int & rx = x, && rrx = rx, &&& rrrx = rrx ;
    1663 rrrx = 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)
     1926rrrx = 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§
    16671930\end{cfa}
    16681931
     
    16771940\begin{cfa}
    16781941int x;
    1679 x + 1;                  // lvalue variable (int) converts to rvalue for expression
     1942x + 1; §\C[2.0in]{// lvalue variable (int) converts to rvalue for expression}§
    16801943\end{cfa}
    16811944An rvalue has no type qualifiers (©cv©), so the lvalue qualifiers are dropped.
     
    16871950\begin{cfa}
    16881951int x, &r = x, f( int p );
    1689 x = ®r® + f( ®r® );  // lvalue reference converts to rvalue
     1952x = ®r® + f( ®r® ); §\C{// lvalue reference converts to rvalue}§
    16901953\end{cfa}
    16911954An rvalue has no type qualifiers (©cv©), so the reference qualifiers are dropped.
     
    16941957lvalue to reference conversion: \lstinline[deletekeywords=lvalue]@lvalue-type cv1 T@ converts to ©cv2 T &©, which allows implicitly converting variables to references.
    16951958\begin{cfa}
    1696 int x, &r = ®x®, f( int & p ); // lvalue variable (int) convert to reference (int &)
    1697 f( ®x® );               // lvalue variable (int) convert to reference (int &)
     1959int x, &r = ®x®, f( int & p ); §\C{// lvalue variable (int) convert to reference (int \&)}§
     1960f( ®x® ); §\C{// lvalue variable (int) convert to reference (int \&)}§
    16981961\end{cfa}
    16991962Conversion can restrict a type, where ©cv1© $\le$ ©cv2©, \eg passing an ©int© to a ©const volatile int &©, which has low cost.
     
    17051968\begin{cfa}
    17061969int x, & f( int & p );
    1707 f( ®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 &)
     1970f( ®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§
    17091972\end{cfa}
    17101973In both case, modifications to the temporary are inaccessible (\Index{warning}).
     
    18952158in 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:
    18962159\begin{cfa}
    1897 [§\,§] g();                                                     §\C{// no input or output parameters}§
    1898 [ void ] g( void );                                     §\C{// no input or output parameters}§
     2160[§\,§] g(); §\C{// no input or output parameters}§
     2161[ void ] g( void ); §\C{// no input or output parameters}§
    18992162\end{cfa}
    19002163
     
    19142177\begin{cfa}
    19152178typedef int foo;
    1916 int f( int (* foo) );                           §\C{// foo is redefined as a parameter name}§
     2179int f( int (* foo) ); §\C{// foo is redefined as a parameter name}§
    19172180\end{cfa}
    19182181The 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.
     
    19222185C-style declarations can be used to declare parameters for \CFA style routine definitions, \eg:
    19232186\begin{cfa}
    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}§
     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}§
    19262189\end{cfa}
    19272190The 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:
    19282191\begin{cfa}
    19292192#define ptoa( n, d ) int (*n)[ d ]
    1930 int 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 ] )}§
     2193int 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 ] )}§
    19322195\end{cfa}
    19332196Again, programmers are highly encouraged to use one declaration form or the other, rather than mixing the forms.
     
    19512214        int z;
    19522215        ... x = 0; ... y = z; ...
    1953         ®return;®                                                       §\C{// implicitly return x, y}§
     2216        ®return;® §\C{// implicitly return x, y}§
    19542217}
    19552218\end{cfa}
     
    19612224[ int x, int y ] f() {
    19622225        ...
    1963 }                                                                               §\C{// implicitly return x, y}§
     2226} §\C{// implicitly return x, y}§
    19642227\end{cfa}
    19652228In this case, the current values of ©x© and ©y© are returned to the calling routine just as if a ©return© had been encountered.
     
    19702233[ int x, int y ] f( int, x, int y ) {
    19712234        ...
    1972 }                                                                               §\C{// implicitly return x, y}§
     2235} §\C{// implicitly return x, y}§
    19732236\end{cfa}
    19742237This notation allows the compiler to eliminate temporary variables in nested routine calls.
    19752238\begin{cfa}
    1976 [ int x, int y ] f( int, x, int y );    §\C{// prototype declaration}§
     2239[ int x, int y ] f( int, x, int y ); §\C{// prototype declaration}§
    19772240int a, b;
    19782241[a, b] = f( f( f( a, b ) ) );
     
    19882251as well, parameter names are optional, \eg:
    19892252\begin{cfa}
    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}§
     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}§
    19942257\end{cfa}
    19952258This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
     
    20122275The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
    20132276\begin{cfa}
    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}§
     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}§
    20182281\end{cfa}
    20192282While parameter names are optional, \emph{a routine name cannot be specified};
    20202283for example, the following is incorrect:
    20212284\begin{cfa}
    2022 * [ int x ] f () fp;                                    §\C{// routine name "f" is not allowed}§
     2285* [ int x ] f () fp; §\C{// routine name "f" is not allowed}§
    20232286\end{cfa}
    20242287
     
    20432306whereas a named (keyword) call may be:
    20442307\begin{cfa}
    2045 p( z : 3, x : 4, y : 7 );       §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§
     2308p( z : 3, x : 4, y : 7 );  §\C{// rewrite $\Rightarrow$ p( 4, 7, 3 )}§
    20462309\end{cfa}
    20472310Here the order of the arguments is unimportant, and the names of the parameters are used to associate argument values with the corresponding parameters.
     
    20602323For example, the following routine prototypes and definition are all valid.
    20612324\begin{cfa}
    2062 void p( int, int, int );                        §\C{// equivalent prototypes}§
     2325void p( int, int, int ); §\C{// equivalent prototypes}§
    20632326void p( int x, int y, int z );
    20642327void p( int y, int x, int z );
    20652328void p( int z, int y, int x );
    2066 void p( int q, int r, int s ) {}        §\C{// match with this definition}§
     2329void p( int q, int r, int s ) {} §\C{// match with this definition}§
    20672330\end{cfa}
    20682331Forcing matching parameter names in routine prototypes with corresponding routine definitions is possible, but goes against a strong tradition in C programming.
     
    20762339int f( int x, double y );
    20772340
    2078 f( j : 3, i : 4 );                              §\C{// 1st f}§
    2079 f( x : 7, y : 8.1 );                    §\C{// 2nd f}§
    2080 f( 4, 5 );                                              §\C{// ambiguous call}§
     2341f( j : 3, i : 4 ); §\C{// 1st f}§
     2342f( x : 7, y : 8.1 ); §\C{// 2nd f}§
     2343f( 4, 5 );  §\C{// ambiguous call}§
    20812344\end{cfa}
    20822345However, named arguments compound routine resolution in conjunction with conversions:
    20832346\begin{cfa}
    2084 f( i : 3, 5.7 );                                §\C{// ambiguous call ?}§
     2347f( i : 3, 5.7 ); §\C{// ambiguous call ?}§
    20852348\end{cfa}
    20862349Depending on the cost associated with named arguments, this call could be resolvable or ambiguous.
     
    20962359the allowable positional calls are:
    20972360\begin{cfa}
    2098 p();                                                    §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
    2099 p( 4 );                                                 §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
    2100 p( 4, 4 );                                              §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
    2101 p( 4, 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§
     2361p(); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
     2362p( 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
     2363p( 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
     2364p( 4, 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§
    21022365// empty arguments
    2103 p(  , 4, 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§
    2104 p( 4,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§
    2105 p( 4, 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
    2106 p( 4,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
    2107 p(  , 4,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§
    2108 p(  ,  , 4 );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§
    2109 p(  ,  ,   );                                   §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
     2366p(  , 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§
     2367p( 4,  , 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§
     2368p( 4, 4,   ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§
     2369p( 4,  ,   ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§
     2370p(  , 4,   ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§
     2371p(  ,  , 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§
     2372p(  ,  ,   ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§
    21102373\end{cfa}
    21112374Here the missing arguments are inserted from the default values in the parameter list.
     
    21312394Default values may only appear in a prototype versus definition context:
    21322395\begin{cfa}
    2133 void p( int x, int y = 2, int z = 3 );          §\C{// prototype: allowed}§
    2134 void p( int, int = 2, int = 3 );                        §\C{// prototype: allowed}§
    2135 void p( int x, int y = 2, int z = 3 ) {}        §\C{// definition: not allowed}§
     2396void p( int x, int y = 2, int z = 3 ); §\C{// prototype: allowed}§
     2397void p( int, int = 2, int = 3 ); §\C{// prototype: allowed}§
     2398void p( int x, int y = 2, int z = 3 ) {} §\C{// definition: not allowed}§
    21362399\end{cfa}
    21372400The reason for this restriction is to allow separate compilation.
     
    21582421\begin{cfa}
    21592422void p( int x, int y = 2, int z = 3... );
    2160 p( 1, 4, 5, 6, z : 3 );         §\C{// assume p( /* positional */, ... , /* named */ );}§
    2161 p( 1, z : 3, 4, 5, 6 );         §\C{// assume p( /* positional */, /* named */, ... );}§
     2423p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§
     2424p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§
    21622425\end{cfa}
    21632426The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments;
     
    21892452Furthermore, overloading cannot handle accessing default arguments in the middle of a positional list, via a missing argument, such as:
    21902453\begin{cfa}
    2191 p( 1, /* default */, 5 );               §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§
     2454p( 1, /* default */, 5 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 5 )}§
    21922455\end{cfa}
    21932456
     
    22022465\begin{cfa}
    22032466struct {
    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}§
     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}§
    22102473};
    22112474\end{cfa}
     
    22152478\begin{cfa}
    22162479struct {
    2217         int , , ;                               §\C{// 3 unnamed fields}§
     2480        int , , ; §\C{// 3 unnamed fields}§
    22182481}
    22192482\end{cfa}
     
    22622525        struct T t;
    22632526} s;
    2264        
     2527
    22652528
    22662529
     
    23092572const unsigned int size = 5;
    23102573int ia[size];
    2311 ...                                             §\C{// assign values to array ia}§
    2312 qsort( ia, size );              §\C{// sort ascending order using builtin ?<?}§
     2574... §\C{// assign values to array ia}§
     2575qsort( ia, size ); §\C{// sort ascending order using builtin ?<?}§
    23132576{
    23142577        ®int ?<?( int x, int y ) { return x > y; }® §\C{// nested routine}§
    2315         qsort( ia, size );      §\C{// sort descending order by local redefinition}§
     2578        qsort( ia, size ); §\C{// sort descending order by local redefinition}§
    23162579}
    23172580\end{cfa}
     
    23212584The following program in undefined in \CFA (and Indexc{gcc})
    23222585\begin{cfa}
    2323 [* [int]( int )] foo() {                §\C{// int (* foo())( int )}§
     2586[* [int]( int )] foo() { §\C{// int (* foo())( int )}§
    23242587        int ®i® = 7;
    23252588        int bar( int p ) {
    2326                 ®i® += 1;                               §\C{// dependent on local variable}§
    2327                 sout | ®i® | endl;
     2589                ®i® += 1; §\C{// dependent on local variable}§
     2590                sout | ®i®;
    23282591        }
    2329         return bar;                                     §\C{// undefined because of local dependence}§
     2592        return bar; §\C{// undefined because of local dependence}§
    23302593}
    23312594int main() {
    2332         * [int]( int ) fp = foo();      §\C{// int (* fp)( int )}§
    2333         sout | fp( 3 ) | endl;
    2334 }
    2335 \end{cfa}
    2336 because 
     2595        * [int]( int ) fp = foo(); §\C{// int (* fp)( int )}§
     2596        sout | fp( 3 );
     2597}
     2598\end{cfa}
     2599because
    23372600
    23382601Currently, there are no \Index{lambda} expressions, \ie unnamed routines because routine names are very important to properly select the correct routine.
     
    23432606In C and \CFA, lists of elements appear in several contexts, such as the parameter list of a routine call.
    23442607\begin{cfa}
    2345 f( ®2, x, 3 + i® );                             §\C{// element list}§
     2608f( ®2, x, 3 + i® ); §\C{// element list}§
    23462609\end{cfa}
    23472610A list of elements is called a \newterm{tuple}, and is different from a \Index{comma expression}.
     
    23602623typedef struct { int quot, rem; } div_t;        §\C[7cm]{// from include stdlib.h}§
    23612624div_t div( int num, int den );
    2362 div_t qr = div( 13, 5 );                                        §\C{// return quotient/remainder aggregate}§
    2363 printf( "%d %d\n", qr.quot, qr.rem );           §\C{// print quotient/remainder}§
     2625div_t qr = div( 13, 5 ); §\C{// return quotient/remainder aggregate}§
     2626printf( "%d %d\n", qr.quot, qr.rem ); §\C{// print quotient/remainder}§
    23642627\end{cfa}
    23652628This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue.
     
    23712634For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating value.
    23722635\begin{cfa}
    2373 double modf( double x, double * i );            §\C{// from include math.h}§
    2374 double intp, frac = modf( 13.5, &intp );        §\C{// return integral and fractional components}§
    2375 printf( "%g %g\n", intp, frac );                        §\C{// print integral/fractional components}§
     2636double modf( double x, double * i ); §\C{// from include math.h}§
     2637double intp, frac = modf( 13.5, &intp ); §\C{// return integral and fractional components}§
     2638printf( "%g %g\n", intp, frac ); §\C{// print integral/fractional components}§
    23762639\end{cfa}
    23772640This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call.
     
    24002663When 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.
    24012664\begin{cfa}
    2402 void g( int, int );                                                     §\C{// 1}§
    2403 void g( double, double );                                       §\C{// 2}§
    2404 g( div( 13, 5 ) );                                                      §\C{// select 1}§
    2405 g( modf( 13.5 ) );                                                      §\C{// select 2}§
     2665void g( int, int ); §\C{// 1}§
     2666void g( double, double ); §\C{// 2}§
     2667g( div( 13, 5 ) ); §\C{// select 1}§
     2668g( modf( 13.5 ) ); §\C{// select 2}§
    24062669\end{cfa}
    24072670In this case, there are two overloaded ©g© routines.
     
    24122675The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call.
    24132676\begin{cfa}
    2414 [ int, int ] div( int x, int y );                       §\C{// from include stdlib}§
    2415 printf( "%d %d\n", div( 13, 5 ) );                      §\C{// print quotient/remainder}§
    2416 
    2417 [ double, double ] modf( double x );            §\C{// from include math}§
    2418 printf( "%g %g\n", modf( 13.5 ) );                      §\C{// print integral/fractional components}§
     2677[ int, int ] div( int x, int y ); §\C{// from include stdlib}§
     2678printf( "%d %d\n", div( 13, 5 ) ); §\C{// print quotient/remainder}§
     2679
     2680[ double, double ] modf( double x ); §\C{// from include math}§
     2681printf( "%g %g\n", modf( 13.5 ) ); §\C{// print integral/fractional components}§
    24192682\end{cfa}
    24202683This 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.
     
    24262689\begin{cfa}
    24272690int quot, rem;
    2428 [ quot, rem ] = div( 13, 5 );                           §\C{// assign multiple variables}§
    2429 printf( "%d %d\n", quot, rem );                         §\C{// print quotient/remainder}\CRT§
     2691[ quot, rem ] = div( 13, 5 ); §\C{// assign multiple variables}§
     2692printf( "%d %d\n", quot, rem ); §\C{// print quotient/remainder}\CRT§
    24302693\end{cfa}
    24312694Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call.
     
    24332696
    24342697\subsection{Expressions}
     2698
     2699% Change order of expression evaluation.
     2700% http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0145r2.pdf
    24352701
    24362702Multiple-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.
     
    24532719In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}.
    24542720\begin{cfa}
    2455 [int, int] ®qr® = div( 13, 5 );                 §\C{// initialize tuple variable}§
    2456 printf( "%d %d\n", ®qr® );                              §\C{// print quotient/remainder}§
     2721[int, int] ®qr® = div( 13, 5 ); §\C{// initialize tuple variable}§
     2722printf( "%d %d\n", ®qr® ); §\C{// print quotient/remainder}§
    24572723\end{cfa}
    24582724It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}.
     
    24602726One way to access the individual components of a tuple variable is with assignment.
    24612727\begin{cfa}
    2462 [ quot, rem ] = qr;                                             §\C{// assign multiple variables}§
     2728[ quot, rem ] = qr; §\C{// assign multiple variables}§
    24632729\end{cfa}
    24642730
     
    24832749[int, double] * p;
    24842750
    2485 int y = x.0;                                                    §\C{// access int component of x}§
    2486 y = f().1;                                                              §\C{// access int component of f}§
    2487 p->0 = 5;                                                               §\C{// access int component of tuple pointed-to by p}§
    2488 g( x.1, x.0 );                                                  §\C{// rearrange x to pass to g}§
    2489 double z = [ x, f() ].0.1;                              §\C{// access second component of first component of tuple expression}§
     2751int y = x.0; §\C{// access int component of x}§
     2752y = f().1; §\C{// access int component of f}§
     2753p->0 = 5; §\C{// access int component of tuple pointed-to by p}§
     2754g( x.1, x.0 ); §\C{// rearrange x to pass to g}§
     2755double z = [ x, f() ].0.1; §\C{// access second component of first component of tuple expression}§
    24902756\end{cfa}
    24912757Tuple-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.
     
    25542820double y;
    25552821[int, double] z;
    2556 [y, x] = 3.14;                                                  §\C{// mass assignment}§
     2822[y, x] = 3.14; §\C{// mass assignment}§
    25572823[x, y] = z;                                                         §\C{// multiple assignment}§
    25582824z = 10;                                                         §\C{// mass assignment}§
    2559 z = [x, y];                                                             §\C{// multiple assignment}§
     2825z = [x, y]; §\C{// multiple assignment}§
    25602826\end{cfa}
    25612827Let $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.
     
    26012867        double c, d;
    26022868        [ void ] f( [ int, int ] );
    2603         f( [ c, a ] = [ b, d ] = 1.5 );  // assignments in parameter list
     2869        f( [ c, a ] = [ b, d ] = 1.5 ); §\C{// assignments in parameter list}§
    26042870\end{cfa}
    26052871The 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.
     
    26142880\begin{cfa}
    26152881struct S;
    2616 void ?{}(S *);         // (1)
    2617 void ?{}(S *, int);    // (2)
    2618 void ?{}(S * double);  // (3)
    2619 void ?{}(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
     2882void ?{}(S *); §\C{// (1)}§
     2883void ?{}(S *, int); §\C{// (2)}§
     2884void ?{}(S * double); §\C{// (3)}§
     2885void ?{}(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}§
    26242890\end{cfa}
    26252891In 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)©.
     
    26622928A member-access tuple may be used anywhere a tuple can be used, \eg:
    26632929\begin{cfa}
    2664 s.[ y, z, x ] = [ 3, 3.2, 'x' ];                §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§
    2665 f( s.[ y, z ] );                                                §\C{// equivalent to f( s.y, s.z )}§
     2930s.[ y, z, x ] = [ 3, 3.2, 'x' ]; §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§
     2931f( s.[ y, z ] ); §\C{// equivalent to f( s.y, s.z )}§
    26662932\end{cfa}
    26672933Note, the fields appearing in a record-field tuple may be specified in any order;
     
    26732939void f( double, long );
    26742940
    2675 f( x.[ 0, 3 ] );                                                §\C{// f( x.0, x.3 )}§
    2676 x.[ 0, 1 ] = x.[ 1, 0 ];                                §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§
     2941f( x.[ 0, 3 ] ); §\C{// f( x.0, x.3 )}§
     2942x.[ 0, 1 ] = x.[ 1, 0 ]; §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§
    26772943[ long, int, long ] y = x.[ 2, 0, 2 ];
    26782944\end{cfa}
     
    26912957\begin{cfa}
    26922958[ int, float, double ] f();
    2693 [ double, float ] x = f().[ 2, 1 ];             §\C{// f() called once}§
     2959[ double, float ] x = f().[ 2, 1 ]; §\C{// f() called once}§
    26942960\end{cfa}
    26952961
     
    27042970That 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.
    27052971\begin{cfa}
    2706 int f();     // (1)
    2707 double f();  // (2)
    2708 
    2709 f();       // ambiguous - (1),(2) both equally viable
    2710 (int)f();  // choose (2)
     2972int f(); §\C{// (1)}§
     2973double f(); §\C{// (2)}§
     2974
     2975f(); §\C{// ambiguous - (1),(2) both equally viable}§
     2976(int)f(); §\C{// choose (2)}§
    27112977\end{cfa}
    27122978Since casting is a fundamental operation in \CFA, casts need to be given a meaningful interpretation in the context of tuples.
     
    27162982void g();
    27172983
    2718 (void)f();  // valid, ignore results
    2719 (int)g();   // invalid, void cannot be converted to int
     2984(void)f(); §\C{// valid, ignore results}§
     2985(int)g(); §\C{// invalid, void cannot be converted to int}§
    27202986
    27212987struct A { int x; };
    2722 (struct A)f();  // invalid, int cannot be converted to A
     2988(struct A)f(); §\C{// invalid, int cannot be converted to A}§
    27232989\end{cfa}
    27242990In C, line 4 is a valid cast, which calls ©f© and discards its result.
     
    27363002        [int, [int, int], int] g();
    27373003
    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
     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}§
    27433009\end{cfa}
    27443010
     
    28003066void f([int, int], int, int);
    28013067
    2802 f([0, 0], 0, 0);    // no cost
    2803 f(0, 0, 0, 0);      // cost for structuring
    2804 f([0, 0,], [0, 0]); // cost for flattening
    2805 f([0, 0, 0], 0);    // cost for flattening and structuring
     3068f([0, 0], 0, 0); §\C{// no cost}§
     3069f(0, 0, 0, 0); §\C{// cost for structuring}§
     3070f([0, 0,], [0, 0]); §\C{// cost for flattening}§
     3071f([0, 0, 0], 0); §\C{// cost for flattening and structuring}§
    28063072\end{cfa}
    28073073
     
    28663132[ unsigned int, char ]
    28673133[ double, double, double ]
    2868 [ * int, int * ]                §\C{// mix of CFA and ANSI}§
     3134[ * int, int * ] §\C{// mix of CFA and ANSI}§
    28693135[ * [ 5 ] int, * * char, * [ [ int, int ] ] (int, int) ]
    28703136\end{cfa}
     
    28733139Examples of declarations using tuple types are:
    28743140\begin{cfa}
    2875 [ int, int ] x;                 §\C{// 2 element tuple, each element of type int}§
    2876 * [ char, char ] y;             §\C{// pointer to a 2 element tuple}§
     3141[ int, int ] x; §\C{// 2 element tuple, each element of type int}§
     3142* [ char, char ] y; §\C{// pointer to a 2 element tuple}§
    28773143[ [ int, int ] ] z ([ int, int ]);
    28783144\end{cfa}
     
    28913157[ int, int ] w1;
    28923158[ int, int, int ] w2;
    2893 [ void ] f (int, int, int); /* three input parameters of type int */
    2894 [ void ] g ([ int, int, int ]); /* 3 element tuple as input */
     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}§
    28953161f( [ 1, 2, 3 ] );
    28963162f( w1, 3 );
     
    29723238[ int, int, int, int ] w = [ 1, 2, 3, 4 ];
    29733239int x = 5;
    2974 [ x, w ] = [ w, x ];            §\C{// all four tuple coercions}§
     3240[ x, w ] = [ w, x ]; §\C{// all four tuple coercions}§
    29753241\end{cfa}
    29763242Starting on the right-hand tuple in the last assignment statement, w is opened, producing a tuple of four values;
     
    30603326both these examples produce indeterminate results:
    30613327\begin{cfa}
    3062 f( 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}§
     3328f( 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}§
    30643330\end{cfa}
    30653331
     
    30833349
    30843350
    3085 \section{I/O Library}
    3086 \label{s:IOLibrary}
    3087 \index{input/output library}
    3088 
    3089 The 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.
    3090 The approach combines ideas from \CC and Python.
    3091 The \CFA header file for the I/O library is \Indexc{fstream}.
    3092 
    3093 The common case is printing out a sequence of variables separated by whitespace.
     3351\section{Stream I/O Library}
     3352\label{s:StreamIOLibrary}
     3353\index{input/output stream library}
     3354\index{stream library}
     3355
     3356The 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.
     3357Stream I/O can be implicitly or explicitly formatted.
     3358Implicit formatting means \CFA selects the output or input format for values that match with the type of a variable.
     3359Explicit 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.
     3361Specifically:
     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
     3370Format manipulators in \CFA have local effect, whereas \CC have global effect, except ©setw©.
     3371Hence, it is common programming practice to toggle manipulators on and then back to the default to prevent downstream side-effects.
     3372Without 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}
     3377The \CFA header file for the I/O library is \Indexc{fstream.hfa}.
     3378
     3379For implicit formatted output, the common case is printing a series of variables separated by whitespace.
    30943380\begin{cquote}
    3095 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    3096 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{\CC}}      \\
     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}}   \\
    30973383\begin{cfa}
    30983384int x = 1, y = 2, z = 3;
    3099 sout | x ®|® y ®|® z | endl;
     3385sout | x ®|® y ®|® z;
    31003386\end{cfa}
    31013387&
     
    31033389
    31043390cout << x ®<< " "® << y ®<< " "® << z << endl;
     3391\end{cfa}
     3392&
     3393\begin{cfa}
     3394x = 1;  y = 2;  z = 3
     3395print( x, y, z )
    31053396\end{cfa}
    31063397\\
     
    31103401&
    31113402\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    3112 1 2 3
     34031® ®2® ®3
     3404\end{cfa}
     3405&
     3406\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     34071® ®2® ®3
    31133408\end{cfa}
    31143409\end{tabular}
    31153410\end{cquote}
    3116 The \CFA form has half the characters of the \CC form, and is similar to \Index*{Python} I/O with respect to implicit separators.
    3117 Similar simplification occurs for \Index{tuple} I/O, which prints all tuple values separated by ``\lstinline[showspaces=true]@, @''.
     3411The \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.
     3412Similar simplification occurs for \Index{tuple} I/O, which flattens the tuple and prints each value separated by ``\lstinline[showspaces=true]@, @''.
    31183413\begin{cfa}
    31193414[int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];
    3120 sout | t1 | t2 | endl;                                  §\C{// print tuples}§
     3415sout | t1 | t2; §\C{// print tuples}§
    31213416\end{cfa}
    31223417\begin{cfa}[showspaces=true,aboveskip=0pt]
    312334181®, ®2®, ®3 4®, ®5®, ®6
    31243419\end{cfa}
    3125 Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority overloadable operator, other than assignment.
     3420Finally, \CFA uses the logical-or operator for I/O as it is the lowest-priority \emph{overloadable} operator, other than assignment.
    31263421Therefore, fewer output expressions require parenthesis.
    31273422\begin{cquote}
     
    31303425&
    31313426\begin{cfa}
    3132 sout | x * 3 | y + 1 | z << 2 | x == y | (x | y) | (x || y) | (x > z ? 1 : 2) | endl;
     3427sout | x * 3 | y + 1 | z << 2 | x == y | ®(®x | y®)® | ®(®x || y®)® | ®(®x > z ? 1 : 2®)®;
    31333428\end{cfa}
    31343429\\
     
    31363431&
    31373432\begin{cfa}
    3138 cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << (x | y) << (x || y) << (x > z ? 1 : 2) << endl;
     3433cout << x * 3 << y + 1 << ®(®z << 2®)® << ®(®x == y®)® << ®(®x | y®)® << ®(®x || y®)® << ®(®x > z ? 1 : 2®)® << endl;
    31393434\end{cfa}
    31403435\\
     
    31453440\end{tabular}
    31463441\end{cquote}
    3147 There 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.
     3442Input and output use a uniform operator, ©|©, rather than separate operators, as in ©>>© and ©<<© for \CC.
     3443There 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
     3445For 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]
     3449int 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]
     3456sin | x | y | z;
     3457\end{cfa}
     3458&
     3459\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     3460cin >> x >> y >> z;
     3461\end{cfa}
     3462&
     3463\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     3464x = 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
    31483487
    31493488
    31503489\subsection{Implicit Separator}
    31513490
    3152 The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator.
     3491The \Index{implicit separator}\index{I/O!separator} character (space/blank) is a separator not a terminator for output.
    31533492The rules for implicitly adding the separator are:
    31543493\begin{enumerate}
     
    31563495A separator does not appear at the start or end of a line.
    31573496\begin{cfa}[belowskip=0pt]
    3158 sout | 1 | 2 | 3 | endl;
     3497sout | 1 | 2 | 3;
    31593498\end{cfa}
    31603499\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    31653504A separator does not appear before or after a character literal or variable.
    31663505\begin{cfa}
    3167 sout | '1' | '2' | '3' | endl;
     3506sout | '1' | '2' | '3';
    31683507123
    31693508\end{cfa}
    31703509
    31713510\item
    3172 A separator does not appear before or after a null (empty) C string.
    3173 \begin{cfa}
    3174 sout | 1 | "" | 2 | "" | 3 | endl;
     3511A 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}
     3513sout | 1 | "" | 2 | "" | 3;
    31753514123
    31763515\end{cfa}
    3177 which is a local mechanism to disable insertion of the separator character.
    3178 
    3179 \item
    3180 A separator does not appear before a C string starting with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[mathescape=off,basicstyle=\tt]@([{=$£¥¡¿«@
     3516
     3517\item
     3518{\lstset{language=CFA,deletedelim=**[is][]{¢}{¢}}
     3519A 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.
     3520\begin{cfa}[belowskip=0pt]
     3521sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x"
     3522                | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";
     3523\end{cfa}
     3524\begin{cfa}[basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt]
     35251®,® x 2®.® x 3®;® x 4®!® x 5®?® x 6®%® x 7§\color{red}\textcent§ x 8®»® x 9®)® x 10®]® x 11®}® x
     3526\end{cfa}}%
     3527
     3528\item
     3529A 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.
    31813530%$
    31823531\begin{cfa}[mathescape=off]
    31833532sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥"
    3184                 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10 | endl;
     3533                | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;
    31853534\end{cfa}
    31863535%$
     
    31893538\end{cfa}
    31903539%$
    3191 where \lstinline[basicstyle=\tt]@¡¿@ are inverted opening exclamation and question marks, and \lstinline[basicstyle=\tt]@«@ is an opening citation mark.
    3192 
    3193 \item
    3194 {\lstset{language=CFA,deletedelim=**[is][]{¢}{¢}}
    3195 A seperator does not appear after a C string ending with the (extended) \Index*{ASCII}\index{ASCII!extended} characters: \lstinline[basicstyle=\tt]@,.;!?)]}%¢»@
     3540
     3541\item
     3542A 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@
    31963543\begin{cfa}[belowskip=0pt]
    3197 sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x"
    3198                 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x" | endl;
    3199 \end{cfa}
    3200 \begin{cfa}[basicstyle=\tt,showspaces=true,aboveskip=0pt,belowskip=0pt]
    3201 1®,® x 2®.® x 3®;® x 4®!® x 5®?® x 6®%® x 7§\color{red}\textcent§ x 8®»® x 9®)® x 10®]® x 11®}® x
    3202 \end{cfa}}%
    3203 where \lstinline[basicstyle=\tt]@»@ is a closing citation mark.
    3204 
    3205 \item
    3206 A 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@
    3207 \begin{cfa}[belowskip=0pt]
    3208 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx" | endl;
     3544sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx";
    32093545\end{cfa}
    32103546\begin{cfa}[basicstyle=\tt,showspaces=true,showtabs=true,aboveskip=0pt,belowskip=0pt]
     
    32153551If a space is desired before or after one of the special string start/end characters, simply insert a space.
    32163552\begin{cfa}[belowskip=0pt]
    3217 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 | endl;
     3553sout | "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;
    32183554\end{cfa}
    32193555\begin{cfa}[basicstyle=\tt,showspaces=true,showtabs=true,aboveskip=0pt,belowskip=0pt]
     
    32233559
    32243560
    3225 \subsection{Manipulator}
    3226 
    3227 The following \CC-style \Index{manipulator}s and routines control implicit seperation.
     3561\subsection{Separation Manipulators}
     3562
     3563The following \Index{manipulator}s control \Index{implicit output separation}.
     3564The effect of these manipulators is global for an output stream (except ©sepOn© and ©sepOff©).
    32283565\begin{enumerate}
    32293566\item
    3230 Routines \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.
     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.
    32313568The separator string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    32323569\begin{cfa}[mathescape=off,belowskip=0pt]
    3233 sepSet( sout, ", $" );                                          §\C{// set separator from " " to ", \$"}§
    3234 sout | 1 | 2 | 3 | " \"" | ®sep® | "\"" | endl;
     3570sepSet( sout, ", $" ); §\C{// set separator from " " to ", \$"}§
     3571sout | 1 | 2 | 3 | " \"" | ®sep® | "\"";
    32353572\end{cfa}
    32363573%$
     
    32403577%$
    32413578\begin{cfa}[belowskip=0pt]
    3242 sepSet( sout, " " );                                            §\C{// reset separator to " "}§
    3243 sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\"" | endl;
     3579sepSet( sout, " " ); §\C{// reset separator to " "}§
     3580sout | 1 | 2 | 3 | " \"" | ®sepGet( sout )® | "\"";
    32443581\end{cfa}
    32453582\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    32483585©sepGet© can be used to store a separator and then restore it:
    32493586\begin{cfa}[belowskip=0pt]
    3250 char store[®sepSize®];                                          §\C{// sepSize is the maximum separator size}§
    3251 strcpy( store, sepGet( sout ) );                          §\C{// copy current separator}§
    3252 sepSet( sout, "_" );                                            §\C{// change separator to underscore}§
    3253 sout | 1 | 2 | 3 | endl;
     3587char store[®sepSize®]; §\C{// sepSize is the maximum separator size}§
     3588strcpy( store, sepGet( sout ) ); §\C{// copy current separator}§
     3589sepSet( sout, "_" ); §\C{// change separator to underscore}§
     3590sout | 1 | 2 | 3;
    32543591\end{cfa}
    32553592\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    32573594\end{cfa}
    32583595\begin{cfa}[belowskip=0pt]
    3259 sepSet( sout, store );                                          §\C{// change separator back to original}§
    3260 sout | 1 | 2 | 3 | endl;
     3596sepSet( sout, store ); §\C{// change separator back to original}§
     3597sout | 1 | 2 | 3;
    32613598\end{cfa}
    32623599\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    32653602
    32663603\item
    3267 Routine \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.
     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.
    32683605The tuple separator-string can be at most 16 characters including the ©'\0'© string terminator (15 printable characters).
    32693606\begin{cfa}[belowskip=0pt]
    3270 sepSetTuple( sout, " " );                                       §\C{// set tuple separator from ", " to " "}§
    3271 sout | t1 | t2 | " \"" | ®sepTuple® | "\"" | endl;
     3607sepSetTuple( sout, " " ); §\C{// set tuple separator from ", " to " "}§
     3608sout | t1 | t2 | " \"" | ®sepTuple® | "\"";
    32723609\end{cfa}
    32733610\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    32753612\end{cfa}
    32763613\begin{cfa}[belowskip=0pt]
    3277 sepSetTuple( sout, ", " );                                      §\C{// reset tuple separator to ", "}§
    3278 sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\"" | endl;
     3614sepSetTuple( sout, ", " ); §\C{// reset tuple separator to ", "}§
     3615sout | t1 | t2 | " \"" | ®sepGetTuple( sout )® | "\"";
    32793616\end{cfa}
    32803617\begin{cfa}[showspaces=true,aboveskip=0pt]
     
    32843621
    32853622\item
    3286 Manipulators \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.
     3623\Indexc{sepDisable}\index{manipulator!sepDisable@©sepDisable©} and \Indexc{sepEnable}\index{manipulator!sepEnable@©sepEnable©} toggle printing the separator.
    32873624\begin{cfa}[belowskip=0pt]
    3288 sout | sepDisable | 1 | 2 | 3 | endl;           §\C{// globally turn off implicit separator}§
     3625sout | sepDisable | 1 | 2 | 3; §\C{// turn off implicit separator}§
    32893626\end{cfa}
    32903627\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    32923629\end{cfa}
    32933630\begin{cfa}[belowskip=0pt]
    3294 sout | sepEnable | 1 | 2 | 3 | endl;            §\C{// globally turn on implicit separator}§
     3631sout | sepEnable | 1 | 2 | 3; §\C{// turn on implicit separator}§
    32953632\end{cfa}
    32963633\begin{cfa}[mathescape=off,showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    32993636
    33003637\item
    3301 Manipulators \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.
     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.
    33023639\begin{cfa}[belowskip=0pt]
    3303 sout | 1 | sepOff | 2 | 3 | endl;                       §\C{// locally turn off implicit separator
     3640sout | 1 | sepOff | 2 | 3; §\C{// turn off implicit separator for the next item
    33043641\end{cfa}
    33053642\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    33073644\end{cfa}
    33083645\begin{cfa}[belowskip=0pt]
    3309 sout | sepDisable | 1 | sepOn | 2 | 3 | endl; §\C{// locally turn on implicit separator
     3646sout | sepDisable | 1 | sepOn | 2 | 3; §\C{// turn on implicit separator for the next item
    33103647\end{cfa}
    33113648\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    33143651The tuple separator also responses to being turned on and off.
    33153652\begin{cfa}[belowskip=0pt]
    3316 sout | t1 | sepOff | t2 | endl;                         §\C{// locally turn on/off implicit separator
     3653sout | t1 | sepOff | t2; §\C{// turn off implicit separator for the next item
    33173654\end{cfa}
    33183655\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    33223659use ©sep© to accomplish this functionality.
    33233660\begin{cfa}[belowskip=0pt]
    3324 sout | sepOn | 1 | 2 | 3 | sepOn | endl ;       §\C{// sepOn does nothing at start/end of line}§
     3661sout | sepOn | 1 | 2 | 3 | sepOn; §\C{// sepOn does nothing at start/end of line}§
    33253662\end{cfa}
    33263663\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     
    33283665\end{cfa}
    33293666\begin{cfa}[belowskip=0pt]
    3330 sout | sep | 1 | 2 | 3 | sep | endl ;           §\C{// use sep to print separator at start/end of line}§
     3667sout | sep | 1 | 2 | 3 | sep ; §\C{// use sep to print separator at start/end of line}§
    33313668\end{cfa}
    33323669\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
    33333670® ®1 2 3® ®
     3671\end{cfa}
     3672\end{enumerate}
     3673
     3674
     3675\subsection{Newline Manipulators}
     3676
     3677The following \Index{manipulators} control \Index{newline separation} for input and output.
     3678
     3679For 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}
     3688For example, in:
     3689\begin{cfa}
     3690sin | i | ®nl® | j;
     36911 ®2®
     36923
     3693\end{cfa}
     3694variable ©i© is assigned 1, the 2 is skipped, and variable ©j© is assigned 3.
     3695
     3696For output:
     3697\begin{enumerate}[parsep=0pt]
     3698\item
     3699\Indexc{nl}\index{manipulator!nl@©nl©} inserts a newline.
     3700\begin{cfa}
     3701sout | nl; §\C{// only print newline}§
     3702sout | 2; §\C{// implicit newline}§
     3703sout | 3 | nl | 4 | nl; §\C{// terminating nl merged with implicit newline}§
     3704sout | 5 | nl | nl; §\C{// again terminating nl merged with implicit newline}§
     3705sout | 6; §\C{// implicit newline}§
     3706
     37072
     37083
     37094
     37105
     3711
     37126
     3713\end{cfa}
     3714Note, 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
     3724The 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]
     3729sout | bin( 0 ) | bin( 27HH ) | bin( 27H ) | bin( 27 ) | bin( 27L );
     37300b0 0b11011 0b11011 0b11011 0b11011
     3731sout | bin( -27HH ) | bin( -27H ) | bin( -27 ) | bin( -27L );
     37320b11100101 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]
     3738sout | oct( 0 ) | oct( 27HH ) | oct( 27H ) | oct( 27 ) | oct( 27L );
     37390 033 033 033 033
     3740sout | oct( -27HH ) | oct( -27H ) | oct( -27 ) | oct( -27L );
     37410345 0177745 037777777745 01777777777777777777745
     3742\end{cfa}
     3743Note, 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]
     3748sout | hex( 0 ) | hex( 27HH ) | hex( 27H ) | hex( 27 ) | hex( 27L );
     37490 0x1b 0x1b 0x1b 0x1b
     3750sout | hex( -27HH ) | hex( -27H ) | hex( -27 ) | hex( -27L );
     37510xe5 0xffe5 0xffffffe5 0xffffffffffffffe5
     3752
     3753sout | hex( 0.0 ) | hex( 27.5F ) | hex( 27.5 ) | hex( 27.5L );
     37540x0.p+0 0x1.b8p+4 0x1.b8p+4 0xd.cp+1
     3755sout | 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.
     3761Default is 6 digits of precision.
     3762\begin{cfa}[belowskip=0pt]
     3763sout | sci( 0.0 ) | sci( 27.5 ) | sci( -27.5 );
     37640.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]
     3770sout | upcase( bin( 27 ) ) | upcase( hex( 27 ) ) | upcase( 27.5e-10 ) | upcase( hex( 27.5 ) );
     37710®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©.
     3776Printing the base is the default.
     3777\begin{cfa}[belowskip=0pt]
     3778sout | nobase( bin( 27 ) ) | nobase( oct( 27 ) ) | nobase( hex( 27 ) );
     377911011 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.
     3784Printing a decimal point is the default, if there are no fractional digits.
     3785\begin{cfa}[belowskip=0pt]
     3786sout | 0. | nodp( 0. ) | 27.0 | nodp( 27.0 ) | nodp( 27.5 );
     37870.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]
     3793sout | 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 )©
     3799For all types, ©minimum© is the minimum number of printed characters.
     3800If the value is shorter than the minimum, it is padded on the right with spaces.
     3801\begin{cfa}[belowskip=0pt]
     3802sout | wd( 4, 34) | wd( 3, 34 ) | wd( 2, 34 );
     3803sout | wd( 10, 4.) | wd( 9, 4. ) | wd( 8, 4. );
     3804sout | 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}
     3811If the value is larger, it is printed without truncation, ignoring the ©minimum©.
     3812\begin{cfa}[belowskip=0pt]
     3813sout | wd( 4, 34567 ) | wd( 3, 34567 ) | wd( 2, 34567 );
     3814sout | wd( 4, 3456. ) | wd( 3, 3456. ) | wd( 2, 3456. );
     3815sout | wd( 4, "abcde" ) | wd( 3, "abcde" ) | wd( 2,"abcde" );
     3816\end{cfa}
     3817\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     38183456®7® 345®67® 34®567®
     38193456®.® 345®6.® 34®56.®
     3820abcd®e® abc®de® ab®cde®
     3821\end{cfa}
     3822
     3823For integer types, ©precision© is the minimum number of printed digits.
     3824If the value is shorter, it is padded on the left with leading zeros.
     3825\begin{cfa}[belowskip=0pt]
     3826sout | 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}
     3831If the value is larger, it is printed without truncation, ignoring the ©precision©.
     3832\begin{cfa}[belowskip=0pt]
     3833sout | wd( 4,1, 3456 ) | wd( 8,2, 3456 ) | wd( 10,3, 3456 );
     3834\end{cfa}
     3835\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     38363456     3456       3456
     3837\end{cfa}
     3838If ©precision© is 0, nothing is printed for zero.
     3839If ©precision© is greater than the minimum, it becomes the minimum.
     3840\begin{cfa}[belowskip=0pt]
     3841sout | 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}
     3846For floating-point types, ©precision© is the minimum number of digits after the decimal point.
     3847\begin{cfa}[belowskip=0pt]
     3848sout | 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]
     385127.®500®     27.®5®      28. 27.®50000000®
     3852\end{cfa}
     3853For 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]
     3855sout | 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©}
     3863For 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©).
     3864If a value's significant digits is greater than ©significant©, the last significant digit is rounded up.
     3865\begin{cfa}[belowskip=0pt]
     3866sout | 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]
     3869234.567 234.5®7®  234.®6®    23®5®
     3870\end{cfa}
     3871If 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]
     3873sout | 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]
     3876234567. 2.3457®e+05® 2.346®e+05® 2.35®e+05®
     3877\end{cfa}
     3878If ©significant© is greater than ©minimum©, it defines the number of printed characters.
     3879\begin{cfa}[belowskip=0pt]
     3880sout | 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]
     3883234567. 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]
     3889sout | 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]
     389227®  ® 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]
     3898sout | pad0( wd( 4, 27 ) ) | pad0( wd( 4,3, 27 ) ) | pad0( wd( 8,3, 27.5 ) );
     3899®00®27  ®0®27 ®00®27.500
    33343900\end{cfa}
    33353901\end{enumerate}
     
    33413907int main( void ) {
    33423908        int x = 1, y = 2, z = 3;
    3343         sout | x | y | z | endl;
     3909        sout | x | y | z;
    33443910        [int, [ int, int ] ] t1 = [ 1, [ 2, 3 ] ], t2 = [ 4, [ 5, 6 ] ];
    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;
     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;
    33503916        sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥"
    3351                 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10 | endl;
     3917                | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10;
    33523918        sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x"
    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;
     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;
    33563922
    33573923        sepSet( sout, ", $" );                                          // set separator from " " to ", $"
    3358         sout | 1 | 2 | 3 | " \"" | sep | "\"" | endl;
     3924        sout | 1 | 2 | 3 | " \"" | sep | "\"";
    33593925        sepSet( sout, " " );                                            // reset separator to " "
    3360         sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"" | endl;
     3926        sout | 1 | 2 | 3 | " \"" | sepGet( sout ) | "\"";
    33613927
    33623928        char store[sepSize];
    33633929        strcpy( store, sepGet( sout ) );
    33643930        sepSet( sout, "_" );
    3365         sout | 1 | 2 | 3 | endl;
     3931        sout | 1 | 2 | 3;
    33663932        sepSet( sout, store );
    3367         sout | 1 | 2 | 3 | endl;
     3933        sout | 1 | 2 | 3;
    33683934
    33693935        sepSetTuple( sout, " " );                                       // set tuple separator from ", " to " "
    3370         sout | t1 | t2 | " \"" | sepTuple | "\"" | endl;
     3936        sout | t1 | t2 | " \"" | sepTuple | "\"";
    33713937        sepSetTuple( sout, ", " );                                      // reset tuple separator to ", "
    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
     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
    33793945        sout | sepEnable;
    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
     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
    33843950}
    33853951
     
    33903956\end{comment}
    33913957%$
     3958
     3959
     3960\subsection{Input Value Manipulators}
     3961
     3962The 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.
     3963For ©_Bool© type, the constants are ©true© and ©false©.
     3964For 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}
     3973For 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.
     3974Floating-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
     3976For 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.
     3977Instead, the next sequence of non-whitespace characters are read, and the input sequence is terminated with delimiter ©'\0'©.
     3978The string variable \emph{must} be large enough to contain the input sequence.
     3979
     3980The 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©
     3985The argument defines a ©pattern© or ©length©.
     3986The ©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.
     3987The ©length© is composed of the next $N$ characters, including the newline character.
     3988If the match successes, the input characters are discarded, and input continues with the next character.
     3989If the match fails, the input characters are left unread.
     3990\begin{cfa}[belowskip=0pt]
     3991char sk[$\,$] = "abc";
     3992sin | "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©}
     4002For all types except ©char©, ©maximum© is the maximum number of characters read for the current operation.
     4003\begin{cfa}[belowskip=0pt]
     4004char s[10];   int i;   double d;   
     4005sin | 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}
     4010Note, input ©wdi© cannot be overloaded with output ©wd© because both have the same parameters but return different types.
     4011Currently, \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©}
     4015For 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]
     4017double d;
     4018sin | 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©}
     4026For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{in} the set.
     4027Matching characters are read into the C string and null terminated.
     4028\begin{cfa}[belowskip=0pt]
     4029char s[10];
     4030sin | 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©}
     4038For the C-string type, the argument defines a ©scanset© that matches any number of characters \emph{not in} the set.
     4039Non-matching characters are read into the C string and null terminated.
     4040\begin{cfa}[belowskip=0pt]
     4041char s[10];
     4042sin | excl( "abc", s );
     4043\end{cfa}
     4044\begin{cfa}[showspaces=true,aboveskip=0pt,belowskip=0pt]
     4045®xyz®bca
     4046\end{cfa}
     4047\end{enumerate}
    33924048
    33934049
     
    37594415\begin{itemize}
    37604416\item
    3761 preventing having to determine or write long generic types,
    3762 \item
    3763 ensure secondary variables, related to a primary variable, always have the same type.
     4417not determining or writing long generic types,
     4418\item
     4419ensuring secondary variables, related to a primary variable, always have the same type.
    37644420\end{itemize}
    37654421
     
    37834439There is also the conundrum in type inferencing of when to \emph{\Index{brand}} a type.
    37844440That is, when is the type of the variable more important than the type of its initialization expression.
    3785 For example, if a change is made in an initialization expression, it can cause significant cascading type changes and/or errors.
     4441For example, if a change is made in an initialization expression, it can cause cascading type changes and/or errors.
    37864442At some point, a variable type needs to remain constant and the expression to be in error when it changes.
    37874443
     
    40164672
    40174673coroutine Fibonacci {
    4018         int fn;                                                         §\C{// used for communication}§
     4674        int fn; §\C{// used for communication}§
    40194675};
    40204676void ?{}( Fibonacci * this ) {
     
    40224678}
    40234679void main( Fibonacci * this ) {
    4024         int fn1, fn2;                                           §\C{// retained between resumes}§
    4025         this->fn = 0;                                           §\C{// case 0}§
     4680        int fn1, fn2; §\C{// retained between resumes}§
     4681        this->fn = 0; §\C{// case 0}§
    40264682        fn1 = this->fn;
    4027         suspend();                                                      §\C{// return to last resume}§
    4028 
    4029         this->fn = 1;                                           §\C{// case 1}§
     4683        suspend(); §\C{// return to last resume}§
     4684
     4685        this->fn = 1; §\C{// case 1}§
    40304686        fn2 = fn1;
    40314687        fn1 = this->fn;
    4032         suspend();                                                      §\C{// return to last resume}§
    4033 
    4034         for ( ;; ) {                                            §\C{// general case}§
     4688        suspend(); §\C{// return to last resume}§
     4689
     4690        for ( ;; ) { §\C{// general case}§
    40354691                this->fn = fn1 + fn2;
    40364692                fn2 = fn1;
    40374693                fn1 = this->fn;
    4038                 suspend();                                              §\C{// return to last resume}§
     4694                suspend(); §\C{// return to last resume}§
    40394695        } // for
    40404696}
    40414697int next( Fibonacci * this ) {
    4042         resume( this );                                         §\C{// transfer to last suspend}§
     4698        resume( this ); §\C{// transfer to last suspend}§
    40434699        return this->fn;
    40444700}
     
    40464702        Fibonacci f1, f2;
    40474703        for ( int i = 1; i <= 10; i += 1 ) {
    4048                 sout | next( &f1 ) | ' ' | next( &f2 ) | endl;
     4704                sout | next( &f1 ) | ' ' | next( &f2 );
    40494705        } // for
    40504706}
     
    41124768                MyThread f[4];
    41134769        }
    4114         sout | global.value | endl;
     4770        sout | global.value;
    41154771}
    41164772\end{cfa}
     
    41904846void main( First * this ) {
    41914847        for ( int i = 0; i < 10; i += 1 ) {
    4192                 sout | "First : Suspend No." | i + 1 | endl;
     4848                sout | "First : Suspend No." | i + 1;
    41934849                yield();
    41944850        }
     
    41994855        wait( this->lock );
    42004856        for ( int i = 0; i < 10; i += 1 ) {
    4201                 sout | "Second : Suspend No." | i + 1 | endl;
     4857                sout | "Second : Suspend No." | i + 1;
    42024858                yield();
    42034859        }
     
    42064862int main( void ) {
    42074863        signal_once lock;
    4208         sout | "User main begin" | endl;
     4864        sout | "User main begin";
    42094865        {
    42104866                processor p;
     
    42144870                }
    42154871        }
    4216         sout | "User main end" | endl;
     4872        sout | "User main end";
    42174873}
    42184874\end{cfa}
     
    49115567void ?{}( Line * l ) {
    49125568        l->lnth = 0.0;
    4913         sout | "default" | endl;
     5569        sout | "default";
    49145570}
    49155571
     
    49185574void ?{}( Line * l, float lnth ) {
    49195575        l->lnth = lnth;
    4920         sout | "lnth" | l->lnth | endl;
     5576        sout | "lnth" | l->lnth;
    49215577
    49225578}
     
    49245580// destructor
    49255581void ^?() {
    4926         sout | "destroyed" | endl;
     5582        sout | "destroyed";
    49275583        l.lnth = 0.0;
    49285584}
     
    55856241In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as:
    55866242\begin{cfa}
    5587 *?§\color{red}\textvisiblespace§*?              §\C{// dereference operator, dereference operator}§
    5588 *§\color{red}\textvisiblespace§?*?              §\C{// dereference, multiplication operator}§
     6243*?§\color{red}\textvisiblespace§*? §\C{// dereference operator, dereference operator}§
     6244*§\color{red}\textvisiblespace§?*? §\C{// dereference, multiplication operator}§
    55896245\end{cfa}
    55906246By default, the first interpretation is selected, which does not yield a meaningful parse.
     
    56386294\eg:
    56396295\begin{cfa}
    5640 x;                                                              §\C{// int x}§
    5641 *y;                                                             §\C{// int *y}§
    5642 f( p1, p2 );                                    §\C{// int f( int p1, int p2 );}§
    5643 g( p1, p2 ) int p1, p2;                 §\C{// int g( int p1, int p2 );}§
     6296x; §\C{// int x}§
     6297*y; §\C{// int *y}§
     6298f( p1, p2 ); §\C{// int f( int p1, int p2 );}§
     6299g( p1, p2 ) int p1, p2; §\C{// int g( int p1, int p2 );}§
    56446300\end{cfa}
    56456301\CFA continues to support K\&R routine definitions:
    56466302\begin{cfa}
    5647 f( a, b, c )                                    §\C{// default int return}§
    5648         int a, b; char c                        §\C{// K\&R parameter declarations}§
     6303f( a, b, c ) §\C{// default int return}§
     6304        int a, b; char c §\C{// K\&R parameter declarations}§
    56496305{
    56506306        ...
     
    56656321int rtn( int i );
    56666322int rtn( char c );
    5667 rtn( 'x' );                                             §\C{// programmer expects 2nd rtn to be called}§
     6323rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§
    56686324\end{cfa}
    56696325\item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first.
    56706326In particular, output of ©char© variable now print a character rather than the decimal ASCII value of the character.
    56716327\begin{cfa}
    5672 sout | 'x' | " " | (int)'x' | endl;
     6328sout | 'x' | " " | (int)'x';
    56736329x 120
    56746330\end{cfa}
     
    56876343\item[Change:] make string literals ©const©:
    56886344\begin{cfa}
    5689 char * p = "abc";                               §\C{// valid in C, deprecated in \CFA}§
    5690 char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§
     6345char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§
     6346char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§
    56916347\end{cfa}
    56926348The type of a string literal is changed from ©[] char© to ©const [] char©.
     
    56956351\begin{cfa}
    56966352char * p = "abc";
    5697 p[0] = 'w';                                             §\C{// segment fault or change constant literal}§
     6353p[0] = 'w'; §\C{// segment fault or change constant literal}§
    56986354\end{cfa}
    56996355The same problem occurs when passing a string literal to a routine that changes its argument.
     
    57076363\item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope:
    57086364\begin{cfa}
    5709 int i;                                                  §\C{// forward definition}§
    5710 int *j = ®&i®;                                  §\C{// forward reference, valid in C, invalid in \CFA}§
    5711 int i = 0;                                              §\C{// definition}§
     6365int i; §\C{// forward definition}§
     6366int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§
     6367int i = 0; §\C{// definition}§
    57126368\end{cfa}
    57136369is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed.
     
    57156371\begin{cfa}
    57166372struct X { int i; struct X *next; };
    5717 static struct X a;                              §\C{// forward definition}§
     6373static struct X a; §\C{// forward definition}§
    57186374static struct X b = { 0, ®&a® };§\C{// forward reference, valid in C, invalid in \CFA}§
    5719 static struct X a = { 1, &b };  §\C{// definition}§
     6375static struct X a = { 1, &b }; §\C{// definition}§
    57206376\end{cfa}
    57216377\item[Rationale:] avoids having different initialization rules for builtin types and user-defined types.
     
    57326388struct Person {
    57336389        enum ®Colour® { R, G, B };      §\C[7cm]{// nested type}§
    5734         struct Face {                           §\C{// nested type}§
    5735                 ®Colour® Eyes, Hair;    §\C{// type defined outside (1 level)}§
     6390        struct Face { §\C{// nested type}§
     6391                ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§
    57366392        };
    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}§
     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}§
    57406396};
    5741 ®Colour® c = R;                                 §\C{// type/enum defined same level}§
     6397®Colour® c = R; §\C{// type/enum defined same level}§
    57426398Person®.Colour® pc = Person®.®R;§\C{// type/enum defined inside}§
    5743 Person®.®Face pretty;                   §\C{// type defined inside}\CRT§
     6399Person®.®Face pretty; §\C{// type defined inside}\CRT§
    57446400\end{cfa}
    57456401In 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.
     
    57586414\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:
    57596415\begin{cfa}
    5760 struct Y;                                               §\C{// struct Y and struct X are at the same scope}§
     6416struct Y; §\C{// struct Y and struct X are at the same scope}§
    57616417struct X {
    57626418        struct Y { /* ... */ } y;
     
    57736429\begin{cfa}
    57746430void foo() {
    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 *}§
     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 *}§
    57776433}
    57786434\end{cfa}
     
    59476603void * memalign( size_t align, size_t size );§\indexc{memalign}§
    59486604int posix_memalign( void ** ptr, size_t align, size_t size );§\indexc{posix_memalign}§
    5949 }
    5950 
    5951 // §\CFA§ safe equivalents, i.e., implicit size specification
    5952 forall( dtype T | sized(T) ) T * malloc( void );
    5953 forall( dtype T | sized(T) ) T * calloc( size_t dim );
    5954 forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size );
    5955 forall( dtype T | sized(T) ) T * memalign( size_t align );
    5956 forall( dtype T | sized(T) ) T * aligned_alloc( size_t align );
    5957 forall( dtype T | sized(T) ) int posix_memalign( T ** ptr, size_t align );
    5958 
    5959 // §\CFA§ safe general allocation, fill, resize, array
    5960 forall( dtype T | sized(T) ) T * alloc( void );§\indexc{alloc}§
    5961 forall( dtype T | sized(T) ) T * alloc( char fill );
    5962 forall( dtype T | sized(T) ) T * alloc( size_t dim );
    5963 forall( dtype T | sized(T) ) T * alloc( size_t dim, char fill );
    5964 forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim );
    5965 forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
    5966 
    5967 // §\CFA§ safe general allocation, align, fill, array
    5968 forall( dtype T | sized(T) ) T * align_alloc( size_t align );
    5969 forall( dtype T | sized(T) ) T * align_alloc( size_t align, char fill );
    5970 forall( dtype T | sized(T) ) T * align_alloc( size_t align, size_t dim );
    5971 forall( dtype T | sized(T) ) T * align_alloc( size_t align, size_t dim, char fill );
    59726605
    59736606// C unsafe initialization/copy
    5974 extern "C" {
    59756607void * memset( void * dest, int c, size_t size );
    59766608void * memcpy( void * dest, const void * src, size_t size );
    59776609}
    59786610
     6611forall( 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
    59796634// §\CFA§ safe initialization/copy, i.e., implicit size specification
    5980 forall( dtype T | sized(T) ) T * memset( T * dest, char c );§\indexc{memset}§
    5981 forall( dtype T | sized(T) ) T * memcpy( T * dest, const T * src );§\indexc{memcpy}§
     6635        T * memset( T * dest, char c );§\indexc{memset}§
     6636        T * memcpy( T * dest, const T * src );§\indexc{memcpy}§
    59826637
    59836638// §\CFA§ safe initialization/copy array
    5984 forall( dtype T | sized(T) ) T * memset( T dest[], size_t dim, char c );
    5985 forall( dtype T | sized(T) ) T * memcpy( T dest[], const T src[], size_t dim );
     6639        T * amemset( T dest[], char c, size_t dim );
     6640        T * amemcpy( T dest[], const T src[], size_t dim );
     6641}
    59866642
    59876643// §\CFA§ allocation/deallocation and constructor/destructor
     
    59996655
    60006656
    6001 \subsection{Conversion}
     6657\subsection{String to Value Conversion}
    60026658
    60036659\leavevmode
     
    60356691\leavevmode
    60366692\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    6037 forall( otype T | { int ?<?( T, T ); } )        §\C{// location}§
     6693forall( otype T | { int ?<?( T, T ); } ) §\C{// location}§
    60386694T * bsearch( T key, const T * arr, size_t dim );§\indexc{bsearch}§
    60396695
    6040 forall( otype T | { int ?<?( T, T ); } )        §\C{// position}§
     6696forall( otype T | { int ?<?( T, T ); } ) §\C{// position}§
    60416697unsigned int bsearch( T key, const T * arr, size_t dim );
    60426698
    60436699forall( otype T | { int ?<?( T, T ); } )
    60446700void qsort( const T * arr, size_t dim );§\indexc{qsort}§
     6701
     6702forall( 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
     6711forall( 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
     6720forall( otype E | { int ?<?( E, E ); } ) {
     6721        void qsort( E * vals, size_t dim );§\indexc{qsort}§
     6722}
    60456723\end{cfa}
    60466724
     
    60696747\leavevmode
    60706748\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    6071 void rand48seed( long int s );§\indexc{rand48seed}§
    6072 char rand48();§\indexc{rand48}§
    6073 int rand48();
    6074 unsigned int rand48();
    6075 long int rand48();
    6076 unsigned long int rand48();
    6077 float rand48();
    6078 double rand48();
    6079 float _Complex rand48();
    6080 double _Complex rand48();
    6081 long double _Complex rand48();
     6749void srandom( unsigned int seed );§\indexc{srandom}§
     6750char random( void );§\indexc{random}§
     6751char random( char u ); §\C{// [0,u)}§
     6752char random( char l, char u ); §\C{// [l,u)}§
     6753int random( void );
     6754int random( int u ); §\C{// [0,u)}§
     6755int random( int l, int u ); §\C{// [l,u)}§
     6756unsigned int random( void );
     6757unsigned int random( unsigned int u ); §\C{// [0,u)}§
     6758unsigned int random( unsigned int l, unsigned int u ); §\C{// [l,u)}§
     6759long int random( void );
     6760long int random( long int u ); §\C{// [0,u)}§
     6761long int random( long int l, long int u ); §\C{// [l,u)}§
     6762unsigned long int random( void );
     6763unsigned long int random( unsigned long int u ); §\C{// [0,u)}§
     6764unsigned long int random( unsigned long int l, unsigned long int u ); §\C{// [l,u)}§
     6765float random( void );                                            §\C{// [0.0, 1.0)}§
     6766double random( void );                                           §\C{// [0.0, 1.0)}§
     6767float _Complex random( void );                           §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
     6768double _Complex random( void );                          §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
     6769long double _Complex random( void );             §\C{// [0.0, 1.0)+[0.0, 1.0)i}§
    60826770\end{cfa}
    60836771
     
    61226810[ int, long double ] remquo( long double, long double );
    61236811
    6124 float div( float, float, int * );§\indexc{div}§ §\C{// alternative name for remquo}§
     6812float div( float, float, int * );§\indexc{div}§ §\C{// alternative name for remquo}§
    61256813double div( double, double, int * );
    61266814long double div( long double, long double, int * );
     
    62786966long double atan2( long double, long double );
    62796967
    6280 float atan( float, float );                                     §\C{// alternative name for atan2}§
     6968float atan( float, float ); §\C{// alternative name for atan2}§
    62816969double atan( double, double );§\indexc{atan}§
    62826970long double atan( long double, long double );
     
    64587146
    64597147
    6460 \section{Time}
    6461 \label{s:TimeLib}
     7148\section{Time Keeping}
     7149\label{s:TimeKeeping}
    64627150
    64637151
    64647152%\subsection{\texorpdfstring{\protect\lstinline@Duration@}{Duration}}
    6465 \subsection{\texorpdfstring{\LstKeywordStyle{\textmd{Duration}}}{Duration}}
     7153\subsection{\texorpdfstring{\LstBasicStyle{Duration}}{Duration}}
    64667154\label{s:Duration}
    64677155
     
    64697157\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    64707158struct Duration {
    6471         int64_t tv;                                                     §\C{// nanoseconds}§
     7159        int64_t tv; §\C{// nanoseconds}§
    64727160};
    64737161
     
    65127200
    65137201Duration abs( Duration rhs );
    6514 
    6515 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Duration dur );
    65167202
    65177203Duration ?`ns( int64_t nsec );
     
    65377223int64_t ?`d( Duration dur );
    65387224int64_t ?`w( Duration dur );
     7225
     7226Duration max( Duration lhs, Duration rhs );
     7227Duration min( Duration lhs, Duration rhs );
    65397228\end{cfa}
    65407229
    65417230
    65427231%\subsection{\texorpdfstring{\protect\lstinline@\timeval@}{timeval}}
    6543 \subsection{\texorpdfstring{\LstKeywordStyle{\textmd{timeval}}}{timeval}}
     7232\subsection{\texorpdfstring{\LstBasicStyle{timeval}}{timeval}}
    65447233\label{s:timeval}
    65457234
     
    65607249
    65617250
    6562 \subsection{\texorpdfstring{\protect\lstinline@timespec@}{timespec}}
     7251%\subsection{\texorpdfstring{\protect\lstinline@timespec@}{timespec}}
     7252\subsection{\texorpdfstring{\LstBasicStyle{timespec}}{timespec}}
    65637253\label{s:timespec}
    65647254
     
    65797269
    65807270
    6581 \subsection{\texorpdfstring{\protect\lstinline@itimerval@}{itimerval}}
     7271%\subsection{\texorpdfstring{\protect\lstinline@itimerval@}{itimerval}}
     7272\subsection{\texorpdfstring{\LstBasicStyle{itimerval}}{itimerval}}
    65827273\label{s:itimerval}
    65837274
     
    65897280
    65907281
    6591 \subsection{\texorpdfstring{\protect\lstinline@Time@}{Time}}
     7282%\subsection{\texorpdfstring{\protect\lstinline@Time@}{Time}}
     7283\subsection{\texorpdfstring{\LstBasicStyle{Time}}{Time}}
    65927284\label{s:Time}
    65937285
     
    65957287\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    65967288struct Time {
    6597         uint64_t tv;                                            §\C{// nanoseconds since UNIX epoch}§
     7289        uint64_t tv; §\C{// nanoseconds since UNIX epoch}§
    65987290};
    65997291
    66007292void ?{}( Time & time );
    66017293void ?{}( Time & time, zero_t );
    6602 void ?{}( Time & time, int year, int month = 0, int day = 0, int hour = 0, int min = 0, int sec = 0, int nsec = 0 );
     7294
    66037295Time ?=?( Time & time, zero_t );
    66047296
     
    66097301Time ?=?( Time & time, timespec t );
    66107302
    6611 Time ?+?( Time & lhs, Duration rhs ) { return (Time)@{ lhs.tv + rhs.tv }; }
    6612 Time ?+?( Duration lhs, Time rhs ) { return rhs + lhs; }
    6613 Time ?+=?( Time & lhs, Duration rhs ) { lhs = lhs + rhs; return lhs; }
    6614 
    6615 Duration ?-?( Time lhs, Time rhs ) { return (Duration)@{ lhs.tv - rhs.tv }; }
    6616 Time ?-?( Time lhs, Duration rhs ) { return (Time)@{ lhs.tv - rhs.tv }; }
    6617 Time ?-=?( 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 
    6625 forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Time time );
     7303Time ?+?( Time & lhs, Duration rhs );
     7304Time ?+?( Duration lhs, Time rhs );
     7305Time ?+=?( Time & lhs, Duration rhs );
     7306
     7307Duration ?-?( Time lhs, Time rhs );
     7308Time ?-?( Time lhs, Duration rhs );
     7309Time ?-=?( 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 );
    66267316
    66277317char * yy_mm_dd( Time time, char * buf );
     
    66417331
    66427332size_t strftime( char * buf, size_t size, const char * fmt, Time time );
     7333forall( dtype ostype | ostream( ostype ) ) ostype & ?|?( ostype & os, Time time );
    66437334\end{cfa}
    66447335
     
    66617352
    66627353%\subsection{\texorpdfstring{\protect\lstinline@Clock@}{Clock}}
    6663 \subsection{\texorpdfstring{\LstKeywordStyle{\textmd{Clock}}}{Clock}}
     7354\subsection{\texorpdfstring{\LstBasicStyle{Clock}}{Clock}}
    66647355\label{s:Clock}
    66657356
     
    66677358\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    66687359struct Clock {
    6669         Duration offset;                                        §\C{// for virtual clock: contains offset from real-time}§
    6670         int clocktype;                                          §\C{// implementation only -1 (virtual), CLOCK\_REALTIME}§
     7360        Duration offset; §\C{// for virtual clock: contains offset from real-time}§
     7361        int clocktype; §\C{// implementation only -1 (virtual), CLOCK\_REALTIME}§
    66717362};
    66727363
     
    66757366void ?{}( Clock & clk );
    66767367void ?{}( Clock & clk, Duration adj );
    6677 Duration getRes();
    6678 Time getTimeNsec();                                             §\C{// with nanoseconds}§
    6679 Time getTime();                                                 §\C{// without nanoseconds}§
     7368
     7369Duration getResNsec(); §\C{// with nanoseconds}§
     7370Duration getRes(); §\C{// without nanoseconds}§
     7371
     7372Time getTimeNsec(); §\C{// with nanoseconds}§
     7373Time getTime(); §\C{// without nanoseconds}§
    66807374Time getTime( Clock & clk );
    66817375Time ?()( Clock & clk );
     
    66937387
    66947388\begin{cfa}
    6695 void ?{}( Int * this );                                 §\C{// constructor/destructor}§
     7389void ?{}( Int * this ); §\C{// constructor/destructor}§
    66967390void ?{}( Int * this, Int init );
    66977391void ?{}( Int * this, zero_t );
     
    67027396void ^?{}( Int * this );
    67037397
    6704 Int ?=?( Int * lhs, Int rhs );                  §\C{// assignment}§
     7398Int ?=?( Int * lhs, Int rhs ); §\C{// assignment}§
    67057399Int ?=?( Int * lhs, long int rhs );
    67067400Int ?=?( Int * lhs, unsigned long int rhs );
     
    67197413unsigned long int narrow( Int val );
    67207414
    6721 int ?==?( Int oper1, Int oper2 );               §\C{// comparison}§
     7415int ?==?( Int oper1, Int oper2 ); §\C{// comparison}§
    67227416int ?==?( Int oper1, long int oper2 );
    67237417int ?==?( long int oper2, Int oper1 );
     
    67557449int ?>=?( unsigned long int oper1, Int oper2 );
    67567450
    6757 Int +?( Int oper );                                             §\C{// arithmetic}§
     7451Int +?( Int oper ); §\C{// arithmetic}§
    67587452Int -?( Int oper );
    67597453Int ~?( Int oper );
     
    68377531Int ?>>=?( Int * lhs, mp_bitcnt_t shift );
    68387532
    6839 Int abs( Int oper );                                    §\C{// number functions}§
     7533Int abs( Int oper ); §\C{// number functions}§
    68407534Int fact( unsigned long int N );
    68417535Int gcd( Int oper1, Int oper2 );
     
    68627556#include <gmp>§\indexc{gmp}§
    68637557int main( void ) {
    6864         sout | "Factorial Numbers" | endl;
     7558        sout | "Factorial Numbers";
    68657559        Int fact = 1;
    68667560
    6867         sout | 0 | fact | endl;
     7561        sout | 0 | fact;
    68687562        for ( unsigned int i = 1; i <= 40; i += 1 ) {
    68697563                fact *= i;
    6870                 sout | i | fact | endl;
     7564                sout | i | fact;
    68717565        }
    68727566}
     
    69487642// implementation
    69497643struct Rational {§\indexc{Rational}§
    6950         long int numerator, denominator;        §\C{// invariant: denominator > 0}§
     7644        long int numerator, denominator; §\C{// invariant: denominator > 0}§
    69517645}; // Rational
    69527646
    6953 Rational rational();                                    §\C{// constructors}§
     7647Rational rational(); §\C{// constructors}§
    69547648Rational rational( long int n );
    69557649Rational rational( long int n, long int d );
     
    69577651void ?{}( Rational * r, one_t );
    69587652
    6959 long int numerator( Rational r );               §\C{// numerator/denominator getter/setter}§
     7653long int numerator( Rational r ); §\C{// numerator/denominator getter/setter}§
    69607654long int numerator( Rational r, long int n );
    69617655long int denominator( Rational r );
    69627656long int denominator( Rational r, long int d );
    69637657
    6964 int ?==?( Rational l, Rational r );             §\C{// comparison}§
     7658int ?==?( Rational l, Rational r ); §\C{// comparison}§
    69657659int ?!=?( Rational l, Rational r );
    69667660int ?<?( Rational l, Rational r );
     
    69697663int ?>=?( Rational l, Rational r );
    69707664
    6971 Rational -?( Rational r );                              §\C{// arithmetic}§
     7665Rational -?( Rational r ); §\C{// arithmetic}§
    69727666Rational ?+?( Rational l, Rational r );
    69737667Rational ?-?( Rational l, Rational r );
     
    69757669Rational ?/?( Rational l, Rational r );
    69767670
    6977 double widen( Rational r );                             §\C{// conversion}§
     7671double widen( Rational r ); §\C{// conversion}§
    69787672Rational narrow( double f, long int md );
    69797673
  • doc/working/exception/impl/exception.c

    r7951100 rb067d9b  
    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
    322327        asm volatile (".cfi_personality 0x3,__gcfa_personality_v0");
    323328        // Setup the exception table
    324329        asm volatile (".cfi_lsda 0x3, .LLSDACFA2");
     330        #endif
    325331
    326332        // Label which defines the start of the area for which the handler is setup
     
    356362// Some more works need to be done if we want to have a single
    357363// call to the try routine
     364#if defined(__PIC__)
     365asm (
     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;
     388asm (
     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
    358399asm (
    359400        //HEADER
     
    375416        "       .text\n"                                                        // TABLE footer
    376417        "       .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"
    379418);
     419#endif
  • src/CodeGen/CodeGenerator.cc

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May  5 09:08:32 2018
    13 // Update Count     : 494
     12// Last Modified On : Sat Oct 19 19:30:38 2019
     13// Update Count     : 506
    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 ( !lineMarks || to.isUnset() ) return;
     85                if ( !options.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( CodeGenerator::tabsize ), output( os ), printLabels( *this ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ), printExprTypes( printExprTypes ), endl( *this ) {}
     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 ) {}
    119120
    120121        string CodeGenerator::mangleName( DeclarationWithType * decl ) {
    121122                // GCC builtins should always be printed unmangled
    122                 if ( pretty || decl->linkage.is_gcc_builtin ) return decl->name;
     123                if ( options.pretty || decl->linkage.is_gcc_builtin ) return decl->name;
    123124                if ( decl->mangleName != "" ) {
    124125                        // need to incorporate scope level in order to differentiate names for destructors
     
    133134                output << "__attribute__ ((";
    134135                for ( list< Attribute * >::iterator attr( attributes.begin() );; ) {
    135                         output << (*attr)->get_name();
    136                         if ( ! (*attr)->get_parameters().empty() ) {
     136                        output << (*attr)->name;
     137                        if ( ! (*attr)->parameters.empty() ) {
    137138                                output << "(";
    138                                 genCommaList( (*attr)->get_parameters().begin(), (*attr)->get_parameters().end() );
     139                                genCommaList( (*attr)->parameters.begin(), (*attr)->parameters.end() );
    139140                                output << ")";
    140141                        } // if
     
    164165                previsit( (BaseSyntaxNode *)node );
    165166                GuardAction( [this, node](){
    166                         if ( printExprTypes ) {
    167                                 output << " /* " << genType( node->result, "", pretty, genC ) << " */ ";
     167                        if ( options.printExprTypes && node->result ) {
     168                                output << " /* " << genType( node->result, "", options ) << " */ ";
    168169                        }
    169170                } );
     
    173174        void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
    174175                // deleted decls should never be used, so don't print them
    175                 if ( functionDecl->isDeleted && genC ) return;
     176                if ( functionDecl->isDeleted && options.genC ) return;
    176177                extension( functionDecl );
    177178                genAttributes( functionDecl->get_attributes() );
     
    180181                functionDecl->get_funcSpec().print( output );
    181182
    182                 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), pretty, genC );
     183                Options subOptions = options;
     184                subOptions.anonymousUnused = functionDecl->has_body();
     185                output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), subOptions );
    183186
    184187                asmName( functionDecl );
     
    194197        void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
    195198                // deleted decls should never be used, so don't print them
    196                 if ( objectDecl->isDeleted && genC ) return;
    197                 if (objectDecl->get_name().empty() && genC ) {
     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() ) {
    198205                        // only generate an anonymous name when generating C code, otherwise it clutters the output too much
    199206                        static UniqueName name = { "__anonymous_object" };
    200207                        objectDecl->set_name( name.newName() );
     208                        // Stops unused parameter warnings.
     209                        if ( options.anonymousUnused ) {
     210                                objectDecl->attributes.push_back( new Attribute( "unused" ) );
     211                        }
    201212                }
    202213
     
    205216
    206217                handleStorageClass( objectDecl );
    207                 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty, genC );
     218                output << genType( objectDecl->get_type(), mangleName( objectDecl ), options.pretty, options.genC );
    208219
    209220                asmName( objectDecl );
     
    224235
    225236        void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) {
    226                 if( ! aggDecl->get_parameters().empty() && ! genC ) {
     237                if( ! aggDecl->parameters.empty() && ! options.genC ) {
    227238                        // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    228239                        output << "forall(";
    229                         genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() );
     240                        genCommaList( aggDecl->parameters.begin(), aggDecl->parameters.end() );
    230241                        output << ")" << endl;
    231242                        output << indent;
     
    233244
    234245                output << kind;
    235                 genAttributes( aggDecl->get_attributes() );
    236                 output << aggDecl->get_name();
     246                genAttributes( aggDecl->attributes );
     247                output << aggDecl->name;
    237248
    238249                if ( aggDecl->has_body() ) {
    239                         std::list< Declaration * > & memb = aggDecl->get_members();
     250                        std::list< Declaration * > & memb = aggDecl->members;
    240251                        output << " {" << endl;
    241252
     
    294305
    295306        void CodeGenerator::postvisit( TraitDecl * traitDecl ) {
    296                 assertf( ! genC, "TraitDecls should not reach code generation." );
     307                assertf( ! options.genC, "TraitDecls should not reach code generation." );
    297308                extension( traitDecl );
    298309                handleAggregate( traitDecl, "trait " );
     
    300311
    301312        void CodeGenerator::postvisit( TypedefDecl * typeDecl ) {
    302                 assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );
     313                assertf( ! options.genC, "Typedefs are removed and substituted in earlier passes." );
    303314                output << "typedef ";
    304                 output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl;
     315                output << genType( typeDecl->get_base(), typeDecl->get_name(), options ) << endl;
    305316        }
    306317
    307318        void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
    308                 assertf( ! genC, "TypeDecls should not reach code generation." );
     319                assertf( ! options.genC, "TypeDecls should not reach code generation." );
    309320                output << typeDecl->genTypeString() << " " << typeDecl->name;
    310321                if ( typeDecl->sized ) {
     
    371382
    372383        void CodeGenerator::postvisit( ConstructorInit * init ){
    373                 assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
     384                assertf( ! options.genC, "ConstructorInit nodes should not reach code generation." );
    374385                // pseudo-output for constructor/destructor pairs
    375386                output << "<ctorinit>{" << endl << ++indent << "ctor: ";
     
    507518                                        } else {
    508519                                                // no constructors with 0 or more than 2 parameters
    509                                                 assertf( ! genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
     520                                                assertf( ! options.genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
    510521                                                output << "(";
    511522                                                (*arg++)->accept( *visitor );
     
    604615                        // an lvalue cast, this has been taken out.
    605616                        output << "(";
    606                         output << genType( castExpr->get_result(), "", pretty, genC );
     617                        output << genType( castExpr->get_result(), "", options );
    607618                        output << ")";
    608619                } // if
     
    612623
    613624        void CodeGenerator::postvisit( KeywordCastExpr * castExpr ) {
    614                 assertf( ! genC, "KeywordCast should not reach code generation." );
     625                assertf( ! options.genC, "KeywordCast should not reach code generation." );
    615626                extension( castExpr );
    616627                output << "((" << castExpr->targetString() << " &)";
     
    620631
    621632        void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
    622                 assertf( ! genC, "VirtualCastExpr should not reach code generation." );
     633                assertf( ! options.genC, "VirtualCastExpr should not reach code generation." );
    623634                extension( castExpr );
    624635                output << "(virtual ";
     
    628639
    629640        void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
    630                 assertf( ! genC, "UntypedMemberExpr should not reach code generation." );
     641                assertf( ! options.genC, "UntypedMemberExpr should not reach code generation." );
    631642                extension( memberExpr );
    632643                memberExpr->get_aggregate()->accept( *visitor );
     
    661672                output << "sizeof(";
    662673                if ( sizeofExpr->get_isType() ) {
    663                         output << genType( sizeofExpr->get_type(), "", pretty, genC );
     674                        output << genType( sizeofExpr->get_type(), "", options );
    664675                } else {
    665676                        sizeofExpr->get_expr()->accept( *visitor );
     
    673684                output << "__alignof__(";
    674685                if ( alignofExpr->get_isType() ) {
    675                         output << genType( alignofExpr->get_type(), "", pretty, genC );
     686                        output << genType( alignofExpr->get_type(), "", options );
    676687                } else {
    677688                        alignofExpr->get_expr()->accept( *visitor );
     
    681692
    682693        void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
    683                 assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );
     694                assertf( ! options.genC, "UntypedOffsetofExpr should not reach code generation." );
    684695                output << "offsetof(";
    685                 output << genType( offsetofExpr->get_type(), "", pretty, genC );
     696                output << genType( offsetofExpr->get_type(), "", options );
    686697                output << ", " << offsetofExpr->get_member();
    687698                output << ")";
     
    691702                // use GCC builtin
    692703                output << "__builtin_offsetof(";
    693                 output << genType( offsetofExpr->get_type(), "", pretty, genC );
     704                output << genType( offsetofExpr->get_type(), "", options );
    694705                output << ", " << mangleName( offsetofExpr->get_member() );
    695706                output << ")";
     
    697708
    698709        void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
    699                 assertf( ! genC, "OffsetPackExpr should not reach code generation." );
    700                 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")";
     710                assertf( ! options.genC, "OffsetPackExpr should not reach code generation." );
     711                output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", options ) << ")";
    701712        }
    702713
     
    728739                extension( commaExpr );
    729740                output << "(";
    730                 if ( genC ) {
     741                if ( options.genC ) {
    731742                        // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
    732743                        commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
     
    739750
    740751        void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
    741                 assertf( ! genC, "TupleAssignExpr should not reach code generation." );
     752                assertf( ! options.genC, "TupleAssignExpr should not reach code generation." );
    742753                tupleExpr->stmtExpr->accept( *visitor );
    743754        }
    744755
    745756        void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
    746                 assertf( ! genC, "UntypedTupleExpr should not reach code generation." );
     757                assertf( ! options.genC, "UntypedTupleExpr should not reach code generation." );
    747758                extension( tupleExpr );
    748759                output << "[";
     
    752763
    753764        void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
    754                 assertf( ! genC, "TupleExpr should not reach code generation." );
     765                assertf( ! options.genC, "TupleExpr should not reach code generation." );
    755766                extension( tupleExpr );
    756767                output << "[";
     
    760771
    761772        void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
    762                 assertf( ! genC, "TupleIndexExpr should not reach code generation." );
     773                assertf( ! options.genC, "TupleIndexExpr should not reach code generation." );
    763774                extension( tupleExpr );
    764775                tupleExpr->get_tuple()->accept( *visitor );
     
    767778
    768779        void CodeGenerator::postvisit( TypeExpr * typeExpr ) {
    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 );
     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 );
    773784                }
    774785        }
     
    788799        void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
    789800                assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
    790                 output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
     801                output << "(" << genType( compLitExpr->get_result(), "", options ) << ")";
    791802                compLitExpr->get_initializer()->accept( *visitor );
    792803        }
    793804
    794805        void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
    795                 assertf( ! genC, "Unique expressions should not reach code generation." );
     806                assertf( ! options.genC, "Unique expressions should not reach code generation." );
    796807                output << "unq<" << unqExpr->get_id() << ">{ ";
    797808                unqExpr->get_expr()->accept( *visitor );
     
    829840
    830841        void CodeGenerator::postvisit( ConstructorExpr * expr ) {
    831                 assertf( ! genC, "Unique expressions should not reach code generation." );
     842                assertf( ! options.genC, "Unique expressions should not reach code generation." );
    832843                expr->callExpr->accept( *visitor );
    833844        }
    834845
    835846        void CodeGenerator::postvisit( DeletedExpr * expr ) {
    836                 assertf( ! genC, "Deleted expressions should not reach code generation." );
     847                assertf( ! options.genC, "Deleted expressions should not reach code generation." );
    837848                expr->expr->accept( *visitor );
    838849        }
    839850
     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
    840856        void CodeGenerator::postvisit( GenericExpr * expr ) {
    841                 assertf( ! genC, "C11 _Generic expressions should not reach code generation." );
     857                assertf( ! options.genC, "C11 _Generic expressions should not reach code generation." );
    842858                output << "_Generic(";
    843859                expr->control->accept( *visitor );
     
    849865                                output << "default: ";
    850866                        } else {
    851                                 output << genType( assoc.type, "", pretty, genC ) << ": ";
     867                                output << genType( assoc.type, "", options ) << ": ";
    852868                        }
    853869                        assoc.expr->accept( *visitor );
     
    884900        void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
    885901                assert( exprStmt );
    886                 if ( genC ) {
     902                if ( options.genC ) {
    887903                        // cast the top-level expression to void to reduce gcc warnings.
    888904                        exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
     
    9941010                  case BranchStmt::FallThrough:
    9951011                  case BranchStmt::FallThroughDefault:
    996                         assertf( ! genC, "fallthru should not reach code generation." );
     1012                        assertf( ! options.genC, "fallthru should not reach code generation." );
    9971013                  output << "fallthru";
    9981014                        break;
    9991015                } // switch
    10001016                // print branch target for labelled break/continue/fallthru in debug mode
    1001                 if ( ! genC && branchStmt->get_type() != BranchStmt::Goto ) {
     1017                if ( ! options.genC && branchStmt->get_type() != BranchStmt::Goto ) {
    10021018                        if ( ! branchStmt->get_target().empty() ) {
    10031019                                output << " " << branchStmt->get_target();
     
    10161032
    10171033        void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
    1018                 assertf( ! genC, "Throw statements should not reach code generation." );
     1034                assertf( ! options.genC, "Throw statements should not reach code generation." );
    10191035
    10201036                output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ?
     
    10311047        }
    10321048        void CodeGenerator::postvisit( CatchStmt * stmt ) {
    1033                 assertf( ! genC, "Catch statements should not reach code generation." );
     1049                assertf( ! options.genC, "Catch statements should not reach code generation." );
    10341050
    10351051                output << ((stmt->get_kind() == CatchStmt::Terminate) ?
     
    10481064
    10491065        void CodeGenerator::postvisit( WaitForStmt * stmt ) {
    1050                 assertf( ! genC, "Waitfor statements should not reach code generation." );
     1066                assertf( ! options.genC, "Waitfor statements should not reach code generation." );
    10511067
    10521068                bool first = true;
     
    10941110
    10951111        void CodeGenerator::postvisit( WithStmt * with ) {
    1096                 if ( ! genC ) {
     1112                if ( ! options.genC ) {
    10971113                        output << "with ( ";
    10981114                        genCommaList( with->exprs.begin(), with->exprs.end() );
     
    11601176
    11611177        void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
    1162                 assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );
     1178                assertf( ! options.genC, "ImplicitCtorDtorStmts should not reach code generation." );
    11631179                stmt->callStmt->accept( *visitor );
    11641180        }
  • src/CodeGen/CodeGenerator.h

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Aug 18 15:40:00 2017
    13 // Update Count     : 56
     12// Last Modified On : Tue Apr 30 12:01:00 2019
     13// Update Count     : 57
    1414//
    1515
     
    2020#include <string>                 // for string
    2121
     22#include "CodeGen/Options.h"      // for Options
    2223#include "Common/Indenter.h"      // for Indenter
    2324#include "Common/PassVisitor.h"   // for PassVisitor
     
    3132
    3233                CodeGenerator( std::ostream &os, bool pretty = false, bool genC = false, bool lineMarks = false, bool printExprTypes = false );
     34                CodeGenerator( std::ostream &os, const Options &options );
    3335
    3436                //*** Turn off visit_children for all nodes
     
    9496                void postvisit( ConstructorExpr * );
    9597                void postvisit( DeletedExpr * );
     98                void postvisit( DefaultArgExpr * );
    9699                void postvisit( GenericExpr * );
    97100
     
    143146                std::ostream & output;
    144147                LabelPrinter printLabels;
    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;
     148                Options options;
    149149        public:
    150150                LineEnder endl;
  • src/CodeGen/GenType.cc

    r7951100 rb067d9b  
    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 : Fri Mar 17 09:02:28 2017
    13 // Update Count     : 22
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed May  1 15:24:00 2019
     13// Update Count     : 23
    1414//
    1515#include "GenType.h"
     
    2727namespace CodeGen {
    2828        struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
    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; }
     29                std::string typeString;
     30                GenType( const std::string &typeString, const Options &options );
    3231
    3332                void previsit( BaseSyntaxNode * );
     
    4847                void postvisit( ZeroType * zeroType );
    4948                void postvisit( OneType * oneType );
     49                void postvisit( GlobalScopeType * globalType );
    5050                void postvisit( TraitInstType * inst );
    5151                void postvisit( TypeofType * typeof );
     52                void postvisit( QualifiedType * qualType );
    5253
    5354          private:
     
    5657                void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
    5758
    58                 std::string typeString;
    59                 bool pretty = false; // pretty print
    60                 bool genC = false;   // generating C code?
    61                 bool lineMarks = false;
     59                Options options;
    6260        };
    6361
     62        std::string genType( Type *type, const std::string &baseString, const Options &options ) {
     63                PassVisitor<GenType> gt( baseString, options );
     64                std::ostringstream os;
     65
     66                if ( ! type->get_attributes().empty() ) {
     67                        PassVisitor<CodeGenerator> cg( os, options );
     68                        cg.pass.genAttributes( type->get_attributes() );
     69                } // if
     70
     71                type->accept( gt );
     72                return os.str() + gt.pass.typeString;
     73        }
     74
    6475        std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
    65                 PassVisitor<GenType> gt( baseString, pretty, genC, lineMarks );
    66                 std::ostringstream os;
    67 
    68                 if ( ! type->get_attributes().empty() ) {
    69                         PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
    70                         cg.pass.genAttributes( type->get_attributes() );
    71                 } // if
    72 
    73                 type->accept( gt );
    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 ) {}
     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 ) {}
    8284
    8385        // *** BaseSyntaxNode
     
    133135                } // if
    134136                if ( dimension != 0 ) {
    135                         PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     137                        PassVisitor<CodeGenerator> cg( os, options );
    136138                        dimension->accept( cg );
    137139                } else if ( isVarLen ) {
     
    167169        void GenType::postvisit( ReferenceType * refType ) {
    168170                assert( refType->base != 0);
    169                 assertf( ! genC, "Reference types should not reach code generation." );
     171                assertf( ! options.genC, "Reference types should not reach code generation." );
    170172                handleQualifiers( refType );
    171173                typeString = "&" + typeString;
     
    195197                        } // if
    196198                } else {
    197                         PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     199                        PassVisitor<CodeGenerator> cg( os, options );
    198200                        os << "(" ;
    199201
     
    215217
    216218                // add forall
    217                 if( ! funcType->forall.empty() && ! genC ) {
     219                if( ! funcType->forall.empty() && ! options.genC ) {
    218220                        // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    219221                        std::ostringstream os;
    220                         PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     222                        PassVisitor<CodeGenerator> cg( os, options );
    221223                        os << "forall(";
    222224                        cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() );
     
    229231                if ( ! refType->parameters.empty() ) {
    230232                        std::ostringstream os;
    231                         PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     233                        PassVisitor<CodeGenerator> cg( os, options );
    232234                        os << "(";
    233235                        cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
     
    240242        void GenType::postvisit( StructInstType * structInst )  {
    241243                typeString = structInst->name + handleGeneric( structInst ) + " " + typeString;
    242                 if ( genC ) typeString = "struct " + typeString;
     244                if ( options.genC ) typeString = "struct " + typeString;
    243245                handleQualifiers( structInst );
    244246        }
     
    246248        void GenType::postvisit( UnionInstType * unionInst ) {
    247249                typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString;
    248                 if ( genC ) typeString = "union " + typeString;
     250                if ( options.genC ) typeString = "union " + typeString;
    249251                handleQualifiers( unionInst );
    250252        }
     
    252254        void GenType::postvisit( EnumInstType * enumInst ) {
    253255                typeString = enumInst->name + " " + typeString;
    254                 if ( genC ) typeString = "enum " + typeString;
     256                if ( options.genC ) typeString = "enum " + typeString;
    255257                handleQualifiers( enumInst );
    256258        }
     
    262264
    263265        void GenType::postvisit( TupleType * tupleType ) {
    264                 assertf( ! genC, "Tuple types should not reach code generation." );
     266                assertf( ! options.genC, "Tuple types should not reach code generation." );
    265267                unsigned int i = 0;
    266268                std::ostringstream os;
     
    268270                for ( Type * t : *tupleType ) {
    269271                        i++;
    270                         os << genType( t, "", pretty, genC, lineMarks ) << (i == tupleType->size() ? "" : ", ");
     272                        os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", ");
    271273                }
    272274                os << "] ";
     
    281283        void GenType::postvisit( ZeroType * zeroType ) {
    282284                // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    283                 typeString = (pretty ? "zero_t " : "long int ") + typeString;
     285                typeString = (options.pretty ? "zero_t " : "long int ") + typeString;
    284286                handleQualifiers( zeroType );
    285287        }
     
    287289        void GenType::postvisit( OneType * oneType ) {
    288290                // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    289                 typeString = (pretty ? "one_t " : "long int ") + typeString;
     291                typeString = (options.pretty ? "one_t " : "long int ") + typeString;
    290292                handleQualifiers( oneType );
    291293        }
    292294
     295        void GenType::postvisit( GlobalScopeType * globalType ) {
     296                assertf( ! options.genC, "Global scope type should not reach code generation." );
     297                handleQualifiers( globalType );
     298        }
     299
    293300        void GenType::postvisit( TraitInstType * inst ) {
    294                 assertf( ! genC, "Trait types should not reach code generation." );
     301                assertf( ! options.genC, "Trait types should not reach code generation." );
    295302                typeString = inst->name + " " + typeString;
    296303                handleQualifiers( inst );
     
    299306        void GenType::postvisit( TypeofType * typeof ) {
    300307                std::ostringstream os;
    301                 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     308                PassVisitor<CodeGenerator> cg( os, options );
    302309                os << "typeof(";
    303310                typeof->expr->accept( cg );
     
    307314        }
    308315
     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
    309324        void GenType::handleQualifiers( Type * type ) {
    310325                if ( type->get_const() ) {
     
    320335                        typeString = "_Atomic " + typeString;
    321336                } // if
    322                 if ( type->get_lvalue() && ! genC ) {
    323                         // when not generating C code, print lvalue for debugging.
    324                         typeString = "lvalue " + typeString;
    325                 }
    326337        }
    327338} // namespace CodeGen
  • src/CodeGen/GenType.h

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

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

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

    r7951100 rb067d9b  
    3939}
    4040
     41void abort(const char *fmt, ... ) noexcept __attribute__((noreturn, format(printf, 1, 2)));
     42void 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
    4151// Local Variables: //
    4252// tab-width: 4 //
  • src/Common/Debug.h

    r7951100 rb067d9b  
    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::Compiler ) {
     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 ) {
    3131        #ifdef DEBUG
    3232                std::list< Declaration * > decls;
  • src/Common/Indenter.h

    r7951100 rb067d9b  
    1818
    1919struct Indenter {
    20         static unsigned tabsize;
     20        static unsigned tabsize;  ///< default number of spaces in one level of indentation
    2121
    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;
     22        unsigned int indent;      ///< number of spaces to indent
     23        unsigned int amt;         ///< spaces in one level of indentation
    2524
    26         Indenter & operator+=(int nlevels) { indent += amt*nlevels; return *this; }
    27         Indenter & operator-=(int nlevels) { indent -= amt*nlevels; return *this; }
     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; }
    2830        Indenter operator+(int nlevels) { Indenter indenter = *this; return indenter += nlevels; }
    2931        Indenter operator-(int nlevels) { Indenter indenter = *this; return indenter -= nlevels; }
     
    3335
    3436inline std::ostream & operator<<( std::ostream & out, const Indenter & indent ) {
    35         return out << std::string(indent.indent, ' ');
     37        return out << std::string(indent.indent * indent.amt, ' ');
    3638}
    3739
  • src/Common/PassVisitor.h

    r7951100 rb067d9b  
    44
    55#include <stack>
    6 
     6#include <type_traits>
     7
     8#include "Common/Stats.h"
    79#include "Common/utility.h"
    810
     
    5860
    5961        virtual void visit( ObjectDecl * objectDecl ) override final;
     62        virtual void visit( const ObjectDecl * objectDecl ) override final;
    6063        virtual void visit( FunctionDecl * functionDecl ) override final;
     64        virtual void visit( const FunctionDecl * functionDecl ) override final;
    6165        virtual void visit( StructDecl * aggregateDecl ) override final;
     66        virtual void visit( const StructDecl * aggregateDecl ) override final;
    6267        virtual void visit( UnionDecl * aggregateDecl ) override final;
     68        virtual void visit( const UnionDecl * aggregateDecl ) override final;
    6369        virtual void visit( EnumDecl * aggregateDecl ) override final;
     70        virtual void visit( const EnumDecl * aggregateDecl ) override final;
    6471        virtual void visit( TraitDecl * aggregateDecl ) override final;
     72        virtual void visit( const TraitDecl * aggregateDecl ) override final;
    6573        virtual void visit( TypeDecl * typeDecl ) override final;
     74        virtual void visit( const TypeDecl * typeDecl ) override final;
    6675        virtual void visit( TypedefDecl * typeDecl ) override final;
     76        virtual void visit( const TypedefDecl * typeDecl ) override final;
    6777        virtual void visit( AsmDecl * asmDecl ) override final;
     78        virtual void visit( const AsmDecl * asmDecl ) override final;
    6879        virtual void visit( StaticAssertDecl * assertDecl ) override final;
     80        virtual void visit( const StaticAssertDecl * assertDecl ) override final;
    6981
    7082        virtual void visit( CompoundStmt * compoundStmt ) override final;
     83        virtual void visit( const CompoundStmt * compoundStmt ) override final;
    7184        virtual void visit( ExprStmt * exprStmt ) override final;
     85        virtual void visit( const ExprStmt * exprStmt ) override final;
    7286        virtual void visit( AsmStmt * asmStmt ) override final;
     87        virtual void visit( const AsmStmt * asmStmt ) override final;
    7388        virtual void visit( DirectiveStmt * dirStmt ) override final;
     89        virtual void visit( const DirectiveStmt * dirStmt ) override final;
    7490        virtual void visit( IfStmt * ifStmt ) override final;
     91        virtual void visit( const IfStmt * ifStmt ) override final;
    7592        virtual void visit( WhileStmt * whileStmt ) override final;
     93        virtual void visit( const WhileStmt * whileStmt ) override final;
    7694        virtual void visit( ForStmt * forStmt ) override final;
     95        virtual void visit( const ForStmt * forStmt ) override final;
    7796        virtual void visit( SwitchStmt * switchStmt ) override final;
     97        virtual void visit( const SwitchStmt * switchStmt ) override final;
    7898        virtual void visit( CaseStmt * caseStmt ) override final;
     99        virtual void visit( const CaseStmt * caseStmt ) override final;
    79100        virtual void visit( BranchStmt * branchStmt ) override final;
     101        virtual void visit( const BranchStmt * branchStmt ) override final;
    80102        virtual void visit( ReturnStmt * returnStmt ) override final;
     103        virtual void visit( const ReturnStmt * returnStmt ) override final;
    81104        virtual void visit( ThrowStmt * throwStmt ) override final;
     105        virtual void visit( const ThrowStmt * throwStmt ) override final;
    82106        virtual void visit( TryStmt * tryStmt ) override final;
     107        virtual void visit( const TryStmt * tryStmt ) override final;
    83108        virtual void visit( CatchStmt * catchStmt ) override final;
     109        virtual void visit( const CatchStmt * catchStmt ) override final;
    84110        virtual void visit( FinallyStmt * finallyStmt ) override final;
     111        virtual void visit( const FinallyStmt * finallyStmt ) override final;
    85112        virtual void visit( WaitForStmt * waitforStmt ) override final;
     113        virtual void visit( const WaitForStmt * waitforStmt ) override final;
    86114        virtual void visit( WithStmt * withStmt ) override final;
     115        virtual void visit( const WithStmt * withStmt ) override final;
    87116        virtual void visit( NullStmt * nullStmt ) override final;
     117        virtual void visit( const NullStmt * nullStmt ) override final;
    88118        virtual void visit( DeclStmt * declStmt ) override final;
     119        virtual void visit( const DeclStmt * declStmt ) override final;
    89120        virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
     121        virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
    90122
    91123        virtual void visit( ApplicationExpr * applicationExpr ) override final;
     124        virtual void visit( const ApplicationExpr * applicationExpr ) override final;
    92125        virtual void visit( UntypedExpr * untypedExpr ) override final;
     126        virtual void visit( const UntypedExpr * untypedExpr ) override final;
    93127        virtual void visit( NameExpr * nameExpr ) override final;
     128        virtual void visit( const NameExpr * nameExpr ) override final;
    94129        virtual void visit( CastExpr * castExpr ) override final;
     130        virtual void visit( const CastExpr * castExpr ) override final;
    95131        virtual void visit( KeywordCastExpr * castExpr ) override final;
     132        virtual void visit( const KeywordCastExpr * castExpr ) override final;
    96133        virtual void visit( VirtualCastExpr * castExpr ) override final;
     134        virtual void visit( const VirtualCastExpr * castExpr ) override final;
    97135        virtual void visit( AddressExpr * addressExpr ) override final;
     136        virtual void visit( const AddressExpr * addressExpr ) override final;
    98137        virtual void visit( LabelAddressExpr * labAddressExpr ) override final;
     138        virtual void visit( const LabelAddressExpr * labAddressExpr ) override final;
    99139        virtual void visit( UntypedMemberExpr * memberExpr ) override final;
     140        virtual void visit( const UntypedMemberExpr * memberExpr ) override final;
    100141        virtual void visit( MemberExpr * memberExpr ) override final;
     142        virtual void visit( const MemberExpr * memberExpr ) override final;
    101143        virtual void visit( VariableExpr * variableExpr ) override final;
     144        virtual void visit( const VariableExpr * variableExpr ) override final;
    102145        virtual void visit( ConstantExpr * constantExpr ) override final;
     146        virtual void visit( const ConstantExpr * constantExpr ) override final;
    103147        virtual void visit( SizeofExpr * sizeofExpr ) override final;
     148        virtual void visit( const SizeofExpr * sizeofExpr ) override final;
    104149        virtual void visit( AlignofExpr * alignofExpr ) override final;
     150        virtual void visit( const AlignofExpr * alignofExpr ) override final;
    105151        virtual void visit( UntypedOffsetofExpr * offsetofExpr ) override final;
     152        virtual void visit( const UntypedOffsetofExpr * offsetofExpr ) override final;
    106153        virtual void visit( OffsetofExpr * offsetofExpr ) override final;
     154        virtual void visit( const OffsetofExpr * offsetofExpr ) override final;
    107155        virtual void visit( OffsetPackExpr * offsetPackExpr ) override final;
    108         virtual void visit( AttrExpr * attrExpr ) override final;
     156        virtual void visit( const OffsetPackExpr * offsetPackExpr ) override final;
    109157        virtual void visit( LogicalExpr * logicalExpr ) override final;
     158        virtual void visit( const LogicalExpr * logicalExpr ) override final;
    110159        virtual void visit( ConditionalExpr * conditionalExpr ) override final;
     160        virtual void visit( const ConditionalExpr * conditionalExpr ) override final;
    111161        virtual void visit( CommaExpr * commaExpr ) override final;
     162        virtual void visit( const CommaExpr * commaExpr ) override final;
    112163        virtual void visit( TypeExpr * typeExpr ) override final;
     164        virtual void visit( const TypeExpr * typeExpr ) override final;
    113165        virtual void visit( AsmExpr * asmExpr ) override final;
     166        virtual void visit( const AsmExpr * asmExpr ) override final;
    114167        virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
     168        virtual void visit( const ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
    115169        virtual void visit( ConstructorExpr *  ctorExpr ) override final;
     170        virtual void visit( const ConstructorExpr *  ctorExpr ) override final;
    116171        virtual void visit( CompoundLiteralExpr * compLitExpr ) override final;
     172        virtual void visit( const CompoundLiteralExpr * compLitExpr ) override final;
    117173        virtual void visit( RangeExpr * rangeExpr ) override final;
     174        virtual void visit( const RangeExpr * rangeExpr ) override final;
    118175        virtual void visit( UntypedTupleExpr * tupleExpr ) override final;
     176        virtual void visit( const UntypedTupleExpr * tupleExpr ) override final;
    119177        virtual void visit( TupleExpr * tupleExpr ) override final;
     178        virtual void visit( const TupleExpr * tupleExpr ) override final;
    120179        virtual void visit( TupleIndexExpr * tupleExpr ) override final;
     180        virtual void visit( const TupleIndexExpr * tupleExpr ) override final;
    121181        virtual void visit( TupleAssignExpr * assignExpr ) override final;
     182        virtual void visit( const TupleAssignExpr * assignExpr ) override final;
    122183        virtual void visit( StmtExpr *  stmtExpr ) override final;
     184        virtual void visit( const StmtExpr *  stmtExpr ) override final;
    123185        virtual void visit( UniqueExpr *  uniqueExpr ) override final;
     186        virtual void visit( const UniqueExpr *  uniqueExpr ) override final;
    124187        virtual void visit( UntypedInitExpr *  initExpr ) override final;
     188        virtual void visit( const UntypedInitExpr *  initExpr ) override final;
    125189        virtual void visit( InitExpr *  initExpr ) override final;
     190        virtual void visit( const InitExpr *  initExpr ) override final;
    126191        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;
    127195        virtual void visit( GenericExpr * genExpr ) override final;
     196        virtual void visit( const GenericExpr * genExpr ) override final;
    128197
    129198        virtual void visit( VoidType * basicType ) override final;
     199        virtual void visit( const VoidType * basicType ) override final;
    130200        virtual void visit( BasicType * basicType ) override final;
     201        virtual void visit( const BasicType * basicType ) override final;
    131202        virtual void visit( PointerType * pointerType ) override final;
     203        virtual void visit( const PointerType * pointerType ) override final;
    132204        virtual void visit( ArrayType * arrayType ) override final;
     205        virtual void visit( const ArrayType * arrayType ) override final;
    133206        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;
    134210        virtual void visit( FunctionType * functionType ) override final;
     211        virtual void visit( const FunctionType * functionType ) override final;
    135212        virtual void visit( StructInstType * aggregateUseType ) override final;
     213        virtual void visit( const StructInstType * aggregateUseType ) override final;
    136214        virtual void visit( UnionInstType * aggregateUseType ) override final;
     215        virtual void visit( const UnionInstType * aggregateUseType ) override final;
    137216        virtual void visit( EnumInstType * aggregateUseType ) override final;
     217        virtual void visit( const EnumInstType * aggregateUseType ) override final;
    138218        virtual void visit( TraitInstType * aggregateUseType ) override final;
     219        virtual void visit( const TraitInstType * aggregateUseType ) override final;
    139220        virtual void visit( TypeInstType * aggregateUseType ) override final;
     221        virtual void visit( const TypeInstType * aggregateUseType ) override final;
    140222        virtual void visit( TupleType * tupleType ) override final;
     223        virtual void visit( const TupleType * tupleType ) override final;
    141224        virtual void visit( TypeofType * typeofType ) override final;
     225        virtual void visit( const TypeofType * typeofType ) override final;
    142226        virtual void visit( AttrType * attrType ) override final;
     227        virtual void visit( const AttrType * attrType ) override final;
    143228        virtual void visit( VarArgsType * varArgsType ) override final;
     229        virtual void visit( const VarArgsType * varArgsType ) override final;
    144230        virtual void visit( ZeroType * zeroType ) override final;
     231        virtual void visit( const ZeroType * zeroType ) override final;
    145232        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;
    146236
    147237        virtual void visit( Designation * designation ) override final;
     238        virtual void visit( const Designation * designation ) override final;
    148239        virtual void visit( SingleInit * singleInit ) override final;
     240        virtual void visit( const SingleInit * singleInit ) override final;
    149241        virtual void visit( ListInit * listInit ) override final;
     242        virtual void visit( const ListInit * listInit ) override final;
    150243        virtual void visit( ConstructorInit * ctorInit ) override final;
    151 
    152         virtual void visit( Subrange * subrange ) override final;
     244        virtual void visit( const ConstructorInit * ctorInit ) override final;
    153245
    154246        virtual void visit( Constant * constant ) override final;
     247        virtual void visit( const Constant * constant ) override final;
    155248
    156249        virtual void visit( Attribute * attribute ) override final;
     250        virtual void visit( const Attribute * attribute ) override final;
    157251
    158252        virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override final;
     
    183277        virtual Statement * mutate( FinallyStmt * finallyStmt ) override final;
    184278        virtual Statement * mutate( WaitForStmt * waitforStmt ) override final;
    185         virtual Statement * mutate( WithStmt * withStmt ) override final;
     279        virtual Declaration * mutate( WithStmt * withStmt ) override final;
    186280        virtual NullStmt * mutate( NullStmt * nullStmt ) override final;
    187281        virtual Statement * mutate( DeclStmt * declStmt ) override final;
     
    205299        virtual Expression * mutate( OffsetofExpr * offsetofExpr ) override final;
    206300        virtual Expression * mutate( OffsetPackExpr * offsetPackExpr ) override final;
    207         virtual Expression * mutate( AttrExpr * attrExpr ) override final;
    208301        virtual Expression * mutate( LogicalExpr * logicalExpr ) override final;
    209302        virtual Expression * mutate( ConditionalExpr * conditionalExpr ) override final;
     
    224317        virtual Expression * mutate( InitExpr *  initExpr ) override final;
    225318        virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
     319        virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
    226320        virtual Expression * mutate( GenericExpr * genExpr ) override final;
    227321
     
    231325        virtual Type * mutate( ArrayType * arrayType ) override final;
    232326        virtual Type * mutate( ReferenceType * referenceType ) override final;
     327        virtual Type * mutate( QualifiedType * qualType ) override final;
    233328        virtual Type * mutate( FunctionType * functionType ) override final;
    234329        virtual Type * mutate( StructInstType * aggregateUseType ) override final;
     
    243338        virtual Type * mutate( ZeroType * zeroType ) override final;
    244339        virtual Type * mutate( OneType * oneType ) override final;
     340        virtual Type * mutate( GlobalScopeType * globalType ) override final;
    245341
    246342        virtual Designation * mutate( Designation * designation ) override final;
     
    249345        virtual Initializer * mutate( ConstructorInit * ctorInit ) override final;
    250346
    251         virtual Subrange * mutate( Subrange * subrange ) override final;
    252 
    253347        virtual Constant * mutate( Constant * constant ) override final;
    254348
     
    258352
    259353private:
     354        bool inFunction = false;
     355
    260356        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 );
    261358        template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
    262359        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 );
    263361        template< typename TreeType, typename pass_t > friend void maybeMutate_impl( TreeType *& tree, PassVisitor< pass_t > & mutator );
    264362        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 );
    265364        template< typename Container, typename pass_t > friend void maybeMutate_impl( Container & container, PassVisitor< pass_t > & mutator );
    266365
    267366        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 ); }
    268368        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 ); }
    269370
    270371        template<typename node_type> void call_premutate ( node_type * node ) { premutate_impl( pass, node, 0 ); }
     
    280381        void visitStatementList ( std::list< Statement* > &statements );
    281382        void mutateStatementList( std::list< Statement* > &statements );
     383        void visitStatementList ( const std::list< Statement * > & statements );
    282384
    283385        template< typename func_t >
     
    285387        Statement * visitStatement ( Statement * stmt );
    286388        Statement * mutateStatement( Statement * stmt );
     389        void visitStatement ( const Statement * stmt );
    287390
    288391        template< typename func_t >
     
    290393        Expression * visitExpression ( Expression * expr );
    291394        Expression * mutateExpression( Expression * expr );
    292 
    293 
    294         TypeSubstitution **             get_env_ptr    () { return env_impl             ( pass, 0); }
     395        void visitExpression ( const Expression * expr );
     396
     397
     398        auto                                    get_env_ptr    () -> decltype(env_impl( pass, 0)) { return env_impl( pass, 0); }
    295399        std::list< Statement* > *       get_beforeStmts() { return stmtsToAddBefore_impl( pass, 0); }
    296400        std::list< Statement* > *       get_afterStmts () { return stmtsToAddAfter_impl ( pass, 0); }
     
    303407        void indexerScopeEnter  ()                                    { indexer_impl_enterScope  ( pass, 0       ); }
    304408        void indexerScopeLeave  ()                                    { indexer_impl_leaveScope  ( pass, 0       ); }
    305         void indexerAddId       ( DeclarationWithType      * node  ) { indexer_impl_addId       ( pass, 0, node ); }
    306         void indexerAddType     ( NamedTypeDecl             * node  ) { indexer_impl_addType     ( pass, 0, node ); }
     409        void indexerAddId       ( const DeclarationWithType * node  ) { indexer_impl_addId       ( pass, 0, node ); }
     410        void indexerAddType     ( const NamedTypeDecl       * node  ) { indexer_impl_addType     ( pass, 0, node ); }
    307411        void indexerAddStruct   ( const std::string         & id    ) { indexer_impl_addStruct   ( pass, 0, id   ); }
    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 ); }
     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 ); }
    311415        void indexerAddUnion    ( const std::string         & id    ) { indexer_impl_addUnion    ( pass, 0, id   ); }
    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 ); }
     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 ); }
    316420
    317421
    318422        template< typename TreeType, typename VisitorType >
    319         friend inline void indexerScopedAccept( TreeType * tree, VisitorType &visitor );
     423        friend inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor );
    320424
    321425        template< typename TreeType, typename VisitorType >
    322         friend inline void indexerScopedMutate( TreeType *& tree, VisitorType &visitor );
     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 );
    323430};
    324431
     
    337444public:
    338445        TypeSubstitution * env = nullptr;
     446};
     447
     448class WithConstTypeSubstitution {
     449protected:
     450        WithConstTypeSubstitution() = default;
     451        ~WithConstTypeSubstitution() = default;
     452
     453public:
     454        const TypeSubstitution * env = nullptr;
    339455};
    340456
     
    418534};
    419535
     536#include "Common/Stats.h"
     537
     538extern 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
    420544#include "SynTree/TypeSubstitution.h"
    421545#include "PassVisitor.impl.h"
  • src/Common/PassVisitor.impl.h

    r7951100 rb067d9b  
    2020
    2121#define MUTATE_END( type, node )                \
    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 
     22        auto __return = call_postmutate< type * >( node ); \
     23        assert( __return ); \
     24        return __return;
    4025
    4126
     
    6752        SemanticErrorException errors;
    6853
     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);
    6957        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
     58
     59
    7060                // splice in new declarations after previous decl
    7161                if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
     
    8373                if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
    8474        }
     75        pass_visitor_stats.depth--;
     76        if ( ! errors.isEmpty() ) {
     77                throw errors;
     78        }
     79}
     80
     81template< typename pass_type >
     82inline 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--;
    8598        if ( ! errors.isEmpty() ) {
    8699                throw errors;
     
    94107        SemanticErrorException errors;
    95108
     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);
    96112        for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
    97113                // splice in new declarations after previous decl
     
    109125                if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
    110126        }
     127        pass_visitor_stats.depth--;
    111128        if ( ! errors.isEmpty() ) {
    112129                throw errors;
     
    122139}
    123140
     141template< typename TreeType, typename pass_type >
     142inline 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
    124149template< typename Container, typename pass_type >
    125150inline void maybeAccept_impl( Container & container, PassVisitor< pass_type > & visitor ) {
    126151        if ( ! visitor.get_visit_children() ) return;
    127152        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);
    128157        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    129158                try {
     
    135164                }
    136165        }
     166        pass_visitor_stats.depth--;
     167        if ( ! errors.isEmpty() ) {
     168                throw errors;
     169        }
     170}
     171
     172template< typename Container, typename pass_type >
     173inline 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--;
    137190        if ( ! errors.isEmpty() ) {
    138191                throw errors;
     
    151204template< typename Container, typename pass_type >
    152205inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
     206
    153207        if ( ! mutator.get_visit_children() ) return;
    154208        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);
    155213        for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    156214                try {
     
    163221                } // try
    164222        } // for
     223        pass_visitor_stats.depth--;
    165224        if ( ! errors.isEmpty() ) {
    166225                throw errors;
     
    185244        DeclList_t* afterDecls  = get_afterDecls();
    186245
     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);
    187249        for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
    188250
     
    192254                try {
    193255                        func( *i );
     256                        assert( *i );
    194257                        assert(( empty( beforeStmts ) && empty( afterStmts ))
    195258                            || ( empty( beforeDecls ) && empty( afterDecls )) );
     
    202265                if ( !empty( beforeStmts ) ) { statements.splice( i, *beforeStmts ); }
    203266        }
     267        pass_visitor_stats.depth--;
    204268
    205269        if ( !empty( afterDecls ) ) { splice( std::back_inserter( statements ), afterDecls); }
     
    216280
    217281template< typename pass_type >
     282void 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
     300template< typename pass_type >
    218301void PassVisitor< pass_type >::mutateStatementList( std::list< Statement * > & statements ) {
    219302        handleStatementList( statements, [this]( Statement *& stmt) {
     
    229312
    230313        // don't want statements from outer CompoundStmts to be added to this CompoundStmt
    231         ValueGuardPtr< TypeSubstitution * >  oldEnv        ( get_env_ptr    () );
     314        ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    232315        ValueGuardPtr< DeclList_t >          oldBeforeDecls( get_beforeDecls() );
    233316        ValueGuardPtr< DeclList_t >          oldAfterDecls ( get_afterDecls () );
     
    264347
    265348template< typename pass_type >
     349void 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
     358template< typename pass_type >
    266359Statement * PassVisitor< pass_type >::mutateStatement( Statement * stmt ) {
    267360        return handleStatement( stmt, [this]( Statement * stmt ) {
     
    295388
    296389template< typename pass_type >
     390void 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
     402template< typename pass_type >
    297403Expression * PassVisitor< pass_type >::mutateExpression( Expression * expr ) {
    298404        return handleExpression(expr, [this]( Expression * expr ) {
     
    304410template< typename TreeType, typename VisitorType >
    305411inline 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
     420template< typename TreeType, typename VisitorType >
     421inline void indexerScopedAccept( const TreeType * tree, VisitorType & visitor ) {
    306422        if ( ! visitor.get_visit_children() ) return;
    307423        auto guard = makeFuncGuard(
     
    366482
    367483template< typename pass_type >
     484void 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
     495template< typename pass_type >
    368496DeclarationWithType * PassVisitor< pass_type >::mutate( ObjectDecl * node ) {
    369497        MUTATE_START( node );
     
    404532                        indexerAddId( &func );
    405533                        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
     546template< typename pass_type >
     547void 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;
    406573                        maybeAccept_impl( node->statements, *this );
    407574                        maybeAccept_impl( node->attributes, *this );
     
    434601                        indexerAddId( &func );
    435602                        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;
    436607                        maybeMutate_impl( node->statements, *this );
    437608                        maybeMutate_impl( node->attributes, *this );
     
    465636
    466637template< typename pass_type >
    467 Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
    468         MUTATE_START( node );
     638void PassVisitor< pass_type >::visit( const StructDecl * node ) {
     639        VISIT_START( node );
    469640
    470641        // make up a forward declaration and add it before processing the members
     
    474645        {
    475646                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     647                maybeAccept_impl( node->parameters, *this );
     648                maybeAccept_impl( node->members   , *this );
     649        }
     650
     651        // this addition replaces the forward declaration
     652        indexerAddStruct( node );
     653
     654        VISIT_END( node );
     655}
     656
     657template< typename pass_type >
     658Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
     659        MUTATE_START( node );
     660
     661        // 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 );
     664
     665        {
     666                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    476667                maybeMutate_impl( node->parameters, *this );
    477668                maybeMutate_impl( node->members   , *this );
     
    503694        VISIT_END( node );
    504695}
     696template< typename pass_type >
     697void 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}
    505713
    506714template< typename pass_type >
     
    538746
    539747template< typename pass_type >
     748void 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
     760template< typename pass_type >
    540761Declaration * PassVisitor< pass_type >::mutate( EnumDecl * node ) {
    541762        MUTATE_START( node );
     
    554775template< typename pass_type >
    555776void 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
     790template< typename pass_type >
     791void PassVisitor< pass_type >::visit( const TraitDecl * node ) {
    556792        VISIT_START( node );
    557793
     
    606842}
    607843
    608 template< typename pass_type >
    609 Declaration * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
    610         MUTATE_START( node );
     844
     845template< typename pass_type >
     846void PassVisitor< pass_type >::visit( const TypeDecl * node ) {
     847        VISIT_START( node );
    611848
    612849        {
    613850                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    614                 maybeMutate_impl( node->parameters, *this );
    615                 maybeMutate_impl( node->base      , *this );
     851                maybeAccept_impl( node->parameters, *this );
     852                maybeAccept_impl( node->base      , *this );
    616853        }
    617854
     
    621858        indexerAddType( node );
    622859
     860        maybeAccept_impl( node->assertions, *this );
     861
     862        indexerScopedAccept( node->init, *this );
     863
     864        VISIT_END( node );
     865}
     866
     867template< typename pass_type >
     868Declaration * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
     869        MUTATE_START( node );
     870
     871        {
     872                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     873                maybeMutate_impl( node->parameters, *this );
     874                maybeMutate_impl( node->base      , *this );
     875        }
     876
     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
     880        indexerAddType( node );
     881
    623882        maybeMutate_impl( node->assertions, *this );
    624883
     
    648907
    649908template< typename pass_type >
     909void 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
     925template< typename pass_type >
    650926Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
    651927        MUTATE_START( node );
     
    676952
    677953template< typename pass_type >
     954void PassVisitor< pass_type >::visit( const AsmDecl * node ) {
     955        VISIT_START( node );
     956
     957        maybeAccept_impl( node->stmt, *this );
     958
     959        VISIT_END( node );
     960}
     961
     962template< typename pass_type >
    678963AsmDecl * PassVisitor< pass_type >::mutate( AsmDecl * node ) {
    679964        MUTATE_START( node );
     
    697982
    698983template< typename pass_type >
     984void 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
     993template< typename pass_type >
    699994StaticAssertDecl * PassVisitor< pass_type >::mutate( StaticAssertDecl * node ) {
    700995        MUTATE_START( node );
     
    7121007        VISIT_START( node );
    7131008        {
    714                 auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     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(); } );
    7151012                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
     1013                inFunction = false;
    7161014                visitStatementList( node->kids );
    7171015        }
     
    7201018
    7211019template< typename pass_type >
     1020void 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(); } );
     1026                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
     1027                inFunction = false;
     1028                visitStatementList( node->kids );
     1029        }
     1030        VISIT_END( node );
     1031}
     1032
     1033template< typename pass_type >
    7221034CompoundStmt * PassVisitor< pass_type >::mutate( CompoundStmt * node ) {
    7231035        MUTATE_START( node );
    7241036        {
    725                 auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     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(); } );
    7261040                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
     1041                inFunction = false;
    7271042                mutateStatementList( node->kids );
    7281043        }
     
    7341049template< typename pass_type >
    7351050void PassVisitor< pass_type >::visit( ExprStmt * node ) {
     1051        VISIT_START( node );
     1052
     1053        visitExpression( node->expr );
     1054
     1055        VISIT_END( node );
     1056}
     1057
     1058template< typename pass_type >
     1059void PassVisitor< pass_type >::visit( const ExprStmt * node ) {
    7361060        VISIT_START( node );
    7371061
     
    7651089
    7661090template< typename pass_type >
     1091void 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
     1102template< typename pass_type >
    7671103Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
    7681104        MUTATE_START( node );
     
    7861122
    7871123template< typename pass_type >
     1124void PassVisitor< pass_type >::visit( const DirectiveStmt * node ) {
     1125        VISIT_START( node )
     1126
     1127        VISIT_END( node );
     1128}
     1129
     1130template< typename pass_type >
    7881131Statement * PassVisitor< pass_type >::mutate( DirectiveStmt * node ) {
    7891132        MUTATE_START( node );
     
    8001143                // if statements introduce a level of scope (for the initialization)
    8011144                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    802                 maybeAccept_impl( node->get_initialization(), *this );
     1145                maybeAccept_impl( node->initialization, *this );
    8031146                visitExpression ( node->condition );
    8041147                node->thenPart = visitStatement( node->thenPart );
     
    8091152
    8101153template< typename pass_type >
    811 Statement * PassVisitor< pass_type >::mutate( IfStmt * node ) {
    812         MUTATE_START( node );
     1154void PassVisitor< pass_type >::visit( const IfStmt * node ) {
     1155        VISIT_START( node );
    8131156        {
    8141157                // if statements introduce a level of scope (for the initialization)
    8151158                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    816                 maybeMutate_impl( node->get_initialization(), *this );
     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
     1167template< typename pass_type >
     1168Statement * 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 );
    8171174                node->condition = mutateExpression( node->condition );
    8181175                node->thenPart  = mutateStatement ( node->thenPart  );
     
    8341191                visitExpression ( node->condition );
    8351192                node->body = visitStatement( node->body );
     1193        }
     1194
     1195        VISIT_END( node );
     1196}
     1197
     1198template< typename pass_type >
     1199void 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 );
    8361208        }
    8371209
     
    8721244
    8731245template< typename pass_type >
     1246void 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
     1259template< typename pass_type >
    8741260Statement * PassVisitor< pass_type >::mutate( ForStmt * node ) {
    8751261        MUTATE_START( node );
     
    8981284
    8991285template< typename pass_type >
     1286void 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
     1295template< typename pass_type >
    9001296Statement * PassVisitor< pass_type >::mutate( SwitchStmt * node ) {
    9011297        MUTATE_START( node );
     
    9201316
    9211317template< typename pass_type >
     1318void 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
     1327template< typename pass_type >
    9221328Statement * PassVisitor< pass_type >::mutate( CaseStmt * node ) {
    9231329        MUTATE_START( node );
     
    9381344
    9391345template< typename pass_type >
     1346void PassVisitor< pass_type >::visit( const BranchStmt * node ) {
     1347        VISIT_START( node );
     1348        VISIT_END( node );
     1349}
     1350
     1351template< typename pass_type >
    9401352Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
    9411353        MUTATE_START( node );
     
    9551367
    9561368template< typename pass_type >
     1369void PassVisitor< pass_type >::visit( const ReturnStmt * node ) {
     1370        VISIT_START( node );
     1371
     1372        visitExpression( node->expr );
     1373
     1374        VISIT_END( node );
     1375}
     1376
     1377template< typename pass_type >
    9571378Statement * PassVisitor< pass_type >::mutate( ReturnStmt * node ) {
    9581379        MUTATE_START( node );
     
    9651386//--------------------------------------------------------------------------
    9661387// ThrowStmt
    967 
    9681388template< typename pass_type >
    9691389void PassVisitor< pass_type >::visit( ThrowStmt * node ) {
     
    9771397
    9781398template< typename pass_type >
     1399void 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
     1408template< typename pass_type >
    9791409Statement * PassVisitor< pass_type >::mutate( ThrowStmt * node ) {
    9801410        MUTATE_START( node );
     
    9901420template< typename pass_type >
    9911421void 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
     1431template< typename pass_type >
     1432void PassVisitor< pass_type >::visit( const TryStmt * node ) {
    9921433        VISIT_START( node );
    9931434
     
    10261467
    10271468template< typename pass_type >
     1469void 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
     1481template< typename pass_type >
    10281482Statement * PassVisitor< pass_type >::mutate( CatchStmt * node ) {
    10291483        MUTATE_START( node );
     
    10501504
    10511505template< typename pass_type >
     1506void 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
     1514template< typename pass_type >
    10521515Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
    10531516        MUTATE_START( node );
     
    10821545
    10831546template< typename pass_type >
     1547void 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
     1567template< typename pass_type >
    10841568Statement * PassVisitor< pass_type >::mutate( WaitForStmt * node ) {
    10851569        MUTATE_START( node );
     
    11051589
    11061590//--------------------------------------------------------------------------
    1107 // NullStmt
     1591// WithStmt
    11081592template< typename pass_type >
    11091593void PassVisitor< pass_type >::visit( WithStmt * node ) {
     
    11201604
    11211605template< typename pass_type >
    1122 Statement * PassVisitor< pass_type >::mutate( WithStmt * node ) {
     1606void 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
     1618template< typename pass_type >
     1619Declaration * PassVisitor< pass_type >::mutate( WithStmt * node ) {
    11231620        MUTATE_START( node );
    11241621        maybeMutate_impl( node->exprs, *this );
     
    11291626                maybeMutate_impl( node->stmt, *this );
    11301627        }
     1628        MUTATE_END( Declaration, node );
     1629}
     1630
     1631//--------------------------------------------------------------------------
     1632// NullStmt
     1633template< typename pass_type >
     1634void PassVisitor< pass_type >::visit( NullStmt * node ) {
     1635        VISIT_START( node );
     1636        VISIT_END( node );
     1637}
     1638
     1639template< typename pass_type >
     1640void PassVisitor< pass_type >::visit( const NullStmt * node ) {
     1641        VISIT_START( node );
     1642        VISIT_END( node );
     1643}
     1644
     1645template< typename pass_type >
     1646NullStmt * PassVisitor< pass_type >::mutate( NullStmt * node ) {
     1647        MUTATE_START( node );
     1648        MUTATE_END( NullStmt, node );
     1649}
     1650
     1651//--------------------------------------------------------------------------
     1652// DeclStmt
     1653template< typename pass_type >
     1654void PassVisitor< pass_type >::visit( DeclStmt * node ) {
     1655        VISIT_START( node );
     1656
     1657        maybeAccept_impl( node->decl, *this );
     1658
     1659        VISIT_END( node );
     1660}
     1661
     1662template< typename pass_type >
     1663void 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
     1671template< typename pass_type >
     1672Statement * PassVisitor< pass_type >::mutate( DeclStmt * node ) {
     1673        MUTATE_START( node );
     1674
     1675        maybeMutate_impl( node->decl, *this );
     1676
    11311677        MUTATE_END( Statement, node );
    11321678}
    11331679
    11341680//--------------------------------------------------------------------------
    1135 // NullStmt
    1136 template< typename pass_type >
    1137 void PassVisitor< pass_type >::visit( NullStmt * node ) {
    1138         VISIT_START( node );
    1139         VISIT_END( node );
    1140 }
    1141 
    1142 template< typename pass_type >
    1143 NullStmt * PassVisitor< pass_type >::mutate( NullStmt * node ) {
    1144         MUTATE_START( node );
    1145         MUTATE_END( NullStmt, node );
    1146 }
    1147 
    1148 //--------------------------------------------------------------------------
    1149 // DeclStmt
    1150 template< typename pass_type >
    1151 void PassVisitor< pass_type >::visit( DeclStmt * node ) {
    1152         VISIT_START( node );
    1153 
    1154         maybeAccept_impl( node->decl, *this );
    1155 
    1156         VISIT_END( node );
    1157 }
    1158 
    1159 template< typename pass_type >
    1160 Statement * PassVisitor< pass_type >::mutate( DeclStmt * node ) {
    1161         MUTATE_START( node );
    1162 
    1163         maybeMutate_impl( node->decl, *this );
     1681// ImplicitCtorDtorStmt
     1682template< typename pass_type >
     1683void PassVisitor< pass_type >::visit( ImplicitCtorDtorStmt * node ) {
     1684        VISIT_START( node );
     1685
     1686        maybeAccept_impl( node->callStmt, *this );
     1687
     1688        VISIT_END( node );
     1689}
     1690
     1691template< typename pass_type >
     1692void 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
     1700template< typename pass_type >
     1701Statement * PassVisitor< pass_type >::mutate( ImplicitCtorDtorStmt * node ) {
     1702        MUTATE_START( node );
     1703
     1704        maybeMutate_impl( node->callStmt, *this );
    11641705
    11651706        MUTATE_END( Statement, node );
     
    11671708
    11681709//--------------------------------------------------------------------------
    1169 // ImplicitCtorDtorStmt
    1170 template< typename pass_type >
    1171 void PassVisitor< pass_type >::visit( ImplicitCtorDtorStmt * node ) {
    1172         VISIT_START( node );
    1173 
    1174         maybeAccept_impl( node->callStmt, *this );
    1175 
    1176         VISIT_END( node );
    1177 }
    1178 
    1179 template< typename pass_type >
    1180 Statement * PassVisitor< pass_type >::mutate( ImplicitCtorDtorStmt * node ) {
    1181         MUTATE_START( node );
    1182 
    1183         maybeMutate_impl( node->callStmt, *this );
    1184 
    1185         MUTATE_END( Statement, node );
    1186 }
    1187 
    1188 //--------------------------------------------------------------------------
    11891710// ApplicationExpr
    11901711template< typename pass_type >
     
    11931714
    11941715        indexerScopedAccept( node->result  , *this );
    1195         maybeAccept_impl        ( node->function, *this );
    1196         maybeAccept_impl        ( node->args    , *this );
     1716        maybeAccept_impl   ( node->function, *this );
     1717        maybeAccept_impl   ( node->args    , *this );
     1718
     1719        VISIT_END( node );
     1720}
     1721
     1722template< typename pass_type >
     1723void 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 );
    11971729
    11981730        VISIT_END( node );
     
    12281760
    12291761template< typename pass_type >
     1762void 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
     1774template< typename pass_type >
    12301775Expression * PassVisitor< pass_type >::mutate( UntypedExpr * node ) {
    12311776        MUTATE_START( node );
     
    12531798
    12541799template< typename pass_type >
     1800void PassVisitor< pass_type >::visit( const NameExpr * node ) {
     1801        VISIT_START( node );
     1802
     1803        indexerScopedAccept( node->result, *this );
     1804
     1805        VISIT_END( node );
     1806}
     1807
     1808template< typename pass_type >
    12551809Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
    12561810        MUTATE_START( node );
     
    12691823
    12701824        indexerScopedAccept( node->result, *this );
    1271         maybeAccept_impl        ( node->arg   , *this );
     1825        maybeAccept_impl   ( node->arg   , *this );
     1826
     1827        VISIT_END( node );
     1828}
     1829
     1830template< typename pass_type >
     1831void PassVisitor< pass_type >::visit( const CastExpr * node ) {
     1832        VISIT_START( node );
     1833
     1834        indexerScopedAccept( node->result, *this );
     1835        maybeAccept_impl   ( node->arg   , *this );
    12721836
    12731837        VISIT_END( node );
     
    12981862
    12991863template< typename pass_type >
     1864void 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
     1873template< typename pass_type >
    13001874Expression * PassVisitor< pass_type >::mutate( KeywordCastExpr * node ) {
    13011875        MUTATE_START( node );
     
    13151889
    13161890        indexerScopedAccept( node->result, *this );
    1317         maybeAccept_impl( node->arg, *this );
     1891        maybeAccept_impl   ( node->arg, *this );
     1892
     1893        VISIT_END( node );
     1894}
     1895
     1896template< typename pass_type >
     1897void PassVisitor< pass_type >::visit( const VirtualCastExpr * node ) {
     1898        VISIT_START( node );
     1899
     1900        indexerScopedAccept( node->result, *this );
     1901        maybeAccept_impl   ( node->arg, *this );
    13181902
    13191903        VISIT_END( node );
     
    13441928
    13451929template< typename pass_type >
     1930void 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
     1939template< typename pass_type >
    13461940Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
    13471941        MUTATE_START( node );
     
    13661960
    13671961template< typename pass_type >
     1962void PassVisitor< pass_type >::visit( const LabelAddressExpr * node ) {
     1963        VISIT_START( node );
     1964
     1965        indexerScopedAccept( node->result, *this );
     1966
     1967        VISIT_END( node );
     1968}
     1969
     1970template< typename pass_type >
    13681971Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
    13691972        MUTATE_START( node );
     
    13791982template< typename pass_type >
    13801983void 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
     1993template< typename pass_type >
     1994void PassVisitor< pass_type >::visit( const UntypedMemberExpr * node ) {
    13811995        VISIT_START( node );
    13821996
     
    14132027
    14142028template< typename pass_type >
     2029void 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
     2038template< typename pass_type >
    14152039Expression * PassVisitor< pass_type >::mutate( MemberExpr * node ) {
    14162040        MUTATE_START( node );
     
    14352059
    14362060template< typename pass_type >
     2061void PassVisitor< pass_type >::visit( const VariableExpr * node ) {
     2062        VISIT_START( node );
     2063
     2064        indexerScopedAccept( node->result, *this );
     2065
     2066        VISIT_END( node );
     2067}
     2068
     2069template< typename pass_type >
    14372070Expression * PassVisitor< pass_type >::mutate( VariableExpr * node ) {
    14382071        MUTATE_START( node );
     
    14482081template< typename pass_type >
    14492082void 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
     2091template< typename pass_type >
     2092void PassVisitor< pass_type >::visit( const ConstantExpr * node ) {
    14502093        VISIT_START( node );
    14512094
     
    14732116template< typename pass_type >
    14742117void PassVisitor< pass_type >::visit( SizeofExpr * node ) {
     2118        VISIT_START( node );
     2119
     2120        indexerScopedAccept( node->result, *this );
     2121        if ( node->get_isType() ) {
     2122                maybeAccept_impl( node->type, *this );
     2123        } else {
     2124                maybeAccept_impl( node->expr, *this );
     2125        }
     2126
     2127        VISIT_END( node );
     2128}
     2129
     2130template< typename pass_type >
     2131void PassVisitor< pass_type >::visit( const SizeofExpr * node ) {
    14752132        VISIT_START( node );
    14762133
     
    15172174
    15182175template< typename pass_type >
     2176void 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
     2189template< typename pass_type >
    15192190Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
    15202191        MUTATE_START( node );
     
    15442215
    15452216template< typename pass_type >
     2217void 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
     2226template< typename pass_type >
    15462227Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
    15472228        MUTATE_START( node );
     
    15672248
    15682249template< typename pass_type >
     2250void 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
     2259template< typename pass_type >
    15692260Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
    15702261        MUTATE_START( node );
     
    15902281
    15912282template< typename pass_type >
     2283void 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
     2292template< typename pass_type >
    15922293Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
    15932294        MUTATE_START( node );
     
    16012302
    16022303//--------------------------------------------------------------------------
    1603 // AttrExpr
    1604 template< typename pass_type >
    1605 void PassVisitor< pass_type >::visit( AttrExpr * node ) {
    1606         VISIT_START( node );
    1607 
    1608         indexerScopedAccept( node->result, *this );
    1609         if ( node->get_isType() ) {
    1610                 maybeAccept_impl( node->type, *this );
    1611         } else {
    1612                 maybeAccept_impl( node->expr, *this );
    1613         }
    1614 
    1615         VISIT_END( node );
    1616 }
    1617 
    1618 template< typename pass_type >
    1619 Expression * PassVisitor< pass_type >::mutate( AttrExpr * node ) {
    1620         MUTATE_START( node );
    1621 
    1622         indexerScopedMutate( node->env   , *this );
    1623         indexerScopedMutate( node->result, *this );
    1624         if ( node->get_isType() ) {
    1625                 maybeMutate_impl( node->type, *this );
    1626         } else {
    1627                 maybeMutate_impl( node->expr, *this );
    1628         }
    1629 
    1630         MUTATE_END( Expression, node );
    1631 }
    1632 
    1633 //--------------------------------------------------------------------------
    16342304// LogicalExpr
    16352305template< typename pass_type >
    16362306void 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
     2316template< typename pass_type >
     2317void PassVisitor< pass_type >::visit( const LogicalExpr * node ) {
    16372318        VISIT_START( node );
    16382319
     
    16662347        maybeAccept_impl        ( node->arg2  , *this );
    16672348        maybeAccept_impl        ( node->arg3  , *this );
     2349
     2350        VISIT_END( node );
     2351}
     2352
     2353template< typename pass_type >
     2354void PassVisitor< pass_type >::visit( const ConditionalExpr * node ) {
     2355        VISIT_START( node );
     2356
     2357        indexerScopedAccept( node->result, *this );
     2358        maybeAccept_impl   ( node->arg1  , *this );
     2359        maybeAccept_impl   ( node->arg2  , *this );
     2360        maybeAccept_impl   ( node->arg3  , *this );
    16682361
    16692362        VISIT_END( node );
     
    16972390
    16982391template< typename pass_type >
     2392void 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
     2402template< typename pass_type >
    16992403Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
    17002404        MUTATE_START( node );
     
    17212425
    17222426template< typename pass_type >
     2427void 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
     2436template< typename pass_type >
    17232437Expression * PassVisitor< pass_type >::mutate( TypeExpr * node ) {
    17242438        MUTATE_START( node );
     
    17352449template< typename pass_type >
    17362450void 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
     2461template< typename pass_type >
     2462void PassVisitor< pass_type >::visit( const AsmExpr * node ) {
    17372463        VISIT_START( node );
    17382464
     
    17642490        VISIT_START( node );
    17652491
    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 );
     2492        indexerScopedAccept( node->result    , *this );
     2493        maybeAccept_impl   ( node->callExpr  , *this );
     2494
     2495        VISIT_END( node );
     2496}
     2497
     2498template< typename pass_type >
     2499void PassVisitor< pass_type >::visit( const ImplicitCopyCtorExpr * node ) {
     2500        VISIT_START( node );
     2501
     2502        indexerScopedAccept( node->result    , *this );
     2503        maybeAccept_impl   ( node->callExpr  , *this );
    17712504
    17722505        VISIT_END( node );
     
    17772510        MUTATE_START( node );
    17782511
    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 );
     2512        indexerScopedMutate( node->env       , *this );
     2513        indexerScopedMutate( node->result    , *this );
     2514        maybeMutate_impl   ( node->callExpr  , *this );
    17852515
    17862516        MUTATE_END( Expression, node );
     
    17912521template< typename pass_type >
    17922522void 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
     2531template< typename pass_type >
     2532void PassVisitor< pass_type >::visit( const ConstructorExpr * node ) {
    17932533        VISIT_START( node );
    17942534
     
    18232563
    18242564template< typename pass_type >
     2565void 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
     2574template< typename pass_type >
    18252575Expression * PassVisitor< pass_type >::mutate( CompoundLiteralExpr * node ) {
    18262576        MUTATE_START( node );
     
    18372587template< typename pass_type >
    18382588void PassVisitor< pass_type >::visit( RangeExpr * node ) {
     2589        VISIT_START( node );
     2590
     2591        indexerScopedAccept( node->result, *this );
     2592        maybeAccept_impl   ( node->low   , *this );
     2593        maybeAccept_impl   ( node->high  , *this );
     2594
     2595        VISIT_END( node );
     2596}
     2597
     2598template< typename pass_type >
     2599void PassVisitor< pass_type >::visit( const RangeExpr * node ) {
    18392600        VISIT_START( node );
    18402601
     
    18712632
    18722633template< typename pass_type >
     2634void PassVisitor< pass_type >::visit( const UntypedTupleExpr * node ) {
     2635        VISIT_START( node );
     2636
     2637        indexerScopedAccept( node->result, *this );
     2638        maybeAccept_impl   ( node->exprs , *this );
     2639
     2640        VISIT_END( node );
     2641}
     2642
     2643template< typename pass_type >
    18732644Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
    18742645        MUTATE_START( node );
     
    18942665
    18952666template< typename pass_type >
     2667void 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
     2676template< typename pass_type >
    18962677Expression * PassVisitor< pass_type >::mutate( TupleExpr * node ) {
    18972678        MUTATE_START( node );
     
    19172698
    19182699template< typename pass_type >
     2700void 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
     2709template< typename pass_type >
    19192710Expression * PassVisitor< pass_type >::mutate( TupleIndexExpr * node ) {
    19202711        MUTATE_START( node );
     
    19402731
    19412732template< typename pass_type >
     2733void PassVisitor< pass_type >::visit( const TupleAssignExpr * node ) {
     2734        VISIT_START( node );
     2735
     2736        indexerScopedAccept( node->result  , *this );
     2737        maybeAccept_impl( node->stmtExpr, *this );
     2738
     2739        VISIT_END( node );
     2740}
     2741
     2742template< typename pass_type >
    19422743Expression * PassVisitor< pass_type >::mutate( TupleAssignExpr * node ) {
    19432744        MUTATE_START( node );
     
    19572758
    19582759        // don't want statements from outer CompoundStmts to be added to this StmtExpr
    1959         ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
     2760        ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    19602761        ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
    19612762        ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
     
    19702771
    19712772template< typename pass_type >
     2773void PassVisitor< pass_type >::visit( const StmtExpr * node ) {
     2774        VISIT_START( node );
     2775
     2776        // 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
     2789template< typename pass_type >
    19722790Expression * PassVisitor< pass_type >::mutate( StmtExpr * node ) {
    19732791        MUTATE_START( node );
    19742792
    19752793        // don't want statements from outer CompoundStmts to be added to this StmtExpr
    1976         ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
     2794        ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    19772795        ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
    19782796        ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
     
    19992817
    20002818template< typename pass_type >
     2819void 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
     2828template< typename pass_type >
    20012829Expression * PassVisitor< pass_type >::mutate( UniqueExpr * node ) {
    20022830        MUTATE_START( node );
     
    20132841template< typename pass_type >
    20142842void PassVisitor< pass_type >::visit( UntypedInitExpr * node ) {
     2843        VISIT_START( node );
     2844
     2845        indexerScopedAccept( node->result, *this );
     2846        maybeAccept_impl   ( node->expr  , *this );
     2847        // not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
     2848
     2849        VISIT_END( node );
     2850}
     2851
     2852template< typename pass_type >
     2853void PassVisitor< pass_type >::visit( const UntypedInitExpr * node ) {
    20152854        VISIT_START( node );
    20162855
     
    20482887
    20492888template< typename pass_type >
     2889void 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
     2899template< typename pass_type >
    20502900Expression * PassVisitor< pass_type >::mutate( InitExpr * node ) {
    20512901        MUTATE_START( node );
     
    20662916
    20672917        indexerScopedAccept( node->result, *this );
    2068         maybeAccept_impl( node->expr, *this );
     2918        maybeAccept_impl   ( node->expr, *this );
     2919        // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
     2920
     2921        VISIT_END( node );
     2922}
     2923
     2924template< typename pass_type >
     2925void PassVisitor< pass_type >::visit( const DeletedExpr * node ) {
     2926        VISIT_START( node );
     2927
     2928        indexerScopedAccept( node->result, *this );
     2929        maybeAccept_impl   ( node->expr, *this );
    20692930        // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
    20702931
     
    20842945
    20852946//--------------------------------------------------------------------------
     2947// DefaultArgExpr
     2948template< typename pass_type >
     2949void 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
     2958template< typename pass_type >
     2959void 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
     2968template< typename pass_type >
     2969Expression * PassVisitor< pass_type >::mutate( DefaultArgExpr * node ) {
     2970        MUTATE_START( node );
     2971
     2972        indexerScopedMutate( node->env, *this );
     2973        indexerScopedMutate( node->result, *this );
     2974        maybeMutate_impl( node->expr, *this );
     2975
     2976        MUTATE_END( Expression, node );
     2977}
     2978
     2979//--------------------------------------------------------------------------
    20862980// GenericExpr
    20872981template< typename pass_type >
     
    20922986        maybeAccept_impl( node->control, *this );
    20932987        for ( GenericExpr::Association & assoc : node->associations ) {
     2988                indexerScopedAccept( assoc.type, *this );
     2989                maybeAccept_impl( assoc.expr, *this );
     2990        }
     2991
     2992        VISIT_END( node );
     2993}
     2994
     2995template< typename pass_type >
     2996void 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 ) {
    20943002                indexerScopedAccept( assoc.type, *this );
    20953003                maybeAccept_impl( assoc.expr, *this );
     
    21263034
    21273035template< typename pass_type >
     3036void 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
     3044template< typename pass_type >
    21283045Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
    21293046        MUTATE_START( node );
     
    21383055template< typename pass_type >
    21393056void PassVisitor< pass_type >::visit( BasicType * node ) {
     3057        VISIT_START( node );
     3058
     3059        maybeAccept_impl( node->forall, *this );
     3060
     3061        VISIT_END( node );
     3062}
     3063
     3064template< typename pass_type >
     3065void PassVisitor< pass_type >::visit( const BasicType * node ) {
    21403066        VISIT_START( node );
    21413067
     
    21683094
    21693095template< typename pass_type >
     3096void 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
     3106template< typename pass_type >
    21703107Type * PassVisitor< pass_type >::mutate( PointerType * node ) {
    21713108        MUTATE_START( node );
     
    21923129
    21933130template< typename pass_type >
     3131void 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
     3141template< typename pass_type >
    21943142Type * PassVisitor< pass_type >::mutate( ArrayType * node ) {
    21953143        MUTATE_START( node );
     
    22153163
    22163164template< typename pass_type >
     3165void 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
     3174template< typename pass_type >
    22173175Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) {
    22183176        MUTATE_START( node );
     
    22203178        maybeMutate_impl( node->forall, *this );
    22213179        maybeMutate_impl( node->base, *this );
     3180
     3181        MUTATE_END( Type, node );
     3182}
     3183
     3184//--------------------------------------------------------------------------
     3185// QualifiedType
     3186template< typename pass_type >
     3187void 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
     3197template< typename pass_type >
     3198void 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
     3208template< typename pass_type >
     3209Type * 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 );
    22223215
    22233216        MUTATE_END( Type, node );
     
    22383231
    22393232template< typename pass_type >
     3233void 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
     3243template< typename pass_type >
    22403244Type * PassVisitor< pass_type >::mutate( FunctionType * node ) {
    22413245        MUTATE_START( node );
     
    22663270
    22673271template< typename pass_type >
     3272void PassVisitor< pass_type >::visit( const StructInstType * node ) {
     3273        VISIT_START( node );
     3274
     3275        indexerAddStruct( node->name );
     3276
     3277        {
     3278                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     3279                maybeAccept_impl( node->forall    , *this );
     3280                maybeAccept_impl( node->parameters, *this );
     3281        }
     3282
     3283        VISIT_END( node );
     3284}
     3285
     3286template< typename pass_type >
    22683287Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
    22693288        MUTATE_START( node );
     
    22983317
    22993318template< typename pass_type >
     3319void 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
     3333template< typename pass_type >
    23003334Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
    23013335        MUTATE_START( node );
     
    23253359
    23263360template< typename pass_type >
     3361void 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
     3370template< typename pass_type >
    23273371Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
    23283372        MUTATE_START( node );
     
    23473391
    23483392template< typename pass_type >
     3393void 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
     3402template< typename pass_type >
    23493403Type * PassVisitor< pass_type >::mutate( TraitInstType * node ) {
    23503404        MUTATE_START( node );
     
    23603414template< typename pass_type >
    23613415void 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
     3424template< typename pass_type >
     3425void PassVisitor< pass_type >::visit( const TypeInstType * node ) {
    23623426        VISIT_START( node );
    23633427
     
    23923456
    23933457template< typename pass_type >
     3458void 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
     3468template< typename pass_type >
    23943469Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
    23953470        MUTATE_START( node );
     
    24063481template< typename pass_type >
    24073482void 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
     3491template< typename pass_type >
     3492void PassVisitor< pass_type >::visit( const TypeofType * node ) {
    24083493        VISIT_START( node );
    24093494
     
    24423527
    24433528template< typename pass_type >
     3529void 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
     3543template< typename pass_type >
    24443544Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
    24453545        MUTATE_START( node );
     
    24683568
    24693569template< typename pass_type >
     3570void PassVisitor< pass_type >::visit( const VarArgsType * node ) {
     3571        VISIT_START( node );
     3572
     3573        maybeAccept_impl( node->forall, *this );
     3574
     3575        VISIT_END( node );
     3576}
     3577
     3578template< typename pass_type >
    24703579Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
    24713580        MUTATE_START( node );
     
    24883597
    24893598template< typename pass_type >
     3599void 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
     3607template< typename pass_type >
    24903608Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
    24913609        MUTATE_START( node );
     
    25083626
    25093627template< typename pass_type >
     3628void 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
     3636template< typename pass_type >
    25103637Type * PassVisitor< pass_type >::mutate( OneType * node ) {
    25113638        MUTATE_START( node );
     
    25173644
    25183645//--------------------------------------------------------------------------
     3646// GlobalScopeType
     3647template< typename pass_type >
     3648void PassVisitor< pass_type >::visit( GlobalScopeType * node ) {
     3649        VISIT_START( node );
     3650
     3651        maybeAccept_impl( node->forall, *this );
     3652
     3653        VISIT_END( node );
     3654}
     3655
     3656template< typename pass_type >
     3657void 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
     3665template< typename pass_type >
     3666Type * 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//--------------------------------------------------------------------------
    25193675// Designation
    25203676template< typename pass_type >
     
    25283684
    25293685template< typename pass_type >
     3686void 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
     3694template< typename pass_type >
    25303695Designation * PassVisitor< pass_type >::mutate( Designation * node ) {
    25313696        MUTATE_START( node );
     
    25483713
    25493714template< typename pass_type >
     3715void PassVisitor< pass_type >::visit( const SingleInit * node ) {
     3716        VISIT_START( node );
     3717
     3718        visitExpression( node->value );
     3719
     3720        VISIT_END( node );
     3721}
     3722
     3723template< typename pass_type >
    25503724Initializer * PassVisitor< pass_type >::mutate( SingleInit * node ) {
    25513725        MUTATE_START( node );
     
    25603734template< typename pass_type >
    25613735void 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
     3744template< typename pass_type >
     3745void PassVisitor< pass_type >::visit( const ListInit * node ) {
    25623746        VISIT_START( node );
    25633747
     
    25923776
    25933777template< typename pass_type >
     3778void 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
     3788template< typename pass_type >
    25943789Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
    25953790        MUTATE_START( node );
     
    26033798
    26043799//--------------------------------------------------------------------------
    2605 // Subrange
    2606 template< typename pass_type >
    2607 void PassVisitor< pass_type >::visit( Subrange * node ) {
    2608         VISIT_START( node );
    2609 
    2610         VISIT_END( node );
    2611 }
    2612 
    2613 template< typename pass_type >
    2614 Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
    2615         MUTATE_START( node );
    2616 
    2617         MUTATE_END( Subrange, node );
    2618 }
    2619 
    2620 //--------------------------------------------------------------------------
    26213800// Attribute
    26223801template< typename pass_type >
     
    26283807
    26293808template< typename pass_type >
     3809void PassVisitor< pass_type >::visit( const Constant * node ) {
     3810        VISIT_START( node );
     3811
     3812        VISIT_END( node );
     3813}
     3814
     3815template< typename pass_type >
    26303816Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
    26313817        MUTATE_START( node );
     
    26383824template< typename pass_type >
    26393825void PassVisitor< pass_type >::visit( Attribute * node ) {
     3826        VISIT_START( node );
     3827
     3828        maybeAccept_impl( node->parameters, *this );
     3829
     3830        VISIT_END( node );
     3831}
     3832
     3833template< typename pass_type >
     3834void PassVisitor< pass_type >::visit( const Attribute * node ) {
    26403835        VISIT_START( node );
    26413836
     
    26693864        MUTATE_END( TypeSubstitution, node );
    26703865}
     3866
     3867#undef VISIT_START
     3868#undef VISIT_END
     3869
     3870#undef MUTATE_START
     3871#undef MUTATE_END
  • src/Common/PassVisitor.proto.h

    r7951100 rb067d9b  
    118118static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
    119119
     120template<typename pass_type, typename node_type>
     121static 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
     125template<typename pass_type, typename node_type>
     126static inline void previsit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
     127
     128
     129template<typename pass_type, typename node_type>
     130static 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
     134template<typename pass_type, typename node_type>
     135static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
     136
    120137//---------------------------------------------------------
    121138// Mutate
     
    165182static inline type * name##_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) { return nullptr;}    \
    166183
    167 FIELD_PTR( TypeSubstitution *, env )
     184FIELD_PTR( const TypeSubstitution *, env )
    168185FIELD_PTR( std::list< Statement* >, stmtsToAddBefore )
    169186FIELD_PTR( std::list< Statement* >, stmtsToAddAfter  )
     
    174191FIELD_PTR( PassVisitor<pass_type> * const, visitor )
    175192
     193#undef FIELD_PTR
     194
    176195//---------------------------------------------------------
    177196// Indexer
     
    198217        pass.indexer.func( arg );                                                                                                \
    199218}                                                                                                                              \
    200                                                                                                                                \
    201 template<typename pass_type>                                                                                                   \
    202 static inline void indexer_impl_##func ( pass_type &, long, type ) { }                                                          \
     219template<typename pass_type>                                                                                                   \
     220static inline void indexer_impl_##func ( pass_type &, long, type ) { }
    203221
    204222#define INDEXER_FUNC2( func, type1, type2 )                                                                                             \
     
    207225        pass.indexer.func( arg1, arg2 );                                                                                                \
    208226}                                                                                                                              \
    209                                                                                                                                \
    210227template<typename pass_type>                                                                                                   \
    211228static inline void indexer_impl_##func ( pass_type &, long, type1, type2 ) { }
    212229
    213230
    214 INDEXER_FUNC1( addId     , DeclarationWithType *       );
    215 INDEXER_FUNC1( addType   , NamedTypeDecl *             );
    216 INDEXER_FUNC1( addStruct , StructDecl *                );
    217 INDEXER_FUNC1( addEnum   , EnumDecl *                  );
    218 INDEXER_FUNC1( addUnion  , UnionDecl *                 );
    219 INDEXER_FUNC1( addTrait  , TraitDecl *                 );
    220 INDEXER_FUNC2( addWith   , std::list< Expression * > &, BaseSyntaxNode * );
    221 
    222 
    223 template<typename pass_type>
    224 static inline auto indexer_impl_addStructFwd( pass_type & pass, int, StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
     231INDEXER_FUNC1( addId     , const DeclarationWithType *       );
     232INDEXER_FUNC1( addType   , const NamedTypeDecl *             );
     233INDEXER_FUNC1( addStruct , const StructDecl *                );
     234INDEXER_FUNC1( addEnum   , const EnumDecl *                  );
     235INDEXER_FUNC1( addUnion  , const UnionDecl *                 );
     236INDEXER_FUNC1( addTrait  , const TraitDecl *                 );
     237INDEXER_FUNC2( addWith   , const std::list< Expression * > &, const Declaration * );
     238
     239#undef INDEXER_FUNC1
     240#undef INDEXER_FUNC2
     241
     242template<typename pass_type>
     243static inline auto indexer_impl_addStructFwd( pass_type & pass, int, const StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
    225244        StructDecl * fwd = new StructDecl( decl->name );
    226245        cloneAll( decl->parameters, fwd->parameters );
     
    229248
    230249template<typename pass_type>
    231 static inline auto indexer_impl_addStructFwd( pass_type &, long, StructDecl * ) {}
    232 
    233 template<typename pass_type>
    234 static inline auto indexer_impl_addUnionFwd( pass_type & pass, int, UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
     250static inline auto indexer_impl_addStructFwd( pass_type &, long, const StructDecl * ) {}
     251
     252template<typename pass_type>
     253static inline auto indexer_impl_addUnionFwd( pass_type & pass, int, const UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
    235254        UnionDecl * fwd = new UnionDecl( decl->name );
    236255        cloneAll( decl->parameters, fwd->parameters );
     
    239258
    240259template<typename pass_type>
    241 static inline auto indexer_impl_addUnionFwd( pass_type &, long, UnionDecl * ) {}
     260static inline auto indexer_impl_addUnionFwd( pass_type &, long, const UnionDecl * ) {}
    242261
    243262template<typename pass_type>
  • src/Common/ScopedMap.h

    r7951100 rb067d9b  
    2222#include <vector>
    2323
     24/// Default (empty) ScopedMap note type
     25struct EmptyNote {};
     26
    2427/// A map where the items are placed into nested scopes;
    25 /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
    26 template<typename Key, typename Value>
     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
     30template<typename Key, typename Value, typename Note = EmptyNote>
    2731class ScopedMap {
    28         typedef std::map< Key, Value > Scope;
     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        };
    2946        typedef std::vector< Scope > ScopeList;
    3047
    3148        ScopeList scopes; ///< scoped list of maps
    3249public:
    33         typedef typename Scope::key_type key_type;
    34         typedef typename Scope::mapped_type mapped_type;
    35         typedef typename Scope::value_type value_type;
     50        typedef typename MapType::key_type key_type;
     51        typedef typename MapType::mapped_type mapped_type;
     52        typedef typename MapType::value_type value_type;
    3653        typedef typename ScopeList::size_type size_type;
    3754        typedef typename ScopeList::difference_type difference_type;
    38         typedef typename Scope::reference reference;
    39         typedef typename Scope::const_reference const_reference;
    40         typedef typename Scope::pointer pointer;
    41         typedef typename Scope::const_pointer const_pointer;
     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;
    4259
    4360        class iterator : public std::iterator< std::bidirectional_iterator_tag,
     
    4562        friend class ScopedMap;
    4663        friend class const_iterator;
    47                 typedef typename std::map< Key, Value >::iterator wrapped_iterator;
    48                 typedef typename std::vector< std::map< Key, Value > > scope_list;
     64                typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     65                typedef typename ScopedMap::ScopeList scope_list;
    4966                typedef typename scope_list::size_type size_type;
    5067
    5168                /// Checks if this iterator points to a valid item
    5269                bool is_valid() const {
    53                         return it != (*scopes)[level].end();
     70                        return it != (*scopes)[level].map.end();
    5471                }
    5572
     
    7996
    8097                iterator& operator++ () {
    81                         if ( it == (*scopes)[level].end() ) {
     98                        if ( it == (*scopes)[level].map.end() ) {
    8299                                if ( level == 0 ) return *this;
    83100                                --level;
    84                                 it = (*scopes)[level].begin();
     101                                it = (*scopes)[level].map.begin();
    85102                        } else {
    86103                                ++it;
     
    92109                iterator& operator-- () {
    93110                        // may fail if this is the begin iterator; allowed by STL spec
    94                         if ( it == (*scopes)[level].begin() ) {
     111                        if ( it == (*scopes)[level].map.begin() ) {
    95112                                ++level;
    96                                 it = (*scopes)[level].end();
     113                                it = (*scopes)[level].map.end();
    97114                        }
    98115                        --it;
     
    107124
    108125                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; }
    109129
    110130        private:
     
    117137                                                     value_type > {
    118138        friend class ScopedMap;
    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;
     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;
    122142                typedef typename scope_list::size_type size_type;
    123143
    124144                /// Checks if this iterator points to a valid item
    125145                bool is_valid() const {
    126                         return it != (*scopes)[level].end();
     146                        return it != (*scopes)[level].map.end();
    127147                }
    128148
     
    157177
    158178                const_iterator& operator++ () {
    159                         if ( it == (*scopes)[level].end() ) {
     179                        if ( it == (*scopes)[level].map.end() ) {
    160180                                if ( level == 0 ) return *this;
    161181                                --level;
    162                                 it = (*scopes)[level].begin();
     182                                it = (*scopes)[level].map.begin();
    163183                        } else {
    164184                                ++it;
     
    170190                const_iterator& operator-- () {
    171191                        // may fail if this is the begin iterator; allowed by STL spec
    172                         if ( it == (*scopes)[level].begin() ) {
     192                        if ( it == (*scopes)[level].map.begin() ) {
    173193                                ++level;
    174                                 it = (*scopes)[level].end();
     194                                it = (*scopes)[level].map.end();
    175195                        }
    176196                        --it;
     
    185205
    186206                size_type get_level() const { return level; }
     207
     208                const Note& get_note() const { return (*scopes)[level].note; }
    187209
    188210        private:
     
    197219        }
    198220
     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
    199227        /// Ends a scope; invalidates any iterators pointing to elements of that scope
    200228        void endScope() {
     
    204232
    205233        /// Default constructor initializes with one scope
    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); }
     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); }
    214246
    215247        /// Gets the index of the current scope (counted from 1)
    216248        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; }
    217253
    218254        /// Finds the given key in the outermost scope it occurs; returns end() for none such
    219255        iterator find( const Key &key ) {
    220256                for ( size_type i = scopes.size() - 1; ; --i ) {
    221                         typename Scope::iterator val = scopes[i].find( key );
    222                         if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     257                        typename MapType::iterator val = scopes[i].map.find( key );
     258                        if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
    223259                        if ( i == 0 ) break;
    224260                }
     
    226262        }
    227263        const_iterator find( const Key &key ) const {
    228                         return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->find( key ) );
     264                        return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->find( key ) );
    229265        }
    230266
    231267        /// Finds the given key in the provided scope; returns end() for none such
    232268        iterator findAt( size_type scope, const Key& key ) {
    233                 typename Scope::iterator val = scopes[scope].find( key );
    234                 if ( val != scopes[scope].end() ) return iterator( scopes, val, scope );
     269                typename MapType::iterator val = scopes[scope].map.find( key );
     270                if ( val != scopes[scope].map.end() ) return iterator( scopes, val, scope );
    235271                return end();
    236272        }
    237273        const_iterator findAt( size_type scope, const Key& key ) const {
    238                 return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findAt( scope, key ) );
     274                return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findAt( scope, key ) );
    239275        }
    240276
     
    243279                if ( it.level == 0 ) return end();
    244280                for ( size_type i = it.level - 1; ; --i ) {
    245                         typename Scope::iterator val = scopes[i].find( key );
    246                         if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     281                        typename MapType::iterator val = scopes[i].map.find( key );
     282                        if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
    247283                        if ( i == 0 ) break;
    248284                }
     
    250286        }
    251287        const_iterator findNext( const_iterator &it, const Key &key ) const {
    252                         return const_iterator( const_cast< ScopedMap< Key, Value >* >(this)->findNext( it, key ) );
     288                        return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findNext( it, key ) );
    253289        }
    254290
     
    256292        template< typename value_type_t >
    257293        std::pair< iterator, bool > insert( value_type_t&& value ) {
    258                 std::pair< typename Scope::iterator, bool > res = scopes.back().insert( std::forward<value_type_t>( value ) );
     294                std::pair< typename MapType::iterator, bool > res = scopes.back().map.insert( std::forward<value_type_t>( value ) );
    259295                return std::make_pair( iterator(scopes, std::move( res.first ), scopes.size()-1), std::move( res.second ) );
    260296        }
     
    262298        template< typename value_type_t >
    263299        std::pair< iterator, bool > insert( iterator at, 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 ) );
     300                MapType& scope = (*at.scopes)[ at.level ].map;
     301                std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
    266302                return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
    267303        }
     
    272308        template< typename value_type_t >
    273309        std::pair< iterator, bool > insertAt( size_type scope, value_type_t&& value ) {
    274                 std::pair< typename Scope::iterator, bool > res = scopes.at(scope).insert( std::forward<value_type_t>( value ) );
     310                std::pair< typename MapType::iterator, bool > res = scopes.at(scope).map.insert( std::forward<value_type_t>( value ) );
    275311                return std::make_pair( iterator(scopes, std::move( res.first ), scope), std::move( res.second ) );
    276312        }
     
    288324
    289325        iterator erase( iterator pos ) {
    290                 Scope& scope = (*pos.scopes) [ pos.level ];
     326                MapType& scope = (*pos.scopes)[ pos.level ].map;
    291327                const typename iterator::wrapped_iterator& new_it = scope.erase( pos.it );
    292328                iterator it( *pos.scopes, new_it, pos.level );
  • src/Common/SemanticError.h

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 16 15:01:23 2018
    13 // Update Count     : 30
     12// Last Modified On : Thu Jul 19 10:09:17 2018
     13// Update Count     : 31
    1414//
    1515
     
    1717
    1818#include "ErrorObjects.h"
     19#include "AST/Node.hpp"
    1920#include <cstring>
    2021
     
    5657        {"reference-conversion"   , "rvalue to reference conversion of rvalue: %s" , Severity::Warn},
    5758        {"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},
    5862};
    5963
     
    6266        RvalueToReferenceConversion,
    6367        BadQualifiersZeroOne,
    64         NUMBER_OF_WARNINGS, //This MUST be the last warning
     68        AggrForwardDecl,
     69        SuperfluousDecl,
     70        GccAttributes,
     71        NUMBER_OF_WARNINGS, // This MUST be the last warning
    6572};
    6673
  • src/Common/module.mk

    r7951100 rb067d9b  
    1515###############################################################################
    1616
    17 SRC += Common/SemanticError.cc \
    18        Common/UniqueName.cc \
    19        Common/DebugMalloc.cc \
    20        Common/Assert.cc \
    21        Common/Heap.cc
     17SRC_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
     28SRC += $(SRC_COMMON) Common/DebugMalloc.cc
     29SRCDEMANGLE += $(SRC_COMMON)
  • src/Common/utility.h

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May  6 22:24:16 2018
    13 // Update Count     : 40
     12// Last Modified On : Wed Jul 24 14:28:19 2019
     13// Update Count     : 41
    1414//
    1515
    1616#pragma once
    1717
     18#include <cassert>
    1819#include <cctype>
    1920#include <algorithm>
     
    2627#include <string>
    2728#include <type_traits>
    28 
    29 #include <cassert>
     29#include <utility>
     30#include <vector>
    3031
    3132#include "Common/Indenter.h"
     33
     34class Expression;
     35
     36/// bring std::move into global scope
     37using std::move;
     38
     39/// partner to move that copies any copyable type
     40template<typename T>
     41T copy( const T & x ) { return x; }
    3242
    3343template< typename T >
     
    7181
    7282template< typename Container >
    73 void deleteAll( Container &container ) {
    74         for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
    75                 delete *i;
     83void deleteAll( const Container &container ) {
     84        for ( const auto &i : container ) {
     85                delete i;
    7686        } // for
    7787}
     
    142152                return ret;
    143153        } // switch
     154}
     155
     156/// Splice src onto the end of dst, clearing src
     157template< typename T >
     158void 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
     165template< typename T >
     166void spliceBegin( std::vector< T > & dst, std::vector< T > & src ) {
     167        splice( src, dst );
     168        dst.swap( src );
    144169}
    145170
     
    456481} // ilog2
    457482
     483// -----------------------------------------------------------------------------
     484/// evaluates expr as a long long int. If second is false, expr could not be evaluated
     485std::pair<long long int, bool> eval(const Expression * expr);
     486
     487namespace ast {
     488        class Expr;
     489}
     490
     491std::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.
     497template<typename Iter, typename Compare>
     498Iter 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
     516template<typename Iter, typename Compare>
     517inline 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
     522template<typename Iter>
     523inline Iter sort_mins( Iter begin, Iter end ) {
     524        return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
     525}
    458526
    459527// Local Variables: //
  • src/Concurrency/Keywords.cc

    r7951100 rb067d9b  
    9797                        "__thrd",
    9898                        "get_thread",
    99                         "thread keyword requires threads to be in scope, add #include <thread>",
     99                        "thread keyword requires threads to be in scope, add #include <thread.hfa>",
    100100                        true,
    101101                        KeywordCastExpr::Thread
     
    129129                        "__cor",
    130130                        "get_coroutine",
    131                         "coroutine keyword requires coroutines to be in scope, add #include <coroutine>",
     131                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>",
    132132                        true,
    133133                        KeywordCastExpr::Coroutine
     
    161161                        "__mon",
    162162                        "get_monitor",
    163                         "monitor keyword requires monitors to be in scope, add #include <monitor>",
     163                        "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>",
    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>\n" );
     490                        SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor.hfa>\n" );
    491491
    492492                // Instrument the body
     
    501501        void MutexKeyword::postvisit(StructDecl* decl) {
    502502
    503                 if( decl->name == "monitor_desc" ) {
     503                if( decl->name == "monitor_desc" && decl->body ) {
    504504                        assert( !monitor_decl );
    505505                        monitor_decl = decl;
    506506                }
    507                 else if( decl->name == "monitor_guard_t" ) {
     507                else if( decl->name == "monitor_guard_t" && decl->body ) {
    508508                        assert( !guard_decl );
    509509                        guard_decl = decl;
    510510                }
    511                 else if( decl->name == "monitor_dtor_guard_t" ) {
     511                else if( decl->name == "monitor_dtor_guard_t" && decl->body ) {
    512512                        assert( !dtor_guard_decl );
    513513                        dtor_guard_decl = decl;
     
    575575
    576576                //in reverse order :
    577                 // monitor_guard_t __guard = { __monitors, #, func };
     577                // monitor_dtor_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>");
     687                                SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread.hfa>");
    688688                        }
    689689
  • src/Concurrency/Waitfor.cc

    r7951100 rb067d9b  
    1111// Last Modified By :
    1212// Last Modified On :
    13 // Update Count     : 5
     13// Update Count     : 7
    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;
    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();
     68                {
     69                        acceptable_t acceptables[3];
     70                        if( a < 1 ) {
     71                                acceptables[0].func = f;
     72                                acceptables[0].mon = a;
    8773                        }
    88                         case 1:
    89                         {
    90                                 baz();
     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();
     87                                }
     88                                case 1:
     89                                {
     90                                        baz();
     91                                }
     92                                case 2:
     93                                        signal(a);
     94                                        {
     95                                                break;
     96                                        }
    9197                        }
    92                         case 2:
    93                                 signal(a);
    94                                 {
    95                                         break;
    96                                 }
    9798                }
    9899        }
     
    250251        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
    251252                if( !decl_monitor || !decl_acceptable || !decl_mask )
    252                         SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
     253                        SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor.hfa>" );
    253254
    254255                CompoundStmt * stmt = new CompoundStmt();
     
    555556                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
    556557                                        {
    557                                                 clause.statement,
    558                                                 new BranchStmt(
    559                                                         "",
    560                                                         BranchStmt::Break
    561                                                 )
     558                                                new CompoundStmt({
     559                                                        clause.statement,
     560                                                        new BranchStmt(
     561                                                                "",
     562                                                                BranchStmt::Break
     563                                                        )
     564                                                })
    562565                                        }
    563566                                )
     
    570573                                        new ConstantExpr( Constant::from_int( -2 ) ),
    571574                                        {
    572                                                 waitfor->timeout.statement,
    573                                                 new BranchStmt(
    574                                                         "",
    575                                                         BranchStmt::Break
    576                                                 )
     575                                                new CompoundStmt({
     576                                                        waitfor->timeout.statement,
     577                                                        new BranchStmt(
     578                                                                "",
     579                                                                BranchStmt::Break
     580                                                        )
     581                                                })
    577582                                        }
    578583                                )
     
    585590                                        new ConstantExpr( Constant::from_int( -1 ) ),
    586591                                        {
    587                                                 waitfor->orelse.statement,
    588                                                 new BranchStmt(
    589                                                         "",
    590                                                         BranchStmt::Break
    591                                                 )
     592                                                new CompoundStmt({
     593                                                        waitfor->orelse.statement,
     594                                                        new BranchStmt(
     595                                                                "",
     596                                                                BranchStmt::Break
     597                                                        )
     598                                                })
    592599                                        }
    593600                                )
  • src/Concurrency/module.mk

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

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

    r7951100 rb067d9b  
    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 Aug 18 10:22:00 2017
    13 // Update Count     : 12
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Mar 11 22:26:52 2019
     13// Update Count     : 14
    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

    r7951100 rb067d9b  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Jul 28 13:32:43 2015
    13 // Update Count     : 156
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Mar 11 22:26:02 2019
     13// Update Count     : 159
    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
    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 ) {
     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 ) {
    8080                assert( definition != 0 );
    8181                assert( llabel.size() > 0 );
     
    100100                } // for
    101101
    102                 // produce one of the labels attached to this statement to be
    103                 // temporarily used as the canonical label
     102                // produce one of the labels attached to this statement to be temporarily used as the canonical label
    104103                return labelTable[ llabel.front() ]->get_label();
    105104        }
     
    117116
    118117        // Builds a table that maps a label to its defining statement.
    119         std::map<Label, Statement * > *LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
     118        std::map<Label, Statement * > * LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
    120119                std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
    121120                for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
  • src/ControlStruct/LabelGenerator.cc

    r7951100 rb067d9b  
    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 : Thr Aug 14 14:14:00 2015
    13 // Update Count     : 14
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Mar 11 22:23:20 2019
     13// Update Count     : 15
    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 
    3231                return labelGenerator;
    3332        }
     
    3837                if ( stmt && ! stmt->get_labels().empty() ) {
    3938                        os << "_" << stmt->get_labels().front() << "__";
    40                 }
     39                } // if
    4140                std::string ret = os.str();
    4241                Label l( ret );
  • src/ControlStruct/MLEMutator.cc

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar  8 17:08:25 2018
    13 // Update Count     : 219
     12// Last Modified On : Tue Oct 22 17:22:44 2019
     13// Update Count     : 220
    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
    315335        void MLEMutator::premutate( CaseStmt *caseStmt ) {
    316336                visit_children = false;
  • src/ControlStruct/MLEMutator.h

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

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

    r7951100 rb067d9b  
    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 WithTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
     78                class Pass1 final : public BoxPass, public WithConstTypeSubstitution, 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 WithTypeSubstitution {
     152                class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithConstTypeSubstitution {
    153153                public:
    154154                        PolyGenericCalculator();
     
    657657                                paramExpr = new AddressExpr( paramExpr );
    658658                        } // if
    659                         arg = appExpr->get_args().insert( arg, paramExpr ); // add argument to function call
     659                        arg = appExpr->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->set_env( appExpr->get_env() );
    664                         appExpr->set_env( 0 );
     663                        commaExpr->env = appExpr->env;
     664                        appExpr->env = nullptr;
    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->get_returnVals().front()->get_type(), arg );
     710                                ret = addRetParam( appExpr, function->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->get_function(), adapteeType ) );
     717                        appExpr->get_args().push_front( new CastExpr( appExpr->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->result->get_lvalue() ) {
     727                        if ( arg->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->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() );
     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() );
    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 );
    840839                                        return deref;
    841840                                } // if
     
    17641763
    17651764                Expression *PolyGenericCalculator::postmutate( SizeofExpr *sizeofExpr ) {
    1766                         Type *ty = sizeofExpr->get_isType() ? 
     1765                        Type *ty = sizeofExpr->get_isType() ?
    17671766                                sizeofExpr->get_type() : sizeofExpr->get_expr()->get_result();
    1768                        
     1767
    17691768                        Expression * gen = genSizeof( ty );
    17701769                        if ( gen ) {
  • src/GenPoly/GenPoly.cc

    r7951100 rb067d9b  
    2424#include <vector>                       // for vector
    2525
     26#include "AST/Type.hpp"
    2627#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2728#include "ResolvExpr/typeops.h"         // for flatten
     
    262263                } else {
    263264                        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 );
    264273                }
    265274        }
     
    440449        }
    441450
    442         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env ) {
     451        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
    443452                // is parameter is not polymorphic, don't need to box
    444453                if ( ! isPolyType( param, exprTyVars ) ) return false;
     
    450459        }
    451460
    452         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env ) {
     461        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
    453462                FunctionType * function = getFunctionType( appExpr->function->result );
    454463                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
     
    459468
    460469        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    461                 // xxx - should this actually be insert?
    462                 tyVarMap[ tyVar->get_name() ] = TypeDecl::Data{ tyVar };
     470                tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );
    463471        }
    464472
  • src/GenPoly/GenPoly.h

    r7951100 rb067d9b  
    2020
    2121#include "ErasableScopedMap.h"    // for ErasableScopedMap
     22#include "AST/Fwd.hpp"
    2223#include "SymTab/Mangler.h"       // for Mangler
    2324#include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
     
    7273        /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
    7374        FunctionType *getFunctionType( Type *ty );
     75        const ast::FunctionType * getFunctionType( const ast::Type * ty );
    7476
    7577        /// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;
     
    8183
    8284        /// true if arg requires boxing given exprTyVars
    83         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env );
     85        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );
    8486
    8587        /// true if arg requires boxing in the call to appExpr
    86         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env );
     88        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );
    8789
    8890        /// Adds the type variable `tyVar` to `tyVarMap`
  • src/GenPoly/InstantiateGeneric.cc

    r7951100 rb067d9b  
    168168
    169169        /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
    170         struct GenericInstantiator final : public WithTypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards {
     170        struct GenericInstantiator final : public WithConstTypeSubstitution, 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

    r7951100 rb067d9b  
    2121#include "Lvalue.h"
    2222
     23#include "InitTweak/InitTweak.h"
    2324#include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
    2425#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2526#include "ResolvExpr/Unify.h"            // for unify
    2627#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
    3536
    3637#if 0
     
    4445                // TODO: fold this into the general createDeref function??
    4546                Expression * mkDeref( Expression * arg ) {
    46                         if ( SymTab::dereferenceOperator ) {
     47                        if ( Validate::dereferenceOperator ) {
    4748                                // 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
    48                                 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
     49                                VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator );
    4950                                deref->result = new PointerType( Type::Qualifiers(), deref->result );
    5051                                Type * base = InitTweak::getPointerBase( arg->result );
     
    5354                                delete ret->result;
    5455                                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 a reference
     148                // true for intrinsic function calls that return an lvalue in C
    149149                bool isIntrinsicReference( Expression * expr ) {
     150                        // known intrinsic-reference prelude functions
     151                        static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    150152                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    151153                                std::string fname = InitTweak::getFunctionName( untyped );
    152                                 // known intrinsic-reference prelude functions
    153                                 return fname == "*?" || fname == "?[?]";
     154                                return lvalueFunctions.count(fname);
    154155                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    155156                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    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 );
     157                                        return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
    160158                                }
    161159                        }
     
    168166                                ReferenceType * result = strict_dynamic_cast< ReferenceType * >( appExpr->result );
    169167                                appExpr->result = result->base->clone();
    170                                 appExpr->result->set_lvalue( true );
    171168                                if ( ! inIntrinsic ) {
    172169                                        // when not in an intrinsic function, add a cast to
     
    197194                                unsigned int i = 0;
    198195                                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;
    201200                                        Expression *& arg = std::get<0>( p );
    202201                                        Type * formal = std::get<1>( p )->get_type();
     
    212211                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
    213212
    214                                                 if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
     213                                                if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    215214                                                        // needed for definition of prelude functions, etc.
    216215                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     
    228227                                                        arg = new AddressExpr( arg );
    229228                                                // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
    230                                                 } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
     229                                                } else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    231230                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
    232231                                                        PRINT(
     
    243242                                        }
    244243                                        ++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 ) );
    357359                        int depth1 = destType->referenceDepth();
    358360                        int depth2 = srcType->referenceDepth();
    359361                        int diff = depth1 - depth2;
    360362
    361                         if ( diff > 0 && ! srcType->get_lvalue() ) {
     363                        if ( diff > 0 && ! castExpr->arg->get_lvalue() ) {
    362364                                // rvalue to reference conversion -- introduce temporary
    363365                                // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g.
     
    403405                                        ret = new AddressExpr( ret );
    404406                                }
    405                                 if ( srcType->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
     407                                if ( castExpr->arg->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
    406408                                        // must keep cast if cast-to type is different from the actual type
    407409                                        castExpr->arg = ret;
     
    432434                                delete ret->result;
    433435                                ret->result = castExpr->result;
    434                                 ret->result->set_lvalue( true ); // ensure result is lvalue
     436                                assert( ret->get_lvalue() ); // ensure result is lvalue
    435437                                castExpr->env = nullptr;
    436438                                castExpr->arg = nullptr;
  • src/GenPoly/ScopedSet.h

    r7951100 rb067d9b  
    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
    106108                private:
    107109                        scope_list const *scopes;
     
    180182                        bool operator!= (const const_iterator &that) { return !( *this == that ); }
    181183
     184                        size_type get_level() const { return i; }
     185
    182186                private:
    183187                        scope_list const *scopes;
     
    185189                        size_type i;
    186190                };
    187                
     191
    188192                /// Starts a new scope
    189193                void beginScope() {
     
    222226                        return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
    223227                }
    224                
     228
    225229                /// Finds the given key in the outermost scope inside the given scope where it occurs
    226230                iterator findNext( const_iterator &it, const Value &key ) {
     
    242246                        return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
    243247                }
    244                
     248
    245249        };
    246250} // namespace GenPoly
  • src/GenPoly/ScrubTyVars.cc

    r7951100 rb067d9b  
    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);
    5254                        } // switch
    5355                } // if
  • src/GenPoly/Specialize.cc

    r7951100 rb067d9b  
    4242
    4343namespace GenPoly {
    44         struct Specialize final : public WithTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
     44        struct Specialize final : public WithConstTypeSubstitution, 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, TypeSubstitution *env ) {
     56        bool needsPolySpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) {
    5757                if ( env ) {
    5858                        using namespace ResolvExpr;
     
    145145        }
    146146
    147         bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
     147        bool needsSpecialization( Type *formalType, Type *actualType, const TypeSubstitution *env ) {
    148148                return needsPolySpecialization( formalType, actualType, env ) || needsTupleSpecialization( formalType, actualType );
    149149        }
     
    245245                appExpr->env = TypeSubstitution::newFromExpr( appExpr, env );
    246246                if ( inferParams ) {
    247                         appExpr->get_inferParams() = *inferParams;
     247                        appExpr->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->get_inferParams() );
     286                        *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->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->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
    298                                 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, inferParam->second.inferParams.get() );
     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 );
    299299                        }
    300300                }
  • src/GenPoly/module.mk

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

    r7951100 rb067d9b  
    3737        class GlobalFixer : public WithShortCircuiting {
    3838          public:
    39                 GlobalFixer( const std::string & name, bool inLibrary );
     39                GlobalFixer( bool inLibrary );
    4040
    4141                void previsit( ObjectDecl *objDecl );
     
    5252        };
    5353
    54         void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
    55                 PassVisitor<GlobalFixer> visitor( name, inLibrary );
     54        void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ) {
     55                PassVisitor<GlobalFixer> visitor( inLibrary );
    5656                acceptAll( translationUnit, visitor );
    5757                GlobalFixer & fixer = visitor.pass;
     
    7070        }
    7171
    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 );
     72        GlobalFixer::GlobalFixer( bool inLibrary ) : tempNamer( "_global_init" ) {
    8373                std::list< Expression * > ctorParameters;
    8474                std::list< Expression * > dtorParameters;
     
    9080                        // for library code are run before constructors and destructors for user code,
    9181                        // specify a priority when building the library. Priorities 0-100 are reserved by gcc.
    92                         ctorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) );
    93                         dtorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) );
     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 ) ) );
    9486                }
    95                 initFunction = new FunctionDecl( "_init_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     87                initFunction = new FunctionDecl( "__global_init__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    9688                initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
    97                 destroyFunction = new FunctionDecl( "_destroy_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     89                destroyFunction = new FunctionDecl( "__global_destroy__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    9890                destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
    9991        }
     
    110102                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    111103                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    112                         assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
     104                        assert( ! ctorInit->ctor || ! ctorInit->init );
    113105
    114                         Statement * dtor = ctorInit->get_dtor();
     106                        Statement * dtor = ctorInit->dtor;
    115107                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    116108                                // don't need to call intrinsic dtor, because it does nothing, but
    117109                                // non-intrinsic dtors must be called
    118110                                destroyStatements.push_front( dtor );
    119                                 ctorInit->set_dtor( NULL );
     111                                ctorInit->dtor = nullptr;
    120112                        } // if
    121                         if ( Statement * ctor = ctorInit->get_ctor() ) {
     113                        if ( Statement * ctor = ctorInit->ctor ) {
    122114                                initStatements.push_back( ctor );
    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 );
     115                                objDecl->init = nullptr;
     116                                ctorInit->ctor = nullptr;
     117                        } else if ( Initializer * init = ctorInit->init ) {
     118                                objDecl->init = init;
     119                                ctorInit->init = nullptr;
    128120                        } else {
    129121                                // no constructor and no initializer, which is okay
    130                                 objDecl->set_init( NULL );
     122                                objDecl->init = nullptr;
    131123                        } // if
    132124                        delete ctorInit;
  • src/InitTweak/FixGlobalInit.h

    r7951100 rb067d9b  
    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, 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 );
     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 );
    3228} // namespace
    3329
  • src/InitTweak/FixInit.cc

    r7951100 rb067d9b  
    1010// Created On       : Wed Jan 13 16:29:30 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 21 17:35:05 2017
    13 // Update Count     : 74
     12// Last Modified On : Wed Feb 13 18:15:56 2019
     13// Update Count     : 76
    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
    5657#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
     58#include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy
    5759
    5860bool ctordtorp = false; // print all debug
     
    6668namespace InitTweak {
    6769        namespace {
    68                 typedef std::unordered_map< int, int > UnqCount;
    69 
    7070                struct SelfAssignChecker {
    7171                        void previsit( ApplicationExpr * appExpr );
    7272                };
    7373
    74                 struct InsertImplicitCalls : public WithTypeSubstitution {
     74                struct StmtExprResult {
     75                        static void link( std::list< Declaration * > & translationUnit );
     76
     77                        void previsit( StmtExpr * stmtExpr );
     78                };
     79
     80                struct InsertImplicitCalls : public WithConstTypeSubstitution {
    7581                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
    7682                        /// function calls need their parameters to be copy constructed
     
    8086                };
    8187
    82                 struct ResolveCopyCtors final : public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution {
     88                struct ResolveCopyCtors final : public WithStmtsToAdd, public WithIndexer, public WithShortCircuiting, public WithTypeSubstitution, public WithVisitorRef<ResolveCopyCtors> {
    8389                        /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
    8490                        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
    8591                        /// arguments and return value temporaries
    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 );
     92                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
     93
     94                        Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     95                        void premutate( StmtExpr * stmtExpr );
     96                        void premutate( UniqueExpr * unqExpr );
    9497
    9598                        /// create and resolve ctor/dtor expression: fname(var, [cpArg])
     
    98101                        bool skipCopyConstruct( Type * type );
    99102                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
    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;
     103                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr, Expression *& arg );
    104104                };
    105105
     
    162162                        using Parent::previsit;
    163163
    164                         void previsit( ObjectDecl * objDecl );
    165164                        void previsit( FunctionDecl * funcDecl );
    166165
    167                         void previsit( CompoundStmt * compoundStmt );
    168                         void postvisit( CompoundStmt * compoundStmt );
    169                         void previsit( ReturnStmt * returnStmt );
    170166                        void previsit( BranchStmt * stmt );
    171167                private:
     
    185181
    186182                        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;
    201183                };
    202184
     
    236218                        Expression * postmutate( ConstructorExpr * ctorExpr );
    237219                };
     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                };
    238228        } // namespace
    239229
    240         void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     230        void fix( std::list< Declaration * > & translationUnit, bool inLibrary ) {
    241231                PassVisitor<SelfAssignChecker> checker;
    242232                acceptAll( translationUnit, checker );
    243233
     234                // fixes StmtExpr to properly link to their resulting expression
     235                StmtExprResult::link( translationUnit );
     236
    244237                // fixes ConstructorInit for global variables. should happen before fixInitializers.
    245                 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
    246 
    247                 UnqCount unqCount;
     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 );
    248242
    249243                InsertImplicitCalls::insert( translationUnit );
    250                 ResolveCopyCtors::resolveImplicitCalls( translationUnit, unqCount );
     244
     245                // Needs to happen before ResolveCopyCtors, because argument/return temporaries should not be considered in
     246                // error checking branch statements
    251247                InsertDtors::insert( translationUnit );
     248
     249                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
    252250                FixInit::fixInitializers( translationUnit );
    253 
    254                 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly
    255                 FixCopyCtors::fixCopyCtors( translationUnit, unqCount );
    256 
    257251                GenStructMemberCalls::generate( translationUnit );
    258252
    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.
     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.
    266255                FixCtorExprs::fix( translationUnit );
    267256        }
    268257
    269258        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
    270319                void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {
    271320                        PassVisitor<InsertImplicitCalls> inserter;
     
    273322                }
    274323
    275                 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    276                         PassVisitor<ResolveCopyCtors> resolver( unqCount );
    277                         acceptAll( translationUnit, resolver );
     324                void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) {
     325                        PassVisitor<ResolveCopyCtors> resolver;
     326                        mutateAll( translationUnit, resolver );
    278327                }
    279328
     
    303352                }
    304353
    305                 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    306                         PassVisitor<FixCopyCtors> fixer( unqCount );
    307                         mutateAll( translationUnit, fixer );
    308                 }
    309 
    310354                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    311355                        PassVisitor<GenStructMemberCalls> warner;
     
    318362                }
    319363
    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;
     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;
    368416                                                return;
    369417                                        }
    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                         }
     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;
    383448                }
    384449
     
    457522                        if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) {
    458523                                // fix newly generated StmtExpr
    459                                 postvisit( assign->stmtExpr );
     524                                premutate( assign->stmtExpr );
    460525                        }
    461526                        return resolved;
     
    489554                                        // so that the object isn't changed inside of the polymorphic function
    490555                                        if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
     556                                        // xxx - leaking tmp
    491557                                }
    492558                        }
     
    496562
    497563                        // replace argument to function call with temporary
    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 ) {
     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 ) {
    508615                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    509616
    510617                        ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
     618                        ObjectDecl * returnDecl = nullptr;
    511619
    512620                        // take each argument and attempt to copy construct it.
     
    517625                        for ( Expression * & arg : appExpr->args ) {
    518626                                Type * formal = nullptr;
    519                                 if ( iter != params.end() ) {
     627                                if ( iter != params.end() ) { // does not copy construct C-style variadic arguments
    520628                                        DeclarationWithType * param = *iter++;
    521629                                        formal = param->get_type();
     
    535643                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    536644                                ret->type->set_const( false );
    537                                 impCpCtorExpr->returnDecls.push_back( ret );
     645                                returnDecl = ret;
     646                                stmtsToAddBefore.push_back( new DeclStmt( ret ) );
    538647                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
     648                        } // for
     649                        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 );
    539662                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    540663                                        // 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                                 }
     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
     687                        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 );
    543694                        } // for
    544                         CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
    545                 }
    546 
    547                 void ResolveCopyCtors::postvisit( StmtExpr * stmtExpr ) {
    548                         assert( env );
    549                         assert( stmtExpr->get_result() );
    550                         Type * result = stmtExpr->get_result();
     695                        indexer.leaveScope();
     696
     697                        assert( stmtExpr->result );
     698                        Type * result = stmtExpr->result;
    551699                        if ( ! result->isVoid() ) {
    552700                                static UniqueName retNamer("_tmp_stmtexpr_ret");
     
    562710                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    563711                                ret->type->set_const( false );
    564                                 stmtExpr->returnDecls.push_front( ret );
     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 ) ) );
    565735
    566736                                // must have a non-empty body, otherwise it wouldn't have a result
    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 ) );
     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 ) ) );
    574741                        } // if
    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                         }
     742
     743                        assert( stmtExpr->returnDecls.empty() );
     744                        assert( stmtExpr->dtors.empty() );
    583745                }
    584746
     
    597759                }
    598760
    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() ) );
     761                void ResolveCopyCtors::premutate( UniqueExpr * unqExpr ) {
     762                        visit_children = false;
     763                        // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
     764                        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;
    611788                        } 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.
    676                         visit_children = false;
    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;
    709                         static std::unordered_map< int, UniqueExpr * > unqMap;
    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() ) ) {
    712789                                // take data from other UniqueExpr to ensure consistency
    713790                                delete unqExpr->get_expr();
    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;
     791                                unqExpr->expr = unqMap[unqExpr->get_id()]->expr->clone();
     792                                delete unqExpr->result;
     793                                unqExpr->result = maybeClone( unqExpr->expr->result );
     794                        }
    732795                }
    733796
     
    844907                                                        ctorInit->ctor = nullptr;
    845908                                                }
     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                                                }
    846924                                        } // if
    847925                                } else if ( Initializer * init = ctorInit->init ) {
     
    886964
    887965
    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 
    920966                void InsertDtors::previsit( FunctionDecl * funcDecl ) {
    921967                        // each function needs to have its own set of labels
     
    930976                }
    931977
    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 
    957978                // Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
    958979                // BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
     
    973994                                std::cerr << "S_L = " << printSet( lvars ) << std::endl;
    974995                        )
     996
     997
     998                        // std::set_difference requires that the inputs be sorted.
     999                        lvars.sort();
     1000                        curVars.sort();
    9751001
    9761002                        ObjectSet diff;
     
    9821008                        if ( ! diff.empty() ) {
    9831009                                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 ) );
    10021010                        } // if
    10031011                }
     
    11031111                                                arg2 = new MemberExpr( field, new VariableExpr( params.back() ) );
    11041112                                        }
    1105                                         InitExpander srcParam( arg2 );
     1113                                        InitExpander_old srcParam( arg2 );
    11061114                                        // cast away reference type and construct field.
    11071115                                        Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() );
     
    11161124                                                        callStmt->acceptMutator( *visitor );
    11171125                                                        if ( isCtor ) {
    1118                                                                 function->get_statements()->push_front( callStmt );
    1119                                                         } else {
     1126                                                                function->statements->push_front( callStmt );
     1127                                                        } else { // TODO: don't generate destructor function/object for intrinsic calls
    11201128                                                                // destructor statements should be added at the end
    1121                                                                 function->get_statements()->push_back( callStmt );
     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 );
    11221154                                                        }
    11231155                                                } catch ( SemanticErrorException & error ) {
     
    11631195
    11641196                        std::string fname = getFunctionName( appExpr );
    1165                         if ( fname == function->get_name() ) {
     1197                        if ( fname == function->name ) {
    11661198                                // call to same kind of function
    1167                                 Expression * firstParam = appExpr->get_args().front();
     1199                                Expression * firstParam = appExpr->args.front();
    11681200
    11691201                                if ( isThisExpression( firstParam, thisParam ) ) {
     
    11741206                                        // if first parameter is a member expression on the this parameter,
    11751207                                        // then remove the member from unhandled set.
    1176                                         if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
    1177                                                 unhandled.erase( memberExpr->get_member() );
     1208                                        if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
     1209                                                unhandled.erase( memberExpr->member );
    11781210                                        }
    11791211                                }
  • src/InitTweak/FixInit.h

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

    r7951100 rb067d9b  
    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 <iterator>                // for back_inserter, inserter, back_inse...
    21 #include <list>                    // for _List_iterator, list
    22 
     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"
    2328#include "CodeGen/OperatorTable.h"
    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
     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
    3237#include "ResolvExpr/Resolver.h"
    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
     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
    4450
    4551namespace InitTweak {
     
    186192
    187193                        // need to resolve array dimensions in order to accurately determine if constexpr
    188                         ResolvExpr::findSingleExpression( arrayType->dimension, SymTab::SizeType->clone(), indexer );
     194                        ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
    189195                        // array is variable-length when the dimension is not constexpr
    190196                        arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
     
    192198                        if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    193199
    194                         ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     200                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
    195201                        arrayDimension->get_type()->set_const( true );
    196202
     
    273279                assertf( objDecl, "genCtorDtor passed null objDecl" );
    274280                std::list< Statement * > stmts;
    275                 InitExpander srcParam( maybeClone( arg ) );
     281                InitExpander_old srcParam( maybeClone( arg ) );
    276282                SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), fname, back_inserter( stmts ), objDecl );
    277283                assert( stmts.size() <= 1 );
     
    285291                std::list< Statement * > dtor;
    286292
    287                 InitExpander srcParam( objDecl->get_init() );
    288                 InitExpander nullParam( (Initializer *)NULL );
     293                InitExpander_old srcParam( objDecl->get_init() );
     294                InitExpander_old nullParam( (Initializer *)NULL );
    289295                SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    290296                SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     
    352358                GuardScope( managedTypes );
    353359        }
     360
     361ast::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
    354387} // namespace InitTweak
    355388
  • src/InitTweak/GenInit.h

    r7951100 rb067d9b  
    1919#include <string>              // for string
    2020
     21#include "AST/Fwd.hpp"
     22#include "Common/CodeLocation.h"
     23#include "GenPoly/ScopedSet.h" // for ScopedSet
    2124#include "SynTree/SynTree.h"   // for Visitor Nodes
    22 
    23 #include "GenPoly/ScopedSet.h" // for ScopedSet
    2425
    2526namespace InitTweak {
     
    3536        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
    3637        ConstructorInit * genCtorInit( ObjectDecl * objDecl );
     38        ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl );
    3739
    3840        class ManagedTypes {
  • src/InitTweak/InitTweak.cc

    r7951100 rb067d9b  
     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
    116#include <algorithm>               // for find, all_of
    217#include <cassert>                 // for assertf, assert, strict_dynamic_cast
     
    419#include <iterator>                // for back_insert_iterator, back_inserter
    520#include <memory>                  // for __shared_ptr
    6 
     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"
    729#include "Common/PassVisitor.h"
    830#include "Common/SemanticError.h"  // for SemanticError
     
    2648#include "Tuples/Tuples.h"         // for Tuples::isTtype
    2749
    28 class UntypedValofExpr;
    29 
    3050namespace InitTweak {
    3151        namespace {
     
    6787                };
    6888
    69                 struct InitFlattener : public WithShortCircuiting {
     89                struct InitFlattener_old : public WithShortCircuiting {
    7090                        void previsit( SingleInit * singleInit ) {
    7191                                visit_children = false;
     
    7595                };
    7696
    77         }
     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
    78107
    79108        std::list< Expression * > makeInitList( Initializer * init ) {
    80                 PassVisitor<InitFlattener> flattener;
     109                PassVisitor<InitFlattener_old> flattener;
    81110                maybeAccept( init, flattener );
    82111                return flattener.pass.argList;
     
    95124        }
    96125
    97         class InitExpander::ExpanderImpl {
     126std::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 {
    98133        public:
    99134                virtual ~ExpanderImpl() = default;
     
    102137        };
    103138
    104         class InitImpl : public InitExpander::ExpanderImpl {
     139        class InitImpl_old : public InitExpander_old::ExpanderImpl {
    105140        public:
    106                 InitImpl( Initializer * init ) : init( init ) {}
    107                 virtual ~InitImpl() = default;
     141                InitImpl_old( Initializer * init ) : init( init ) {}
     142                virtual ~InitImpl_old() = default;
    108143
    109144                virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) {
     
    119154        };
    120155
    121         class ExprImpl : public InitExpander::ExpanderImpl {
     156        class ExprImpl_old : public InitExpander_old::ExpanderImpl {
    122157        public:
    123                 ExprImpl( Expression * expr ) : arg( expr ) {}
    124                 virtual ~ExprImpl() { delete arg; }
     158                ExprImpl_old( Expression * expr ) : arg( expr ) {}
     159                virtual ~ExprImpl_old() { delete arg; }
    125160
    126161                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     
    146181        };
    147182
    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*() {
     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*() {
    153188                return cur;
    154189        }
    155190
    156         InitExpander & InitExpander::operator++() {
     191        InitExpander_old & InitExpander_old::operator++() {
    157192                cur = expander->next( indices );
    158193                return *this;
     
    160195
    161196        // use array indices list to build switch statement
    162         void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
     197        void InitExpander_old::addArrayIndex( Expression * index, Expression * dimension ) {
    163198                indices.push_back( index );
    164199                indices.push_back( dimension );
    165200        }
    166201
    167         void InitExpander::clearArrayIndices() {
     202        void InitExpander_old::clearArrayIndices() {
    168203                deleteAll( indices );
    169204                indices.clear();
    170205        }
    171206
    172         bool InitExpander::addReference() {
     207        bool InitExpander_old::addReference() {
    173208                bool added = false;
    174209                for ( Expression *& expr : cur ) {
     
    201236
    202237                template< typename OutIterator >
    203                 void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
     238                void build( UntypedExpr * callExpr, InitExpander_old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
    204239                        if ( idx == idxEnd ) return;
    205240                        Expression * index = *idx++;
     
    258293        // remaining elements.
    259294        // To accomplish this, generate switch statement, consuming all of expander's elements
    260         Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     295        Statement * InitImpl_old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    261296                if ( ! init ) return nullptr;
    262297                CompoundStmt * block = new CompoundStmt();
     
    271306        }
    272307
    273         Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
     308        Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
    274309                return nullptr;
    275310        }
    276311
    277         Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
     312        Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) {
    278313                return expander->buildListInit( dst, indices );
    279314        }
     315
     316class InitExpander_new::ExpanderImpl {
     317public:
     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
     324namespace {
     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
     453InitExpander_new::InitExpander_new( const ast::Init * init )
     454: expander( new InitImpl_new{ init } ), crnt(), indices() {}
     455
     456InitExpander_new::InitExpander_new( const ast::Expr * expr )
     457: expander( new ExprImpl_new{ expr } ), crnt(), indices() {}
     458
     459std::vector< ast::ptr< ast::Expr > > InitExpander_new::operator* () { return crnt; }
     460
     461InitExpander_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
     468ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {
     469        return expander->buildListInit( callExpr, indices );
     470}
     471
     472void InitExpander_new::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {
     473        indices.emplace_back( index );
     474        indices.emplace_back( dimension );
     475}
     476
     477void InitExpander_new::clearArrayIndices() { indices.clear(); }
     478
     479bool InitExpander_new::addReference() {
     480        for ( ast::ptr< ast::Expr > & expr : crnt ) {
     481                expr = new ast::AddressExpr{ expr };
     482        }
     483        return ! crnt.empty();
     484}
    280485
    281486        Type * getTypeofThis( FunctionType * ftype ) {
     
    306511        }
    307512
    308         struct CallFinder {
    309                 CallFinder( const std::list< std::string > & names ) : names( names ) {}
     513        struct CallFinder_old {
     514                CallFinder_old( const std::list< std::string > & names ) : names( names ) {}
    310515
    311516                void postvisit( ApplicationExpr * appExpr ) {
     
    330535        };
    331536
     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
    332554        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
    333                 static PassVisitor<CallFinder> finder( std::list< std::string >{ "?{}", "^?{}" } );
     555                static PassVisitor<CallFinder_old> finder( std::list< std::string >{ "?{}", "^?{}" } );
    334556                finder.pass.matches = &matches;
    335557                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 );
    336564        }
    337565
     
    339567                std::list< Expression * > matches;
    340568                collectCtorDtorCalls( stmt, matches );
    341                 assert( matches.size() <= 1 );
     569                assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() );
    342570                return matches.size() == 1 ? matches.front() : nullptr;
    343571        }
     
    345573        namespace {
    346574                DeclarationWithType * getCalledFunction( Expression * expr );
     575                const ast::DeclWithType * getCalledFunction( const ast::Expr * expr );
    347576
    348577                template<typename CallExpr>
     
    354583                        return getCalledFunction( expr->get_args().front() );
    355584                }
     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
    356595
    357596                DeclarationWithType * getCalledFunction( Expression * expr ) {
     
    374613                        return nullptr;
    375614                }
     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                }
    376644        }
    377645
    378646        DeclarationWithType * getFunction( Expression * expr ) {
    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() );
     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 );
    383659                }
    384660                assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
     
    395671        }
    396672
     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
    397687        namespace {
    398688                template <typename Predicate>
     
    403693                        return std::all_of( callExprs.begin(), callExprs.end(), pred);
    404694                }
     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                }
    405701        }
    406702
     
    408704                return allofCtorDtor( stmt, []( Expression * callExpr ){
    409705                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    410                                 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_result() );
     706                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->function->result );
    411707                                assert( funcType );
    412708                                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;
    413721                        }
    414722                        return false;
     
    429737                                if ( pos == 0 ) return arg;
    430738                                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;
    431752                        }
    432753                        assert( false );
     
    453774        }
    454775
     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
    455796        namespace {
    456797                std::string funcName( Expression * func );
     798                std::string funcName( const ast::Expr * func );
    457799
    458800                template<typename CallExpr>
     
    463805                        assertf( ! expr->get_args().empty(), "Cannot get function name from dereference with no arguments" );
    464806                        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() );
    465816                }
    466817
     
    486837                        }
    487838                }
     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                }
    488861        }
    489862
     
    502875        }
    503876
     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
    504891        Type * getPointerBase( Type * type ) {
    505892                if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
     
    513900                }
    514901        }
     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        }
    515911
    516912        Type * isPointerType( Type * type ) {
     
    561957                void previsit( OffsetofExpr * ) {}
    562958                void previsit( OffsetPackExpr * ) {}
    563                 void previsit( AttrExpr * ) {}
    564959                void previsit( CommaExpr * ) {}
    565960                void previsit( LogicalExpr * ) {}
     
    6091004        bool isCtorDtorAssign( const std::string & str ) { return isCtorDtor( str ) || isAssignment( str ); }
    6101005
    611         FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) {
    612                 FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl );
     1006        const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ) {
     1007                const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( decl );
    6131008                if ( ! function ) return nullptr;
    6141009                if ( function->name != fname ) return nullptr;
     
    6271022        }
    6281023
    629         FunctionDecl * isAssignment( Declaration * decl ) {
     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 ) {
    6301036                return isCopyFunction( decl, "?=?" );
    6311037        }
    632         FunctionDecl * isDestructor( Declaration * decl ) {
    633                 if ( isDestructor( decl->get_name() ) ) {
    634                         return dynamic_cast< FunctionDecl * >( decl );
     1038        const FunctionDecl * isDestructor( const Declaration * decl ) {
     1039                if ( isDestructor( decl->name ) ) {
     1040                        return dynamic_cast< const FunctionDecl * >( decl );
    6351041                }
    6361042                return nullptr;
    6371043        }
    638         FunctionDecl * isDefaultConstructor( Declaration * decl ) {
     1044        const FunctionDecl * isDefaultConstructor( const Declaration * decl ) {
    6391045                if ( isConstructor( decl->name ) ) {
    640                         if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
     1046                        if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
    6411047                                if ( func->type->parameters.size() == 1 ) {
    6421048                                        return func;
     
    6461052                return nullptr;
    6471053        }
    648         FunctionDecl * isCopyConstructor( Declaration * decl ) {
     1054        const FunctionDecl * isCopyConstructor( const Declaration * decl ) {
    6491055                return isCopyFunction( decl, "?{}" );
    6501056        }
  • src/InitTweak/InitTweak.h

    r7951100 rb067d9b  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // RemoveInit.h --
     7// InitTweak.h --
    88//
    99// Author           : Rob Schluntz
    1010// Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:30:33 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jul 19 14:18:00 2019
     13// Update Count     : 6
    1414//
    1515
     
    1919#include <memory>             // for shared_ptr
    2020#include <string>             // for string, allocator
     21#include <vector>
    2122
     23#include "AST/Fwd.hpp"        // for AST nodes
    2224#include "SynTree/SynTree.h"  // for Visitor Nodes
    2325
    2426// helper functions for initialization
    2527namespace InitTweak {
    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 );
     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 );
    3134
    3235        /// returns the base type of the first parameter to a constructor/destructor/assignment function
     
    4144        /// transform Initializer into an argument list that can be passed to a call expression
    4245        std::list< Expression * > makeInitList( Initializer * init );
     46        std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init );
    4347
    4448        /// True if the resolver should try to construct dwt
     
    5761        /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
    5862        DeclarationWithType * getFunction( Expression * expr );
     63        const DeclarationWithType * getFunction( const Expression * expr );
     64        const ast::DeclWithType * getFunction( const ast::Expr * expr );
    5965
    6066        /// Non-Null if expr is a call expression whose target function is intrinsic
    6167        ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
     68        const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr);
    6269
    6370        /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
     
    6572        /// Currently has assertions that make it less than fully general.
    6673        bool isIntrinsicSingleArgCallStmt( Statement * stmt );
     74        bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );
    6775
    6876        /// True if stmt is a call statement where the function called is intrinsic.
     
    7179        /// get all Ctor/Dtor call expressions from a Statement
    7280        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
     81        std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt );
    7382
    7483        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     
    7786        /// returns the name of the function being called
    7887        std::string getFunctionName( Expression * expr );
     88        std::string getFunctionName( const ast::Expr * expr );
    7989
    8090        /// returns the argument to a call expression in position N indexed from 0
    8191        Expression *& getCallArg( Expression * callExpr, unsigned int pos );
     92        const ast::Expr * getCallArg( const ast::Expr * call, unsigned pos );
    8293
    8394        /// returns the base type of a PointerType or ArrayType, else returns NULL
    8495        Type * getPointerBase( Type * );
     96        const ast::Type* getPointerBase( const ast::Type* );
    8597
    8698        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
     
    91103        bool isConstExpr( Initializer * init );
    92104
    93         class InitExpander {
     105        class InitExpander_old {
    94106        public:
    95107                // expand by stepping through init to get each list of arguments
    96                 InitExpander( Initializer * init );
     108                InitExpander_old( Initializer * init );
    97109
    98110                // always expand to expr
    99                 InitExpander( Expression * expr );
     111                InitExpander_old( Expression * expr );
    100112
    101113                // iterator-like interface
    102114                std::list< Expression * > operator*();
    103                 InitExpander & operator++();
     115                InitExpander_old & operator++();
    104116
    105117                // builds statement which has the same semantics as a C-style list initializer
     
    120132                IndexList indices;
    121133        };
     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        };
    122167} // namespace
    123168
  • src/InitTweak/module.mk

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

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

    r7951100 rb067d9b  
    1010## Author           : Peter A. Buhr
    1111## Created On       : Sun May 31 08:51:46 2015
    12 ## Last Modified By : Andrew Beach
    13 ## Last Modified On : Tus Jul 25 10:34:00 2017
    14 ## Update Count     : 76
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Mon Aug  5 12:57:46 2019
     14## Update Count     : 98
    1515###############################################################################
    1616
    1717# create object files in directory with source files
    18 AUTOMAKE_OPTIONS = subdir-objects
     18AUTOMAKE_OPTIONS = foreign subdir-objects
     19ACLOCAL_AMFLAGS  = -I automake
    1920
    2021SRC = main.cc \
    21       MakeLibCfa.cc
     22      MakeLibCfa.cc \
     23      CompilationState.cc
     24
     25SRCDEMANGLE = CompilationState.cc
    2226
    2327MAINTAINERCLEANFILES =
     28MOSTLYCLEANFILES =
    2429
    25 # Is there a way to use a variable for the directory names?
     30if WITH_LIBPROFILER
     31LIBPROFILER = -lprofiler
     32endif
    2633
     34if WITH_LIBTCMALLOC
     35LIBTCMALLOC = -ltcmalloc
     36TCMALLOCFLAG = -DTCMALLOC
     37endif
     38
     39include AST/module.mk
    2740include CodeGen/module.mk
    2841include CodeTools/module.mk
     
    3750include SynTree/module.mk
    3851include Tuples/module.mk
     52include Validate/module.mk
    3953include Virtual/module.mk
    4054
     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
    4162# put into lib for now
    42 cfa_cpplibdir = ${CFA_LIBDIR}
    43 cfa_cpplib_PROGRAMS = driver/cfa-cpp
    44 driver_cfa_cpp_SOURCES = ${SRC}
    45 driver_cfa_cpp_LDADD = -ldl                     # yywrap
    46 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I${abs_top_srcdir}/src/include -DYY_NO_INPUT -O2 -g -std=c++14
    47 driver_cfa_cpp_LDFLAGS = -Xlinker -export-dynamic
     63cfa_cpplibdir = $(CFA_LIBDIR)
     64cfa_cpplib_PROGRAMS = ../driver/cfa-cpp $(DEMANGLER)
     65EXTRA_PROGRAMS = demangler
     66___driver_cfa_cpp_SOURCES = $(SRC)
     67___driver_cfa_cpp_LDADD = -ldl $(LIBPROFILER) $(LIBTCMALLOC)
     68
     69AM_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)
     70AM_LDFLAGS  = @HOST_FLAGS@ -Xlinker -export-dynamic
     71ARFLAGS     = cr
     72
     73demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
     74
     75demangler_LDADD = libdemangle.a -ldl                    # yywrap
     76
     77noinst_LIBRARIES = $(LIBDEMANGLE)
     78EXTRA_LIBRARIES = libdemangle.a
     79libdemangle_a_SOURCES = $(SRCDEMANGLE)
    4880
    4981MAINTAINERCLEANFILES += ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}}
  • src/Makefile.in

    r7951100 rb067d9b  
    2121###############################################################################
    2222
     23######################### -*- Mode: Makefile-Gmake -*- ########################
     24###############################################################################
     25
    2326#SRC +=  ArgTweak/Rewriter.cc \
    2427#       ArgTweak/Mutate.cc
     
    5962######################### -*- Mode: Makefile-Gmake -*- ########################
    6063###############################################################################
     64
     65######################### -*- Mode: Makefile-Gmake -*- ########################
     66###############################################################################
     67
    6168
    6269VPATH = @srcdir@
     
    134141build_triplet = @build@
    135142host_triplet = @host@
    136 cfa_cpplib_PROGRAMS = driver/cfa-cpp$(EXEEXT)
     143cfa_cpplib_PROGRAMS = ../driver/cfa-cpp$(EXEEXT) $(DEMANGLER)
     144EXTRA_PROGRAMS = demangler$(EXEEXT)
    137145subdir = src
    138146ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    139 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
     147am__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
    140153am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    141154        $(ACLOCAL_M4)
     
    145158CONFIG_CLEAN_FILES =
    146159CONFIG_CLEAN_VPATH_FILES =
     160LIBRARIES = $(noinst_LIBRARIES)
     161AM_V_AR = $(am__v_AR_@AM_V@)
     162am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
     163am__v_AR_0 = @echo "  AR      " $@;
     164am__v_AR_1 =
     165libdemangle_a_AR = $(AR) $(ARFLAGS)
     166libdemangle_a_LIBADD =
     167am__dirstamp = $(am__leading_dot)dirstamp
     168am__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)
     176am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \
     177        CodeGen/FixMain.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \
     178        CodeGen/OperatorTable.$(OBJEXT)
     179am__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)
     184am__objects_4 = ControlStruct/ForExprMutator.$(OBJEXT) \
     185        ControlStruct/LabelFixer.$(OBJEXT) \
     186        ControlStruct/LabelGenerator.$(OBJEXT) \
     187        ControlStruct/MLEMutator.$(OBJEXT) \
     188        ControlStruct/Mutate.$(OBJEXT)
     189am__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)
     211am__objects_6 = SymTab/Autogen.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \
     212        SymTab/Indexer.$(OBJEXT) SymTab/Mangler.$(OBJEXT) \
     213        SymTab/ManglerCommon.$(OBJEXT) SymTab/Validate.$(OBJEXT)
     214am__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)
     234am__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)
     244am_libdemangle_a_OBJECTS = $(am__objects_8)
     245libdemangle_a_OBJECTS = $(am_libdemangle_a_OBJECTS)
    147246am__installdirs = "$(DESTDIR)$(cfa_cpplibdir)"
    148247PROGRAMS = $(cfa_cpplib_PROGRAMS)
    149 am__dirstamp = $(am__leading_dot)dirstamp
    150 am__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)
    257 am_driver_cfa_cpp_OBJECTS = $(am__objects_1)
    258 driver_cfa_cpp_OBJECTS = $(am_driver_cfa_cpp_OBJECTS)
    259 driver_cfa_cpp_DEPENDENCIES =
    260 driver_cfa_cpp_LINK = $(CXXLD) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) \
    261         $(driver_cfa_cpp_LDFLAGS) $(LDFLAGS) -o $@
     248am__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)
     276am____driver_cfa_cpp_OBJECTS = $(am__objects_9)
     277___driver_cfa_cpp_OBJECTS = $(am____driver_cfa_cpp_OBJECTS)
     278am__DEPENDENCIES_1 =
     279___driver_cfa_cpp_DEPENDENCIES = $(am__DEPENDENCIES_1) \
     280        $(am__DEPENDENCIES_1)
     281AM_V_lt = $(am__v_lt_@AM_V@)
     282am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
     283am__v_lt_0 = --silent
     284am__v_lt_1 =
     285am_demangler_OBJECTS = SymTab/demangler.$(OBJEXT)
     286demangler_OBJECTS = $(am_demangler_OBJECTS)
     287demangler_DEPENDENCIES = libdemangle.a
    262288AM_V_P = $(am__v_P_@AM_V@)
    263289am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    276302am__depfiles_maybe = depfiles
    277303am__mv = mv -f
    278 AM_V_lt = $(am__v_lt_@AM_V@)
    279 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
    280 am__v_lt_0 = --silent
    281 am__v_lt_1 =
    282304CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
    283305        $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
     306LTCXXCOMPILE = $(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)
    284310AM_V_CXX = $(am__v_CXX_@AM_V@)
    285311am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
     
    287313am__v_CXX_1 =
    288314CXXLD = $(CXX)
    289 CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
    290         -o $@
     315CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
     316        $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
     317        $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    291318AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
    292319am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
    293320am__v_CXXLD_0 = @echo "  CXXLD   " $@;
    294321am__v_CXXLD_1 =
    295 @MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
    296322LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
     323LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
     324        $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
    297325AM_V_LEX = $(am__v_LEX_@AM_V@)
    298326am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
     
    300328am__v_LEX_1 =
    301329YLWRAP = $(top_srcdir)/automake/ylwrap
    302 @MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
    303330am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
    304331                   -e s/c++$$/h++/ -e s/c$$/h/
    305332YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
     333LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
     334        $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
    306335AM_V_YACC = $(am__v_YACC_@AM_V@)
    307336am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
     
    310339COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    311340        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
     341LTCOMPILE = $(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)
    312345AM_V_CC = $(am__v_CC_@AM_V@)
    313346am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
     
    315348am__v_CC_1 =
    316349CCLD = $(CC)
    317 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
     350LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
     351        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
     352        $(AM_LDFLAGS) $(LDFLAGS) -o $@
    318353AM_V_CCLD = $(am__v_CCLD_@AM_V@)
    319354am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
    320355am__v_CCLD_0 = @echo "  CCLD    " $@;
    321356am__v_CCLD_1 =
    322 SOURCES = $(driver_cfa_cpp_SOURCES)
    323 DIST_SOURCES = $(driver_cfa_cpp_SOURCES)
     357SOURCES = $(libdemangle_a_SOURCES) $(___driver_cfa_cpp_SOURCES) \
     358        $(demangler_SOURCES)
     359DIST_SOURCES = $(libdemangle_a_SOURCES) $(___driver_cfa_cpp_SOURCES) \
     360        $(demangler_SOURCES)
    324361am__can_run_installinfo = \
    325362  case $$AM_UPDATE_INFO_DIR in \
     
    327364    *) (install-info --version) >/dev/null 2>&1;; \
    328365  esac
    329 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
     366am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
     367        $(LISP)config.h.in
    330368# Read a list of newline-separated strings from the standard input,
    331369# and print each of them once, without duplicates.  Input order is
     
    346384ETAGS = etags
    347385CTAGS = ctags
    348 am__DIST_COMMON = $(srcdir)/CodeGen/module.mk \
     386am__DIST_COMMON = $(srcdir)/AST/module.mk $(srcdir)/CodeGen/module.mk \
    349387        $(srcdir)/CodeTools/module.mk $(srcdir)/Common/module.mk \
    350388        $(srcdir)/Concurrency/module.mk \
     
    353391        $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk \
    354392        $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk \
    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
     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
    358397DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    359398ACLOCAL = @ACLOCAL@
    360 ALLOCA = @ALLOCA@
    361399AMTAR = @AMTAR@
    362400AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
     401AR = @AR@
    363402AUTOCONF = @AUTOCONF@
    364403AUTOHEADER = @AUTOHEADER@
    365404AUTOMAKE = @AUTOMAKE@
    366405AWK = @AWK@
    367 BACKEND_CC = @BACKEND_CC@
     406BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
    368407CC = @CC@
    369408CCAS = @CCAS@
     
    371410CCASFLAGS = @CCASFLAGS@
    372411CCDEPMODE = @CCDEPMODE@
     412CFACC = @CFACC@
     413CFACC_INSTALL = @CFACC_INSTALL@
     414CFACPP = @CFACPP@
    373415CFA_BACKEND_CC = @CFA_BACKEND_CC@
    374416CFA_BINDIR = @CFA_BINDIR@
     
    382424CPPFLAGS = @CPPFLAGS@
    383425CXX = @CXX@
     426CXXCPP = @CXXCPP@
    384427CXXDEPMODE = @CXXDEPMODE@
    385428CXXFLAGS = @CXXFLAGS@
    386429CYGPATH_W = @CYGPATH_W@
    387430DEFS = @DEFS@
     431DEMANGLER = @DEMANGLER@
    388432DEPDIR = @DEPDIR@
     433DLLTOOL = @DLLTOOL@
     434DRIVER_DIR = @DRIVER_DIR@
     435DSYMUTIL = @DSYMUTIL@
     436DUMPBIN = @DUMPBIN@
    389437ECHO_C = @ECHO_C@
    390438ECHO_N = @ECHO_N@
     
    392440EGREP = @EGREP@
    393441EXEEXT = @EXEEXT@
     442FGREP = @FGREP@
    394443GREP = @GREP@
     444HAS_DISTCC = @HAS_DISTCC@
     445HOST_FLAGS = @HOST_FLAGS@
    395446INSTALL = @INSTALL@
    396447INSTALL_DATA = @INSTALL_DATA@
     
    398449INSTALL_SCRIPT = @INSTALL_SCRIPT@
    399450INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
     451LD = @LD@
    400452LDFLAGS = @LDFLAGS@
    401453LEX = @LEX@
    402454LEXLIB = @LEXLIB@
    403455LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
     456LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
     457LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
     458LIBDEMANGLE = @LIBDEMANGLE@
    404459LIBOBJS = @LIBOBJS@
    405460LIBS = @LIBS@
     461LIBTOOL = @LIBTOOL@
     462LIPO = @LIPO@
     463LN_S = @LN_S@
    406464LTLIBOBJS = @LTLIBOBJS@
    407 MACHINE_TYPE = @MACHINE_TYPE@
    408 MAINT = @MAINT@
     465LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
    409466MAKEINFO = @MAKEINFO@
     467MANIFEST_TOOL = @MANIFEST_TOOL@
    410468MKDIR_P = @MKDIR_P@
     469NM = @NM@
     470NMEDIT = @NMEDIT@
     471OBJDUMP = @OBJDUMP@
    411472OBJEXT = @OBJEXT@
     473OTOOL = @OTOOL@
     474OTOOL64 = @OTOOL64@
    412475PACKAGE = @PACKAGE@
    413476PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    419482PATH_SEPARATOR = @PATH_SEPARATOR@
    420483RANLIB = @RANLIB@
     484SED = @SED@
    421485SET_MAKE = @SET_MAKE@
    422486SHELL = @SHELL@
    423487STRIP = @STRIP@
     488TARGET_HOSTS = @TARGET_HOSTS@
    424489VERSION = @VERSION@
    425490YACC = @YACC@
     
    429494abs_top_builddir = @abs_top_builddir@
    430495abs_top_srcdir = @abs_top_srcdir@
     496ac_ct_AR = @ac_ct_AR@
    431497ac_ct_CC = @ac_ct_CC@
    432498ac_ct_CXX = @ac_ct_CXX@
     499ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    433500am__include = @am__include@
    434501am__leading_dot = @am__leading_dot@
     
    479546
    480547# create object files in directory with source files
    481 AUTOMAKE_OPTIONS = subdir-objects
    482 SRC = 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 \
     548AUTOMAKE_OPTIONS = foreign subdir-objects
     549ACLOCAL_AMFLAGS = -I automake
     550SRC = main.cc MakeLibCfa.cc CompilationState.cc $(SRC_AST) \
     551        $(SRC_CODEGEN) CodeGen/Generate.cc CodeGen/FixNames.cc \
     552        CodeTools/DeclStats.cc CodeTools/ResolvProtoDump.cc \
    486553        CodeTools/TrackLoc.cc Concurrency/Keywords.cc \
    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 \
     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
     571SRCDEMANGLE = 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) \
    530576        Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
    531         Tuples/Explode.cc Virtual/ExpandCasts.cc
    532 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
    533         ${cfa_cpplib_PROGRAMS}}
     577        Tuples/Explode.cc Tuples/Tuples.cc \
     578        Validate/HandleAttributes.cc Validate/FindSpecialDecls.cc
     579MAINTAINERCLEANFILES = ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}}
     580MOSTLYCLEANFILES = 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
     585SRC_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
     604SRC_CODEGEN = \
     605        CodeGen/CodeGenerator.cc \
     606        CodeGen/FixMain.cc \
     607        CodeGen/GenType.cc \
     608        CodeGen/OperatorTable.cc
     609
     610SRC_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
     621SRC_CONTROLSTRUCT = \
     622        ControlStruct/ForExprMutator.cc \
     623        ControlStruct/LabelFixer.cc \
     624        ControlStruct/LabelGenerator.cc \
     625        ControlStruct/MLEMutator.cc \
     626        ControlStruct/Mutate.cc
     627
    534628BUILT_SOURCES = Parser/parser.hh
    535629AM_YFLAGS = -d -t -v
    536 
    537 # Is there a way to use a variable for the directory names?
     630SRC_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
     656SRC_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
     664SRC_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
    538700
    539701# put into lib for now
    540 cfa_cpplibdir = ${CFA_LIBDIR}
    541 driver_cfa_cpp_SOURCES = ${SRC}
    542 driver_cfa_cpp_LDADD = -ldl                     # yywrap
    543 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -Wextra -DDEBUG_ALL -I${abs_top_srcdir}/src/include -DYY_NO_INPUT -O2 -g -std=c++14
    544 driver_cfa_cpp_LDFLAGS = -Xlinker -export-dynamic
     702cfa_cpplibdir = $(CFA_LIBDIR)
     703___driver_cfa_cpp_SOURCES = $(SRC)
     704___driver_cfa_cpp_LDADD = -ldl $(LIBPROFILER) $(LIBTCMALLOC)
     705AM_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)
     706AM_LDFLAGS = @HOST_FLAGS@ -Xlinker -export-dynamic
     707ARFLAGS = cr
     708demangler_SOURCES = SymTab/demangler.cc # test driver for the demangler, also useful as a sanity check that libdemangle.a is complete
     709demangler_LDADD = libdemangle.a -ldl                    # yywrap
     710noinst_LIBRARIES = $(LIBDEMANGLE)
     711EXTRA_LIBRARIES = libdemangle.a
     712libdemangle_a_SOURCES = $(SRCDEMANGLE)
    545713all: $(BUILT_SOURCES)
    546714        $(MAKE) $(AM_MAKEFLAGS) all-am
    547715
    548716.SUFFIXES:
    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)
     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)
    551719        @for dep in $?; do \
    552720          case '$(am__configure_deps)' in \
     
    568736            cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
    569737        esac;
    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):
     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):
    571739
    572740$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
    573741        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    574742
    575 $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
     743$(top_srcdir)/configure: $(am__configure_deps)
    576744        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    577 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
     745$(ACLOCAL_M4): $(am__aclocal_m4_deps)
    578746        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    579747$(am__aclocal_m4_deps):
     748
     749clean-noinstLIBRARIES:
     750        -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
     751AST/$(am__dirstamp):
     752        @$(MKDIR_P) AST
     753        @: > AST/$(am__dirstamp)
     754AST/$(DEPDIR)/$(am__dirstamp):
     755        @$(MKDIR_P) AST/$(DEPDIR)
     756        @: > AST/$(DEPDIR)/$(am__dirstamp)
     757AST/AssertAcyclic.$(OBJEXT): AST/$(am__dirstamp) \
     758        AST/$(DEPDIR)/$(am__dirstamp)
     759AST/Attribute.$(OBJEXT): AST/$(am__dirstamp) \
     760        AST/$(DEPDIR)/$(am__dirstamp)
     761AST/Convert.$(OBJEXT): AST/$(am__dirstamp) \
     762        AST/$(DEPDIR)/$(am__dirstamp)
     763AST/Decl.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     764AST/DeclReplacer.$(OBJEXT): AST/$(am__dirstamp) \
     765        AST/$(DEPDIR)/$(am__dirstamp)
     766AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     767AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
     768        AST/$(DEPDIR)/$(am__dirstamp)
     769AST/Init.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     770AST/LinkageSpec.$(OBJEXT): AST/$(am__dirstamp) \
     771        AST/$(DEPDIR)/$(am__dirstamp)
     772AST/Node.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     773AST/Pass.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     774AST/Print.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     775AST/Stmt.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     776AST/SymbolTable.$(OBJEXT): AST/$(am__dirstamp) \
     777        AST/$(DEPDIR)/$(am__dirstamp)
     778AST/Type.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     779AST/TypeEnvironment.$(OBJEXT): AST/$(am__dirstamp) \
     780        AST/$(DEPDIR)/$(am__dirstamp)
     781AST/TypeSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
     782        AST/$(DEPDIR)/$(am__dirstamp)
     783CodeGen/$(am__dirstamp):
     784        @$(MKDIR_P) CodeGen
     785        @: > CodeGen/$(am__dirstamp)
     786CodeGen/$(DEPDIR)/$(am__dirstamp):
     787        @$(MKDIR_P) CodeGen/$(DEPDIR)
     788        @: > CodeGen/$(DEPDIR)/$(am__dirstamp)
     789CodeGen/CodeGenerator.$(OBJEXT): CodeGen/$(am__dirstamp) \
     790        CodeGen/$(DEPDIR)/$(am__dirstamp)
     791CodeGen/FixMain.$(OBJEXT): CodeGen/$(am__dirstamp) \
     792        CodeGen/$(DEPDIR)/$(am__dirstamp)
     793CodeGen/GenType.$(OBJEXT): CodeGen/$(am__dirstamp) \
     794        CodeGen/$(DEPDIR)/$(am__dirstamp)
     795CodeGen/OperatorTable.$(OBJEXT): CodeGen/$(am__dirstamp) \
     796        CodeGen/$(DEPDIR)/$(am__dirstamp)
     797Concurrency/$(am__dirstamp):
     798        @$(MKDIR_P) Concurrency
     799        @: > Concurrency/$(am__dirstamp)
     800Concurrency/$(DEPDIR)/$(am__dirstamp):
     801        @$(MKDIR_P) Concurrency/$(DEPDIR)
     802        @: > Concurrency/$(DEPDIR)/$(am__dirstamp)
     803Concurrency/Keywords.$(OBJEXT): Concurrency/$(am__dirstamp) \
     804        Concurrency/$(DEPDIR)/$(am__dirstamp)
     805Common/$(am__dirstamp):
     806        @$(MKDIR_P) Common
     807        @: > Common/$(am__dirstamp)
     808Common/$(DEPDIR)/$(am__dirstamp):
     809        @$(MKDIR_P) Common/$(DEPDIR)
     810        @: > Common/$(DEPDIR)/$(am__dirstamp)
     811Common/Assert.$(OBJEXT): Common/$(am__dirstamp) \
     812        Common/$(DEPDIR)/$(am__dirstamp)
     813Common/Eval.$(OBJEXT): Common/$(am__dirstamp) \
     814        Common/$(DEPDIR)/$(am__dirstamp)
     815Common/PassVisitor.$(OBJEXT): Common/$(am__dirstamp) \
     816        Common/$(DEPDIR)/$(am__dirstamp)
     817Common/SemanticError.$(OBJEXT): Common/$(am__dirstamp) \
     818        Common/$(DEPDIR)/$(am__dirstamp)
     819Common/Stats/$(am__dirstamp):
     820        @$(MKDIR_P) Common/Stats
     821        @: > Common/Stats/$(am__dirstamp)
     822Common/Stats/$(DEPDIR)/$(am__dirstamp):
     823        @$(MKDIR_P) Common/Stats/$(DEPDIR)
     824        @: > Common/Stats/$(DEPDIR)/$(am__dirstamp)
     825Common/Stats/Counter.$(OBJEXT): Common/Stats/$(am__dirstamp) \
     826        Common/Stats/$(DEPDIR)/$(am__dirstamp)
     827Common/Stats/Heap.$(OBJEXT): Common/Stats/$(am__dirstamp) \
     828        Common/Stats/$(DEPDIR)/$(am__dirstamp)
     829Common/Stats/Stats.$(OBJEXT): Common/Stats/$(am__dirstamp) \
     830        Common/Stats/$(DEPDIR)/$(am__dirstamp)
     831Common/Stats/Time.$(OBJEXT): Common/Stats/$(am__dirstamp) \
     832        Common/Stats/$(DEPDIR)/$(am__dirstamp)
     833Common/UniqueName.$(OBJEXT): Common/$(am__dirstamp) \
     834        Common/$(DEPDIR)/$(am__dirstamp)
     835ControlStruct/$(am__dirstamp):
     836        @$(MKDIR_P) ControlStruct
     837        @: > ControlStruct/$(am__dirstamp)
     838ControlStruct/$(DEPDIR)/$(am__dirstamp):
     839        @$(MKDIR_P) ControlStruct/$(DEPDIR)
     840        @: > ControlStruct/$(DEPDIR)/$(am__dirstamp)
     841ControlStruct/ForExprMutator.$(OBJEXT): ControlStruct/$(am__dirstamp) \
     842        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     843ControlStruct/LabelFixer.$(OBJEXT): ControlStruct/$(am__dirstamp) \
     844        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     845ControlStruct/LabelGenerator.$(OBJEXT): ControlStruct/$(am__dirstamp) \
     846        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     847ControlStruct/MLEMutator.$(OBJEXT): ControlStruct/$(am__dirstamp) \
     848        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     849ControlStruct/Mutate.$(OBJEXT): ControlStruct/$(am__dirstamp) \
     850        ControlStruct/$(DEPDIR)/$(am__dirstamp)
     851GenPoly/$(am__dirstamp):
     852        @$(MKDIR_P) GenPoly
     853        @: > GenPoly/$(am__dirstamp)
     854GenPoly/$(DEPDIR)/$(am__dirstamp):
     855        @$(MKDIR_P) GenPoly/$(DEPDIR)
     856        @: > GenPoly/$(DEPDIR)/$(am__dirstamp)
     857GenPoly/GenPoly.$(OBJEXT): GenPoly/$(am__dirstamp) \
     858        GenPoly/$(DEPDIR)/$(am__dirstamp)
     859GenPoly/Lvalue.$(OBJEXT): GenPoly/$(am__dirstamp) \
     860        GenPoly/$(DEPDIR)/$(am__dirstamp)
     861InitTweak/$(am__dirstamp):
     862        @$(MKDIR_P) InitTweak
     863        @: > InitTweak/$(am__dirstamp)
     864InitTweak/$(DEPDIR)/$(am__dirstamp):
     865        @$(MKDIR_P) InitTweak/$(DEPDIR)
     866        @: > InitTweak/$(DEPDIR)/$(am__dirstamp)
     867InitTweak/GenInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
     868        InitTweak/$(DEPDIR)/$(am__dirstamp)
     869InitTweak/InitTweak.$(OBJEXT): InitTweak/$(am__dirstamp) \
     870        InitTweak/$(DEPDIR)/$(am__dirstamp)
     871Parser/$(am__dirstamp):
     872        @$(MKDIR_P) Parser
     873        @: > Parser/$(am__dirstamp)
     874Parser/$(DEPDIR)/$(am__dirstamp):
     875        @$(MKDIR_P) Parser/$(DEPDIR)
     876        @: > Parser/$(DEPDIR)/$(am__dirstamp)
     877Parser/LinkageSpec.$(OBJEXT): Parser/$(am__dirstamp) \
     878        Parser/$(DEPDIR)/$(am__dirstamp)
     879ResolvExpr/$(am__dirstamp):
     880        @$(MKDIR_P) ResolvExpr
     881        @: > ResolvExpr/$(am__dirstamp)
     882ResolvExpr/$(DEPDIR)/$(am__dirstamp):
     883        @$(MKDIR_P) ResolvExpr/$(DEPDIR)
     884        @: > ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     885ResolvExpr/AdjustExprType.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     886        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     887ResolvExpr/Alternative.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     888        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     889ResolvExpr/AlternativeFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     890        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     891ResolvExpr/Candidate.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     892        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     893ResolvExpr/CandidateFinder.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     894        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     895ResolvExpr/CastCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     896        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     897ResolvExpr/CommonType.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     898        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     899ResolvExpr/ConversionCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     900        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     901ResolvExpr/CurrentObject.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     902        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     903ResolvExpr/ExplodedActual.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     904        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     905ResolvExpr/ExplodedArg.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     906        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     907ResolvExpr/FindOpenVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     908        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     909ResolvExpr/Occurs.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     910        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     911ResolvExpr/PolyCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     912        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     913ResolvExpr/PtrsAssignable.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     914        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     915ResolvExpr/PtrsCastable.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     916        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     917ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     918        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     919ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     920        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     921ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     922        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     923ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     924        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     925ResolvExpr/SatisfyAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     926        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     927ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     928        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     929ResolvExpr/TypeEnvironment.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     930        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     931ResolvExpr/Unify.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     932        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     933SymTab/$(am__dirstamp):
     934        @$(MKDIR_P) SymTab
     935        @: > SymTab/$(am__dirstamp)
     936SymTab/$(DEPDIR)/$(am__dirstamp):
     937        @$(MKDIR_P) SymTab/$(DEPDIR)
     938        @: > SymTab/$(DEPDIR)/$(am__dirstamp)
     939SymTab/Autogen.$(OBJEXT): SymTab/$(am__dirstamp) \
     940        SymTab/$(DEPDIR)/$(am__dirstamp)
     941SymTab/FixFunction.$(OBJEXT): SymTab/$(am__dirstamp) \
     942        SymTab/$(DEPDIR)/$(am__dirstamp)
     943SymTab/Indexer.$(OBJEXT): SymTab/$(am__dirstamp) \
     944        SymTab/$(DEPDIR)/$(am__dirstamp)
     945SymTab/Mangler.$(OBJEXT): SymTab/$(am__dirstamp) \
     946        SymTab/$(DEPDIR)/$(am__dirstamp)
     947SymTab/ManglerCommon.$(OBJEXT): SymTab/$(am__dirstamp) \
     948        SymTab/$(DEPDIR)/$(am__dirstamp)
     949SymTab/Validate.$(OBJEXT): SymTab/$(am__dirstamp) \
     950        SymTab/$(DEPDIR)/$(am__dirstamp)
     951SymTab/Demangle.$(OBJEXT): SymTab/$(am__dirstamp) \
     952        SymTab/$(DEPDIR)/$(am__dirstamp)
     953SynTree/$(am__dirstamp):
     954        @$(MKDIR_P) SynTree
     955        @: > SynTree/$(am__dirstamp)
     956SynTree/$(DEPDIR)/$(am__dirstamp):
     957        @$(MKDIR_P) SynTree/$(DEPDIR)
     958        @: > SynTree/$(DEPDIR)/$(am__dirstamp)
     959SynTree/Type.$(OBJEXT): SynTree/$(am__dirstamp) \
     960        SynTree/$(DEPDIR)/$(am__dirstamp)
     961SynTree/VoidType.$(OBJEXT): SynTree/$(am__dirstamp) \
     962        SynTree/$(DEPDIR)/$(am__dirstamp)
     963SynTree/BasicType.$(OBJEXT): SynTree/$(am__dirstamp) \
     964        SynTree/$(DEPDIR)/$(am__dirstamp)
     965SynTree/PointerType.$(OBJEXT): SynTree/$(am__dirstamp) \
     966        SynTree/$(DEPDIR)/$(am__dirstamp)
     967SynTree/ArrayType.$(OBJEXT): SynTree/$(am__dirstamp) \
     968        SynTree/$(DEPDIR)/$(am__dirstamp)
     969SynTree/ReferenceType.$(OBJEXT): SynTree/$(am__dirstamp) \
     970        SynTree/$(DEPDIR)/$(am__dirstamp)
     971SynTree/FunctionType.$(OBJEXT): SynTree/$(am__dirstamp) \
     972        SynTree/$(DEPDIR)/$(am__dirstamp)
     973SynTree/ReferenceToType.$(OBJEXT): SynTree/$(am__dirstamp) \
     974        SynTree/$(DEPDIR)/$(am__dirstamp)
     975SynTree/TupleType.$(OBJEXT): SynTree/$(am__dirstamp) \
     976        SynTree/$(DEPDIR)/$(am__dirstamp)
     977SynTree/TypeofType.$(OBJEXT): SynTree/$(am__dirstamp) \
     978        SynTree/$(DEPDIR)/$(am__dirstamp)
     979SynTree/AttrType.$(OBJEXT): SynTree/$(am__dirstamp) \
     980        SynTree/$(DEPDIR)/$(am__dirstamp)
     981SynTree/VarArgsType.$(OBJEXT): SynTree/$(am__dirstamp) \
     982        SynTree/$(DEPDIR)/$(am__dirstamp)
     983SynTree/ZeroOneType.$(OBJEXT): SynTree/$(am__dirstamp) \
     984        SynTree/$(DEPDIR)/$(am__dirstamp)
     985SynTree/Constant.$(OBJEXT): SynTree/$(am__dirstamp) \
     986        SynTree/$(DEPDIR)/$(am__dirstamp)
     987SynTree/Expression.$(OBJEXT): SynTree/$(am__dirstamp) \
     988        SynTree/$(DEPDIR)/$(am__dirstamp)
     989SynTree/TupleExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     990        SynTree/$(DEPDIR)/$(am__dirstamp)
     991SynTree/CommaExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     992        SynTree/$(DEPDIR)/$(am__dirstamp)
     993SynTree/TypeExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     994        SynTree/$(DEPDIR)/$(am__dirstamp)
     995SynTree/ApplicationExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     996        SynTree/$(DEPDIR)/$(am__dirstamp)
     997SynTree/AddressExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
     998        SynTree/$(DEPDIR)/$(am__dirstamp)
     999SynTree/Statement.$(OBJEXT): SynTree/$(am__dirstamp) \
     1000        SynTree/$(DEPDIR)/$(am__dirstamp)
     1001SynTree/CompoundStmt.$(OBJEXT): SynTree/$(am__dirstamp) \
     1002        SynTree/$(DEPDIR)/$(am__dirstamp)
     1003SynTree/DeclStmt.$(OBJEXT): SynTree/$(am__dirstamp) \
     1004        SynTree/$(DEPDIR)/$(am__dirstamp)
     1005SynTree/Declaration.$(OBJEXT): SynTree/$(am__dirstamp) \
     1006        SynTree/$(DEPDIR)/$(am__dirstamp)
     1007SynTree/DeclarationWithType.$(OBJEXT): SynTree/$(am__dirstamp) \
     1008        SynTree/$(DEPDIR)/$(am__dirstamp)
     1009SynTree/ObjectDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
     1010        SynTree/$(DEPDIR)/$(am__dirstamp)
     1011SynTree/FunctionDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
     1012        SynTree/$(DEPDIR)/$(am__dirstamp)
     1013SynTree/AggregateDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
     1014        SynTree/$(DEPDIR)/$(am__dirstamp)
     1015SynTree/NamedTypeDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
     1016        SynTree/$(DEPDIR)/$(am__dirstamp)
     1017SynTree/TypeDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
     1018        SynTree/$(DEPDIR)/$(am__dirstamp)
     1019SynTree/Initializer.$(OBJEXT): SynTree/$(am__dirstamp) \
     1020        SynTree/$(DEPDIR)/$(am__dirstamp)
     1021SynTree/TypeSubstitution.$(OBJEXT): SynTree/$(am__dirstamp) \
     1022        SynTree/$(DEPDIR)/$(am__dirstamp)
     1023SynTree/Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
     1024        SynTree/$(DEPDIR)/$(am__dirstamp)
     1025SynTree/DeclReplacer.$(OBJEXT): SynTree/$(am__dirstamp) \
     1026        SynTree/$(DEPDIR)/$(am__dirstamp)
     1027Tuples/$(am__dirstamp):
     1028        @$(MKDIR_P) Tuples
     1029        @: > Tuples/$(am__dirstamp)
     1030Tuples/$(DEPDIR)/$(am__dirstamp):
     1031        @$(MKDIR_P) Tuples/$(DEPDIR)
     1032        @: > Tuples/$(DEPDIR)/$(am__dirstamp)
     1033Tuples/TupleAssignment.$(OBJEXT): Tuples/$(am__dirstamp) \
     1034        Tuples/$(DEPDIR)/$(am__dirstamp)
     1035Tuples/TupleExpansion.$(OBJEXT): Tuples/$(am__dirstamp) \
     1036        Tuples/$(DEPDIR)/$(am__dirstamp)
     1037Tuples/Explode.$(OBJEXT): Tuples/$(am__dirstamp) \
     1038        Tuples/$(DEPDIR)/$(am__dirstamp)
     1039Tuples/Tuples.$(OBJEXT): Tuples/$(am__dirstamp) \
     1040        Tuples/$(DEPDIR)/$(am__dirstamp)
     1041Validate/$(am__dirstamp):
     1042        @$(MKDIR_P) Validate
     1043        @: > Validate/$(am__dirstamp)
     1044Validate/$(DEPDIR)/$(am__dirstamp):
     1045        @$(MKDIR_P) Validate/$(DEPDIR)
     1046        @: > Validate/$(DEPDIR)/$(am__dirstamp)
     1047Validate/HandleAttributes.$(OBJEXT): Validate/$(am__dirstamp) \
     1048        Validate/$(DEPDIR)/$(am__dirstamp)
     1049Validate/FindSpecialDecls.$(OBJEXT): Validate/$(am__dirstamp) \
     1050        Validate/$(DEPDIR)/$(am__dirstamp)
     1051
     1052libdemangle.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
    5801056install-cfa_cpplibPROGRAMS: $(cfa_cpplib_PROGRAMS)
    5811057        @$(NORMAL_INSTALL)
     
    5881064        sed 's/$(EXEEXT)$$//' | \
    5891065        while read p p1; do if test -f $$p \
     1066         || test -f $$p1 \
    5901067          ; then echo "$$p"; echo "$$p"; else :; fi; \
    5911068        done | \
     
    6021079            if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
    6031080            test -z "$$files" || { \
    604               echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cfa_cpplibdir)$$dir'"; \
    605               $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cfa_cpplibdir)$$dir" || exit $$?; \
     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 $$?; \
    6061083            } \
    6071084        ; done
     
    6191096
    6201097clean-cfa_cpplibPROGRAMS:
    621         -test -z "$(cfa_cpplib_PROGRAMS)" || rm -f $(cfa_cpplib_PROGRAMS)
    622 CodeGen/$(am__dirstamp):
    623         @$(MKDIR_P) CodeGen
    624         @: > CodeGen/$(am__dirstamp)
    625 CodeGen/$(DEPDIR)/$(am__dirstamp):
    626         @$(MKDIR_P) CodeGen/$(DEPDIR)
    627         @: > CodeGen/$(DEPDIR)/$(am__dirstamp)
    628 CodeGen/driver_cfa_cpp-Generate.$(OBJEXT): CodeGen/$(am__dirstamp) \
     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
     1105CodeGen/Generate.$(OBJEXT): CodeGen/$(am__dirstamp) \
    6291106        CodeGen/$(DEPDIR)/$(am__dirstamp)
    630 CodeGen/driver_cfa_cpp-CodeGenerator.$(OBJEXT):  \
    631         CodeGen/$(am__dirstamp) CodeGen/$(DEPDIR)/$(am__dirstamp)
    632 CodeGen/driver_cfa_cpp-GenType.$(OBJEXT): CodeGen/$(am__dirstamp) \
     1107CodeGen/FixNames.$(OBJEXT): CodeGen/$(am__dirstamp) \
    6331108        CodeGen/$(DEPDIR)/$(am__dirstamp)
    634 CodeGen/driver_cfa_cpp-FixNames.$(OBJEXT): CodeGen/$(am__dirstamp) \
    635         CodeGen/$(DEPDIR)/$(am__dirstamp)
    636 CodeGen/driver_cfa_cpp-FixMain.$(OBJEXT): CodeGen/$(am__dirstamp) \
    637         CodeGen/$(DEPDIR)/$(am__dirstamp)
    638 CodeGen/driver_cfa_cpp-OperatorTable.$(OBJEXT):  \
    639         CodeGen/$(am__dirstamp) CodeGen/$(DEPDIR)/$(am__dirstamp)
    6401109CodeTools/$(am__dirstamp):
    6411110        @$(MKDIR_P) CodeTools
     
    6441113        @$(MKDIR_P) CodeTools/$(DEPDIR)
    6451114        @: > CodeTools/$(DEPDIR)/$(am__dirstamp)
    646 CodeTools/driver_cfa_cpp-DeclStats.$(OBJEXT):  \
    647         CodeTools/$(am__dirstamp) CodeTools/$(DEPDIR)/$(am__dirstamp)
    648 CodeTools/driver_cfa_cpp-TrackLoc.$(OBJEXT):  \
    649         CodeTools/$(am__dirstamp) CodeTools/$(DEPDIR)/$(am__dirstamp)
    650 Concurrency/$(am__dirstamp):
    651         @$(MKDIR_P) Concurrency
    652         @: > Concurrency/$(am__dirstamp)
    653 Concurrency/$(DEPDIR)/$(am__dirstamp):
    654         @$(MKDIR_P) Concurrency/$(DEPDIR)
    655         @: > Concurrency/$(DEPDIR)/$(am__dirstamp)
    656 Concurrency/driver_cfa_cpp-Keywords.$(OBJEXT):  \
    657         Concurrency/$(am__dirstamp) \
     1115CodeTools/DeclStats.$(OBJEXT): CodeTools/$(am__dirstamp) \
     1116        CodeTools/$(DEPDIR)/$(am__dirstamp)
     1117CodeTools/ResolvProtoDump.$(OBJEXT): CodeTools/$(am__dirstamp) \
     1118        CodeTools/$(DEPDIR)/$(am__dirstamp)
     1119CodeTools/TrackLoc.$(OBJEXT): CodeTools/$(am__dirstamp) \
     1120        CodeTools/$(DEPDIR)/$(am__dirstamp)
     1121Concurrency/Waitfor.$(OBJEXT): Concurrency/$(am__dirstamp) \
    6581122        Concurrency/$(DEPDIR)/$(am__dirstamp)
    659 Concurrency/driver_cfa_cpp-Waitfor.$(OBJEXT):  \
    660         Concurrency/$(am__dirstamp) \
    661         Concurrency/$(DEPDIR)/$(am__dirstamp)
    662 Common/$(am__dirstamp):
    663         @$(MKDIR_P) Common
    664         @: > Common/$(am__dirstamp)
    665 Common/$(DEPDIR)/$(am__dirstamp):
    666         @$(MKDIR_P) Common/$(DEPDIR)
    667         @: > Common/$(DEPDIR)/$(am__dirstamp)
    668 Common/driver_cfa_cpp-SemanticError.$(OBJEXT): Common/$(am__dirstamp) \
     1123Common/DebugMalloc.$(OBJEXT): Common/$(am__dirstamp) \
    6691124        Common/$(DEPDIR)/$(am__dirstamp)
    670 Common/driver_cfa_cpp-UniqueName.$(OBJEXT): Common/$(am__dirstamp) \
    671         Common/$(DEPDIR)/$(am__dirstamp)
    672 Common/driver_cfa_cpp-DebugMalloc.$(OBJEXT): Common/$(am__dirstamp) \
    673         Common/$(DEPDIR)/$(am__dirstamp)
    674 Common/driver_cfa_cpp-Assert.$(OBJEXT): Common/$(am__dirstamp) \
    675         Common/$(DEPDIR)/$(am__dirstamp)
    676 Common/driver_cfa_cpp-Heap.$(OBJEXT): Common/$(am__dirstamp) \
    677         Common/$(DEPDIR)/$(am__dirstamp)
    678 ControlStruct/$(am__dirstamp):
    679         @$(MKDIR_P) ControlStruct
    680         @: > ControlStruct/$(am__dirstamp)
    681 ControlStruct/$(DEPDIR)/$(am__dirstamp):
    682         @$(MKDIR_P) ControlStruct/$(DEPDIR)
    683         @: > ControlStruct/$(DEPDIR)/$(am__dirstamp)
    684 ControlStruct/driver_cfa_cpp-LabelGenerator.$(OBJEXT):  \
     1125ControlStruct/ExceptTranslate.$(OBJEXT):  \
    6851126        ControlStruct/$(am__dirstamp) \
    6861127        ControlStruct/$(DEPDIR)/$(am__dirstamp)
    687 ControlStruct/driver_cfa_cpp-LabelFixer.$(OBJEXT):  \
    688         ControlStruct/$(am__dirstamp) \
    689         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    690 ControlStruct/driver_cfa_cpp-MLEMutator.$(OBJEXT):  \
    691         ControlStruct/$(am__dirstamp) \
    692         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    693 ControlStruct/driver_cfa_cpp-Mutate.$(OBJEXT):  \
    694         ControlStruct/$(am__dirstamp) \
    695         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    696 ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT):  \
    697         ControlStruct/$(am__dirstamp) \
    698         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    699 ControlStruct/driver_cfa_cpp-ExceptTranslate.$(OBJEXT):  \
    700         ControlStruct/$(am__dirstamp) \
    701         ControlStruct/$(DEPDIR)/$(am__dirstamp)
    702 GenPoly/$(am__dirstamp):
    703         @$(MKDIR_P) GenPoly
    704         @: > GenPoly/$(am__dirstamp)
    705 GenPoly/$(DEPDIR)/$(am__dirstamp):
    706         @$(MKDIR_P) GenPoly/$(DEPDIR)
    707         @: > GenPoly/$(DEPDIR)/$(am__dirstamp)
    708 GenPoly/driver_cfa_cpp-Box.$(OBJEXT): GenPoly/$(am__dirstamp) \
     1128GenPoly/Box.$(OBJEXT): GenPoly/$(am__dirstamp) \
    7091129        GenPoly/$(DEPDIR)/$(am__dirstamp)
    710 GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT): GenPoly/$(am__dirstamp) \
     1130GenPoly/ScrubTyVars.$(OBJEXT): GenPoly/$(am__dirstamp) \
    7111131        GenPoly/$(DEPDIR)/$(am__dirstamp)
    712 GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT): GenPoly/$(am__dirstamp) \
     1132GenPoly/Specialize.$(OBJEXT): GenPoly/$(am__dirstamp) \
    7131133        GenPoly/$(DEPDIR)/$(am__dirstamp)
    714 GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT): GenPoly/$(am__dirstamp) \
     1134GenPoly/FindFunction.$(OBJEXT): GenPoly/$(am__dirstamp) \
    7151135        GenPoly/$(DEPDIR)/$(am__dirstamp)
    716 GenPoly/driver_cfa_cpp-Specialize.$(OBJEXT): GenPoly/$(am__dirstamp) \
     1136GenPoly/InstantiateGeneric.$(OBJEXT): GenPoly/$(am__dirstamp) \
    7171137        GenPoly/$(DEPDIR)/$(am__dirstamp)
    718 GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT):  \
    719         GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
    720 GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT):  \
    721         GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
    722 InitTweak/$(am__dirstamp):
    723         @$(MKDIR_P) InitTweak
    724         @: > InitTweak/$(am__dirstamp)
    725 InitTweak/$(DEPDIR)/$(am__dirstamp):
    726         @$(MKDIR_P) InitTweak/$(DEPDIR)
    727         @: > InitTweak/$(DEPDIR)/$(am__dirstamp)
    728 InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
     1138InitTweak/FixInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
    7291139        InitTweak/$(DEPDIR)/$(am__dirstamp)
    730 InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
     1140InitTweak/FixGlobalInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
    7311141        InitTweak/$(DEPDIR)/$(am__dirstamp)
    732 InitTweak/driver_cfa_cpp-FixGlobalInit.$(OBJEXT):  \
    733         InitTweak/$(am__dirstamp) InitTweak/$(DEPDIR)/$(am__dirstamp)
    734 InitTweak/driver_cfa_cpp-InitTweak.$(OBJEXT):  \
    735         InitTweak/$(am__dirstamp) InitTweak/$(DEPDIR)/$(am__dirstamp)
    7361142Parser/parser.hh: Parser/parser.cc
    7371143        @if test ! -f $@; then rm -f Parser/parser.cc; else :; fi
    7381144        @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) Parser/parser.cc; else :; fi
    739 Parser/$(am__dirstamp):
    740         @$(MKDIR_P) Parser
    741         @: > Parser/$(am__dirstamp)
    742 Parser/$(DEPDIR)/$(am__dirstamp):
    743         @$(MKDIR_P) Parser/$(DEPDIR)
    744         @: > Parser/$(DEPDIR)/$(am__dirstamp)
    745 Parser/driver_cfa_cpp-parser.$(OBJEXT): Parser/$(am__dirstamp) \
     1145Parser/parser.$(OBJEXT): Parser/$(am__dirstamp) \
    7461146        Parser/$(DEPDIR)/$(am__dirstamp)
    747 Parser/driver_cfa_cpp-lex.$(OBJEXT): Parser/$(am__dirstamp) \
     1147Parser/lex.$(OBJEXT): Parser/$(am__dirstamp) \
    7481148        Parser/$(DEPDIR)/$(am__dirstamp)
    749 Parser/driver_cfa_cpp-TypedefTable.$(OBJEXT): Parser/$(am__dirstamp) \
     1149Parser/TypedefTable.$(OBJEXT): Parser/$(am__dirstamp) \
    7501150        Parser/$(DEPDIR)/$(am__dirstamp)
    751 Parser/driver_cfa_cpp-ParseNode.$(OBJEXT): Parser/$(am__dirstamp) \
     1151Parser/ParseNode.$(OBJEXT): Parser/$(am__dirstamp) \
    7521152        Parser/$(DEPDIR)/$(am__dirstamp)
    753 Parser/driver_cfa_cpp-DeclarationNode.$(OBJEXT):  \
    754         Parser/$(am__dirstamp) Parser/$(DEPDIR)/$(am__dirstamp)
    755 Parser/driver_cfa_cpp-ExpressionNode.$(OBJEXT):  \
    756         Parser/$(am__dirstamp) Parser/$(DEPDIR)/$(am__dirstamp)
    757 Parser/driver_cfa_cpp-StatementNode.$(OBJEXT): Parser/$(am__dirstamp) \
     1153Parser/DeclarationNode.$(OBJEXT): Parser/$(am__dirstamp) \
    7581154        Parser/$(DEPDIR)/$(am__dirstamp)
    759 Parser/driver_cfa_cpp-InitializerNode.$(OBJEXT):  \
    760         Parser/$(am__dirstamp) Parser/$(DEPDIR)/$(am__dirstamp)
    761 Parser/driver_cfa_cpp-TypeData.$(OBJEXT): Parser/$(am__dirstamp) \
     1155Parser/ExpressionNode.$(OBJEXT): Parser/$(am__dirstamp) \
    7621156        Parser/$(DEPDIR)/$(am__dirstamp)
    763 Parser/driver_cfa_cpp-LinkageSpec.$(OBJEXT): Parser/$(am__dirstamp) \
     1157Parser/StatementNode.$(OBJEXT): Parser/$(am__dirstamp) \
    7641158        Parser/$(DEPDIR)/$(am__dirstamp)
    765 Parser/driver_cfa_cpp-parserutility.$(OBJEXT): Parser/$(am__dirstamp) \
     1159Parser/InitializerNode.$(OBJEXT): Parser/$(am__dirstamp) \
    7661160        Parser/$(DEPDIR)/$(am__dirstamp)
    767 ResolvExpr/$(am__dirstamp):
    768         @$(MKDIR_P) ResolvExpr
    769         @: > ResolvExpr/$(am__dirstamp)
    770 ResolvExpr/$(DEPDIR)/$(am__dirstamp):
    771         @$(MKDIR_P) ResolvExpr/$(DEPDIR)
    772         @: > ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    773 ResolvExpr/driver_cfa_cpp-AlternativeFinder.$(OBJEXT):  \
    774         ResolvExpr/$(am__dirstamp) \
    775         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    776 ResolvExpr/driver_cfa_cpp-Alternative.$(OBJEXT):  \
    777         ResolvExpr/$(am__dirstamp) \
    778         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    779 ResolvExpr/driver_cfa_cpp-Unify.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    780         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    781 ResolvExpr/driver_cfa_cpp-PtrsAssignable.$(OBJEXT):  \
    782         ResolvExpr/$(am__dirstamp) \
    783         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    784 ResolvExpr/driver_cfa_cpp-CommonType.$(OBJEXT):  \
    785         ResolvExpr/$(am__dirstamp) \
    786         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    787 ResolvExpr/driver_cfa_cpp-ConversionCost.$(OBJEXT):  \
    788         ResolvExpr/$(am__dirstamp) \
    789         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    790 ResolvExpr/driver_cfa_cpp-CastCost.$(OBJEXT):  \
    791         ResolvExpr/$(am__dirstamp) \
    792         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    793 ResolvExpr/driver_cfa_cpp-PtrsCastable.$(OBJEXT):  \
    794         ResolvExpr/$(am__dirstamp) \
    795         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    796 ResolvExpr/driver_cfa_cpp-AdjustExprType.$(OBJEXT):  \
    797         ResolvExpr/$(am__dirstamp) \
    798         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    799 ResolvExpr/driver_cfa_cpp-AlternativePrinter.$(OBJEXT):  \
    800         ResolvExpr/$(am__dirstamp) \
    801         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    802 ResolvExpr/driver_cfa_cpp-Resolver.$(OBJEXT):  \
    803         ResolvExpr/$(am__dirstamp) \
    804         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    805 ResolvExpr/driver_cfa_cpp-ResolveTypeof.$(OBJEXT):  \
    806         ResolvExpr/$(am__dirstamp) \
    807         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    808 ResolvExpr/driver_cfa_cpp-RenameVars.$(OBJEXT):  \
    809         ResolvExpr/$(am__dirstamp) \
    810         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    811 ResolvExpr/driver_cfa_cpp-FindOpenVars.$(OBJEXT):  \
    812         ResolvExpr/$(am__dirstamp) \
    813         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    814 ResolvExpr/driver_cfa_cpp-PolyCost.$(OBJEXT):  \
    815         ResolvExpr/$(am__dirstamp) \
    816         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    817 ResolvExpr/driver_cfa_cpp-Occurs.$(OBJEXT):  \
    818         ResolvExpr/$(am__dirstamp) \
    819         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    820 ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT):  \
    821         ResolvExpr/$(am__dirstamp) \
    822         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    823 ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT):  \
    824         ResolvExpr/$(am__dirstamp) \
    825         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    826 ResolvExpr/driver_cfa_cpp-ExplodedActual.$(OBJEXT):  \
    827         ResolvExpr/$(am__dirstamp) \
    828         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    829 SymTab/$(am__dirstamp):
    830         @$(MKDIR_P) SymTab
    831         @: > SymTab/$(am__dirstamp)
    832 SymTab/$(DEPDIR)/$(am__dirstamp):
    833         @$(MKDIR_P) SymTab/$(DEPDIR)
    834         @: > SymTab/$(DEPDIR)/$(am__dirstamp)
    835 SymTab/driver_cfa_cpp-Indexer.$(OBJEXT): SymTab/$(am__dirstamp) \
    836         SymTab/$(DEPDIR)/$(am__dirstamp)
    837 SymTab/driver_cfa_cpp-Mangler.$(OBJEXT): SymTab/$(am__dirstamp) \
    838         SymTab/$(DEPDIR)/$(am__dirstamp)
    839 SymTab/driver_cfa_cpp-Validate.$(OBJEXT): SymTab/$(am__dirstamp) \
    840         SymTab/$(DEPDIR)/$(am__dirstamp)
    841 SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT): SymTab/$(am__dirstamp) \
    842         SymTab/$(DEPDIR)/$(am__dirstamp)
    843 SymTab/driver_cfa_cpp-Autogen.$(OBJEXT): SymTab/$(am__dirstamp) \
    844         SymTab/$(DEPDIR)/$(am__dirstamp)
    845 SynTree/$(am__dirstamp):
    846         @$(MKDIR_P) SynTree
    847         @: > SynTree/$(am__dirstamp)
    848 SynTree/$(DEPDIR)/$(am__dirstamp):
    849         @$(MKDIR_P) SynTree/$(DEPDIR)
    850         @: > SynTree/$(DEPDIR)/$(am__dirstamp)
    851 SynTree/driver_cfa_cpp-Type.$(OBJEXT): SynTree/$(am__dirstamp) \
    852         SynTree/$(DEPDIR)/$(am__dirstamp)
    853 SynTree/driver_cfa_cpp-VoidType.$(OBJEXT): SynTree/$(am__dirstamp) \
    854         SynTree/$(DEPDIR)/$(am__dirstamp)
    855 SynTree/driver_cfa_cpp-BasicType.$(OBJEXT): SynTree/$(am__dirstamp) \
    856         SynTree/$(DEPDIR)/$(am__dirstamp)
    857 SynTree/driver_cfa_cpp-PointerType.$(OBJEXT): SynTree/$(am__dirstamp) \
    858         SynTree/$(DEPDIR)/$(am__dirstamp)
    859 SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT): SynTree/$(am__dirstamp) \
    860         SynTree/$(DEPDIR)/$(am__dirstamp)
    861 SynTree/driver_cfa_cpp-ReferenceType.$(OBJEXT):  \
    862         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    863 SynTree/driver_cfa_cpp-FunctionType.$(OBJEXT):  \
    864         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    865 SynTree/driver_cfa_cpp-ReferenceToType.$(OBJEXT):  \
    866         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    867 SynTree/driver_cfa_cpp-TupleType.$(OBJEXT): SynTree/$(am__dirstamp) \
    868         SynTree/$(DEPDIR)/$(am__dirstamp)
    869 SynTree/driver_cfa_cpp-TypeofType.$(OBJEXT): SynTree/$(am__dirstamp) \
    870         SynTree/$(DEPDIR)/$(am__dirstamp)
    871 SynTree/driver_cfa_cpp-AttrType.$(OBJEXT): SynTree/$(am__dirstamp) \
    872         SynTree/$(DEPDIR)/$(am__dirstamp)
    873 SynTree/driver_cfa_cpp-VarArgsType.$(OBJEXT): SynTree/$(am__dirstamp) \
    874         SynTree/$(DEPDIR)/$(am__dirstamp)
    875 SynTree/driver_cfa_cpp-ZeroOneType.$(OBJEXT): SynTree/$(am__dirstamp) \
    876         SynTree/$(DEPDIR)/$(am__dirstamp)
    877 SynTree/driver_cfa_cpp-Constant.$(OBJEXT): SynTree/$(am__dirstamp) \
    878         SynTree/$(DEPDIR)/$(am__dirstamp)
    879 SynTree/driver_cfa_cpp-Expression.$(OBJEXT): SynTree/$(am__dirstamp) \
    880         SynTree/$(DEPDIR)/$(am__dirstamp)
    881 SynTree/driver_cfa_cpp-TupleExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    882         SynTree/$(DEPDIR)/$(am__dirstamp)
    883 SynTree/driver_cfa_cpp-CommaExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    884         SynTree/$(DEPDIR)/$(am__dirstamp)
    885 SynTree/driver_cfa_cpp-TypeExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    886         SynTree/$(DEPDIR)/$(am__dirstamp)
    887 SynTree/driver_cfa_cpp-ApplicationExpr.$(OBJEXT):  \
    888         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    889 SynTree/driver_cfa_cpp-AddressExpr.$(OBJEXT): SynTree/$(am__dirstamp) \
    890         SynTree/$(DEPDIR)/$(am__dirstamp)
    891 SynTree/driver_cfa_cpp-Statement.$(OBJEXT): SynTree/$(am__dirstamp) \
    892         SynTree/$(DEPDIR)/$(am__dirstamp)
    893 SynTree/driver_cfa_cpp-CompoundStmt.$(OBJEXT):  \
    894         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    895 SynTree/driver_cfa_cpp-DeclStmt.$(OBJEXT): SynTree/$(am__dirstamp) \
    896         SynTree/$(DEPDIR)/$(am__dirstamp)
    897 SynTree/driver_cfa_cpp-Declaration.$(OBJEXT): SynTree/$(am__dirstamp) \
    898         SynTree/$(DEPDIR)/$(am__dirstamp)
    899 SynTree/driver_cfa_cpp-DeclarationWithType.$(OBJEXT):  \
    900         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    901 SynTree/driver_cfa_cpp-ObjectDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
    902         SynTree/$(DEPDIR)/$(am__dirstamp)
    903 SynTree/driver_cfa_cpp-FunctionDecl.$(OBJEXT):  \
    904         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    905 SynTree/driver_cfa_cpp-AggregateDecl.$(OBJEXT):  \
    906         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    907 SynTree/driver_cfa_cpp-NamedTypeDecl.$(OBJEXT):  \
    908         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    909 SynTree/driver_cfa_cpp-TypeDecl.$(OBJEXT): SynTree/$(am__dirstamp) \
    910         SynTree/$(DEPDIR)/$(am__dirstamp)
    911 SynTree/driver_cfa_cpp-Initializer.$(OBJEXT): SynTree/$(am__dirstamp) \
    912         SynTree/$(DEPDIR)/$(am__dirstamp)
    913 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT):  \
    914         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    915 SynTree/driver_cfa_cpp-Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
    916         SynTree/$(DEPDIR)/$(am__dirstamp)
    917 SynTree/driver_cfa_cpp-DeclReplacer.$(OBJEXT):  \
    918         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    919 Tuples/$(am__dirstamp):
    920         @$(MKDIR_P) Tuples
    921         @: > Tuples/$(am__dirstamp)
    922 Tuples/$(DEPDIR)/$(am__dirstamp):
    923         @$(MKDIR_P) Tuples/$(DEPDIR)
    924         @: > Tuples/$(DEPDIR)/$(am__dirstamp)
    925 Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT):  \
    926         Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
    927 Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT):  \
    928         Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
    929 Tuples/driver_cfa_cpp-Explode.$(OBJEXT): Tuples/$(am__dirstamp) \
    930         Tuples/$(DEPDIR)/$(am__dirstamp)
     1161Parser/TypeData.$(OBJEXT): Parser/$(am__dirstamp) \
     1162        Parser/$(DEPDIR)/$(am__dirstamp)
     1163Parser/parserutility.$(OBJEXT): Parser/$(am__dirstamp) \
     1164        Parser/$(DEPDIR)/$(am__dirstamp)
     1165ResolvExpr/AlternativePrinter.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     1166        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    9311167Virtual/$(am__dirstamp):
    9321168        @$(MKDIR_P) Virtual
     
    9351171        @$(MKDIR_P) Virtual/$(DEPDIR)
    9361172        @: > Virtual/$(DEPDIR)/$(am__dirstamp)
    937 Virtual/driver_cfa_cpp-ExpandCasts.$(OBJEXT): Virtual/$(am__dirstamp) \
     1173Virtual/ExpandCasts.$(OBJEXT): Virtual/$(am__dirstamp) \
    9381174        Virtual/$(DEPDIR)/$(am__dirstamp)
    939 driver/$(am__dirstamp):
    940         @$(MKDIR_P) driver
    941         @: > driver/$(am__dirstamp)
    942 
    943 driver/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)
     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)
     1182SymTab/demangler.$(OBJEXT): SymTab/$(am__dirstamp) \
     1183        SymTab/$(DEPDIR)/$(am__dirstamp)
     1184
     1185demangler$(EXEEXT): $(demangler_OBJECTS) $(demangler_DEPENDENCIES) $(EXTRA_demangler_DEPENDENCIES)
     1186        @rm -f demangler$(EXEEXT)
     1187        $(AM_V_CXXLD)$(CXXLINK) $(demangler_OBJECTS) $(demangler_LDADD) $(LIBS)
    9461188
    9471189mostlyclean-compile:
    9481190        -rm -f *.$(OBJEXT)
     1191        -rm -f AST/*.$(OBJEXT)
    9491192        -rm -f CodeGen/*.$(OBJEXT)
    9501193        -rm -f CodeTools/*.$(OBJEXT)
    9511194        -rm -f Common/*.$(OBJEXT)
     1195        -rm -f Common/Stats/*.$(OBJEXT)
    9521196        -rm -f Concurrency/*.$(OBJEXT)
    9531197        -rm -f ControlStruct/*.$(OBJEXT)
     
    9591203        -rm -f SynTree/*.$(OBJEXT)
    9601204        -rm -f Tuples/*.$(OBJEXT)
     1205        -rm -f Validate/*.$(OBJEXT)
    9611206        -rm -f Virtual/*.$(OBJEXT)
    9621207
     
    9641209        -rm -f *.tab.c
    9651210
    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@
     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@
    10731354
    10741355.cc.o:
     
    10881369@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
    10891370
    1090 driver_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@
     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@
    10941376@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 
    1097 driver_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@
     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@
    11011384@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 
    1104 driver_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@
     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@
    11081392@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 
    1111 driver_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@
     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@
    11151400@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 
    1118 CodeGen/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 
    1125 CodeGen/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 
    1132 CodeGen/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 
    1139 CodeGen/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 
    1146 CodeGen/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 
    1153 CodeGen/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 
    1160 CodeGen/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 
    1167 CodeGen/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 
    1174 CodeGen/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 
    1181 CodeGen/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 
    1188 CodeGen/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 
    1195 CodeGen/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 
    1202 CodeTools/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 
    1209 CodeTools/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 
    1216 CodeTools/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 
    1223 CodeTools/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 
    1230 Concurrency/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 
    1237 Concurrency/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 
    1244 Concurrency/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 
    1251 Concurrency/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 
    1258 Common/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 
    1265 Common/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 
    1272 Common/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 
    1279 Common/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 
    1286 Common/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 
    1293 Common/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 
    1300 Common/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 
    1307 Common/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 
    1314 Common/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 
    1321 Common/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 
    1328 ControlStruct/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 
    1335 ControlStruct/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 
    1342 ControlStruct/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 
    1349 ControlStruct/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 
    1356 ControlStruct/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 
    1363 ControlStruct/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 
    1370 ControlStruct/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 
    1377 ControlStruct/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 
    1384 ControlStruct/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 
    1391 ControlStruct/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 
    1398 ControlStruct/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 
    1405 ControlStruct/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 
    1412 GenPoly/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 
    1419 GenPoly/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 
    1426 GenPoly/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 
    1433 GenPoly/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 
    1440 GenPoly/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 
    1447 GenPoly/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 
    1454 GenPoly/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 
    1461 GenPoly/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 
    1468 GenPoly/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 
    1475 GenPoly/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 
    1482 GenPoly/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 
    1489 GenPoly/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 
    1496 GenPoly/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 
    1503 GenPoly/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 
    1510 InitTweak/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 
    1517 InitTweak/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 
    1524 InitTweak/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 
    1531 InitTweak/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 
    1538 InitTweak/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 
    1545 InitTweak/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 
    1552 InitTweak/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 
    1559 InitTweak/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 
    1566 Parser/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 
    1573 Parser/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 
    1580 Parser/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 
    1587 Parser/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 
    1594 Parser/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 
    1601 Parser/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 
    1608 Parser/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 
    1615 Parser/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 
    1622 Parser/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 
    1629 Parser/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 
    1636 Parser/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 
    1643 Parser/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 
    1650 Parser/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 
    1657 Parser/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 
    1664 Parser/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 
    1671 Parser/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 
    1678 Parser/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 
    1685 Parser/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 
    1692 Parser/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 
    1699 Parser/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 
    1706 Parser/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 
    1713 Parser/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 
    1720 ResolvExpr/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 
    1727 ResolvExpr/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 
    1734 ResolvExpr/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 
    1741 ResolvExpr/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 
    1748 ResolvExpr/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 
    1755 ResolvExpr/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 
    1762 ResolvExpr/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 
    1769 ResolvExpr/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 
    1776 ResolvExpr/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 
    1783 ResolvExpr/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 
    1790 ResolvExpr/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 
    1797 ResolvExpr/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 
    1804 ResolvExpr/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 
    1811 ResolvExpr/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 
    1818 ResolvExpr/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 
    1825 ResolvExpr/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 
    1832 ResolvExpr/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 
    1839 ResolvExpr/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 
    1846 ResolvExpr/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 
    1853 ResolvExpr/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 
    1860 ResolvExpr/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 
    1867 ResolvExpr/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 
    1874 ResolvExpr/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 
    1881 ResolvExpr/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 
    1888 ResolvExpr/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 
    1895 ResolvExpr/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 
    1902 ResolvExpr/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 
    1909 ResolvExpr/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 
    1916 ResolvExpr/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 
    1923 ResolvExpr/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 
    1930 ResolvExpr/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 
    1937 ResolvExpr/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 
    1944 ResolvExpr/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 
    1951 ResolvExpr/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 
    1958 ResolvExpr/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 
    1965 ResolvExpr/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 
    1972 ResolvExpr/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 
    1979 ResolvExpr/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 
    1986 SymTab/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 
    1993 SymTab/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 
    2000 SymTab/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 
    2007 SymTab/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 
    2014 SymTab/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 
    2021 SymTab/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 
    2028 SymTab/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 
    2035 SymTab/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 
    2042 SymTab/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 
    2049 SymTab/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 
    2056 SynTree/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 
    2063 SynTree/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 
    2070 SynTree/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 
    2077 SynTree/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 
    2084 SynTree/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 
    2091 SynTree/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 
    2098 SynTree/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 
    2105 SynTree/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 
    2112 SynTree/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 
    2119 SynTree/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 
    2126 SynTree/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 
    2133 SynTree/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 
    2140 SynTree/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 
    2147 SynTree/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 
    2154 SynTree/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 
    2161 SynTree/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 
    2168 SynTree/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 
    2175 SynTree/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 
    2182 SynTree/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 
    2189 SynTree/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 
    2196 SynTree/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 
    2203 SynTree/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 
    2210 SynTree/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 
    2217 SynTree/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 
    2224 SynTree/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 
    2231 SynTree/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 
    2238 SynTree/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 
    2245 SynTree/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 
    2252 SynTree/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 
    2259 SynTree/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 
    2266 SynTree/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 
    2273 SynTree/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 
    2280 SynTree/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 
    2287 SynTree/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 
    2294 SynTree/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 
    2301 SynTree/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 
    2308 SynTree/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 
    2315 SynTree/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 
    2322 SynTree/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 
    2329 SynTree/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 
    2336 SynTree/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 
    2343 SynTree/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 
    2350 SynTree/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 
    2357 SynTree/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 
    2364 SynTree/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 
    2371 SynTree/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 
    2378 SynTree/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 
    2385 SynTree/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 
    2392 SynTree/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 
    2399 SynTree/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 
    2406 SynTree/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 
    2413 SynTree/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 
    2420 SynTree/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 
    2427 SynTree/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 
    2434 SynTree/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 
    2441 SynTree/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 
    2448 SynTree/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 
    2455 SynTree/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 
    2462 SynTree/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 
    2469 SynTree/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 
    2476 SynTree/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 
    2483 SynTree/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 
    2490 SynTree/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 
    2497 SynTree/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 
    2504 SynTree/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 
    2511 SynTree/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 
    2518 SynTree/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 
    2525 SynTree/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 
    2532 Tuples/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 
    2539 Tuples/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 
    2546 Tuples/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 
    2553 Tuples/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 
    2560 Tuples/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 
    2567 Tuples/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 
    2574 Virtual/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 
    2581 Virtual/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`
     1401@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
    25871402
    25881403.ll.cc:
     
    25911406.yy.cc:
    25921407        $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
     1408
     1409mostlyclean-libtool:
     1410        -rm -f *.lo
     1411
     1412clean-libtool:
     1413        -rm -rf .libs _libs
     1414        -rm -rf ../driver/.libs ../driver/_libs
    25931415
    25941416ID: $(am__tagged_files)
     
    26771499check: $(BUILT_SOURCES)
    26781500        $(MAKE) $(AM_MAKEFLAGS) check-am
    2679 all-am: Makefile $(PROGRAMS)
     1501all-am: Makefile $(LIBRARIES) $(PROGRAMS)
    26801502installdirs:
    26811503        for dir in "$(DESTDIR)$(cfa_cpplibdir)"; do \
     
    27031525        fi
    27041526mostlyclean-generic:
     1527        -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
    27051528
    27061529clean-generic:
     
    27091532        -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
    27101533        -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)
    27111537        -rm -f CodeGen/$(DEPDIR)/$(am__dirstamp)
    27121538        -rm -f CodeGen/$(am__dirstamp)
     
    27151541        -rm -f Common/$(DEPDIR)/$(am__dirstamp)
    27161542        -rm -f Common/$(am__dirstamp)
     1543        -rm -f Common/Stats/$(DEPDIR)/$(am__dirstamp)
     1544        -rm -f Common/Stats/$(am__dirstamp)
    27171545        -rm -f Concurrency/$(DEPDIR)/$(am__dirstamp)
    27181546        -rm -f Concurrency/$(am__dirstamp)
     
    27331561        -rm -f Tuples/$(DEPDIR)/$(am__dirstamp)
    27341562        -rm -f Tuples/$(am__dirstamp)
     1563        -rm -f Validate/$(DEPDIR)/$(am__dirstamp)
     1564        -rm -f Validate/$(am__dirstamp)
    27351565        -rm -f Virtual/$(DEPDIR)/$(am__dirstamp)
    27361566        -rm -f Virtual/$(am__dirstamp)
    2737         -rm -f driver/$(am__dirstamp)
    27381567
    27391568maintainer-clean-generic:
     
    27471576clean: clean-am
    27481577
    2749 clean-am: clean-cfa_cpplibPROGRAMS clean-generic mostlyclean-am
     1578clean-am: clean-cfa_cpplibPROGRAMS clean-generic clean-libtool \
     1579        clean-noinstLIBRARIES mostlyclean-am
    27501580
    27511581distclean: distclean-am
    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)
     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)
    27531583        -rm -f Makefile
    27541584distclean-am: clean-am distclean-compile distclean-generic \
     
    27961626
    27971627maintainer-clean: maintainer-clean-am
    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)
     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)
    27991629        -rm -f Makefile
    28001630maintainer-clean-am: distclean-am maintainer-clean-generic
     
    28021632mostlyclean: mostlyclean-am
    28031633
    2804 mostlyclean-am: mostlyclean-compile mostlyclean-generic
     1634mostlyclean-am: mostlyclean-compile mostlyclean-generic \
     1635        mostlyclean-libtool
    28051636
    28061637pdf: pdf-am
     
    28171648
    28181649.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
    2819         clean-cfa_cpplibPROGRAMS clean-generic cscopelist-am ctags \
    2820         ctags-am distclean distclean-compile distclean-generic \
     1650        clean-cfa_cpplibPROGRAMS clean-generic clean-libtool \
     1651        clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
     1652        distclean-compile distclean-generic distclean-libtool \
    28211653        distclean-tags distdir dvi dvi-am html html-am info info-am \
    28221654        install install-am install-cfa_cpplibPROGRAMS install-data \
     
    28271659        installcheck-am installdirs maintainer-clean \
    28281660        maintainer-clean-generic mostlyclean mostlyclean-compile \
    2829         mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
    2830         uninstall-am uninstall-cfa_cpplibPROGRAMS
     1661        mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
     1662        tags tags-am uninstall uninstall-am \
     1663        uninstall-cfa_cpplibPROGRAMS
    28311664
    28321665.PRECIOUS: Makefile
    28331666
     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
    28341674
    28351675# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • src/Parser/DeclarationNode.cc

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun  7 12:08:55 2018
    13 // Update Count     : 1079
     12// Last Modified On : Thu Jul 25 22:17:10 2019
     13// Update Count     : 1116
    1414//
    1515
     
    4141
    4242// These must harmonize with the corresponding DeclarationNode enumerations.
    43 const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "float", "double", "long double", "int128", "float80", "float128", "NoBasicTypeNames" };
    44 const char * DeclarationNode::complexTypeNames[] = { "_Complex", "_Imaginary", "NoComplexTypeNames" };
     43const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "int128",
     44                                                                                                   "float", "double", "long double", "float80", "float128",
     45                                                                                                   "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" };
     46const char * DeclarationNode::complexTypeNames[] = { "_Complex", "NoComplexTypeNames", "_Imaginary" }; // Imaginary unsupported => parse, but make invisible and print error message
    4547const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" };
    4648const char * DeclarationNode::lengthNames[] = { "short", "long", "long long", "NoLengthNames" };
    4749const char * DeclarationNode::aggregateNames[] = { "struct", "union", "trait", "coroutine", "monitor", "thread", "NoAggregateNames" };
    4850const char * DeclarationNode::typeClassNames[] = { "otype", "dtype", "ftype", "NoTypeClassNames" };
    49 const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "zero_t", "one_t", "NoBuiltinTypeNames" };
     51const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" };
    5052
    5153UniqueName DeclarationNode::anonymous( "__anonymous" );
     
    5456
    5557DeclarationNode::DeclarationNode() :
    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 ) {
     58        linkage( ::linkage ) {
    6559
    6660//      variable.name = nullptr;
     
    10498        newnode->builtin = NoBuiltinType;
    10599        newnode->type = maybeClone( type );
     100        newnode->inLine = inLine;
    106101        newnode->storageClasses = storageClasses;
    107102        newnode->funcSpecs = funcSpecs;
     
    131126} // DeclarationNode::clone
    132127
    133 void DeclarationNode::print( std::ostream &os, int indent ) const {
     128void DeclarationNode::print( std::ostream & os, int indent ) const {
    134129        os << string( indent, ' ' );
    135130        if ( name ) {
     
    167162}
    168163
    169 void DeclarationNode::printList( std::ostream &os, int indent ) const {
     164void DeclarationNode::printList( std::ostream & os, int indent ) const {
    170165        ParseNode::printList( os, indent );
    171166        if ( hasEllipsis ) {
     
    254249} // DeclarationNode::newFromTypedef
    255250
     251DeclarationNode * DeclarationNode::newFromGlobalScope() {
     252        DeclarationNode * newnode = new DeclarationNode;
     253        newnode->type = new TypeData( TypeData::GlobalScope );
     254        return newnode;
     255}
     256
     257DeclarationNode * 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
    256269DeclarationNode * DeclarationNode::newAggregate( Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
    257         assert( name );
    258270        DeclarationNode * newnode = new DeclarationNode;
    259271        newnode->type = new TypeData( TypeData::Aggregate );
    260272        newnode->type->aggregate.kind = kind;
    261         newnode->type->aggregate.name = name;
     273        newnode->type->aggregate.name =  name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
    262274        newnode->type->aggregate.actuals = actuals;
    263275        newnode->type->aggregate.fields = fields;
     
    265277        newnode->type->aggregate.tagged = false;
    266278        newnode->type->aggregate.parent = nullptr;
     279        newnode->type->aggregate.anon = name == nullptr;
    267280        return newnode;
    268281} // DeclarationNode::newAggregate
    269282
    270283DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body ) {
    271         assert( name );
    272284        DeclarationNode * newnode = new DeclarationNode;
    273285        newnode->type = new TypeData( TypeData::Enum );
    274         newnode->type->enumeration.name = name;
     286        newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
    275287        newnode->type->enumeration.constants = constants;
    276288        newnode->type->enumeration.body = body;
     289        newnode->type->enumeration.anon = name == nullptr;
    277290        return newnode;
    278291} // DeclarationNode::newEnum
     
    391404}
    392405
    393 DeclarationNode * DeclarationNode::newTypeof( ExpressionNode * expr ) {
    394         DeclarationNode * newnode = new DeclarationNode;
    395         newnode->type = new TypeData( TypeData::Typeof );
     406DeclarationNode * DeclarationNode::newTypeof( ExpressionNode * expr, bool basetypeof ) {
     407        DeclarationNode * newnode = new DeclarationNode;
     408        newnode->type = new TypeData( basetypeof ? TypeData::Basetypeof : TypeData::Typeof );
    396409        newnode->type->typeexpr = expr;
    397410        return newnode;
     
    405418        return newnode;
    406419} // DeclarationNode::newBuiltinType
    407 
    408 DeclarationNode * 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 
    417 DeclarationNode * 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 }
    425420
    426421DeclarationNode * DeclarationNode::newAttribute( const string * name, ExpressionNode * expr ) {
     
    503498} // DeclarationNode::copySpecifiers
    504499
    505 static 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
     500static void addQualifiersToType( TypeData *& src, TypeData * dst ) {
    514501        if ( dst->base ) {
    515502                addQualifiersToType( src, dst->base );
     
    564551} // addQualifiers
    565552
    566 static void addTypeToType( TypeData *&src, TypeData *&dst ) {
     553static void addTypeToType( TypeData *& src, TypeData *& dst ) {
    567554        if ( src->forall && dst->kind == TypeData::Function ) {
    568555                if ( dst->forall ) {
     
    955942}
    956943
    957 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > &outputList ) {
     944void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) {
    958945        SemanticErrorException errors;
    959946        std::back_insert_iterator< std::list< Declaration * > > out( outputList );
     
    961948        for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
    962949                try {
     950                        bool extracted = false;
     951                        bool anon = false;
    963952                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    964953                                // handle the case where a structure declaration is contained within an object or type declaration
    965954                                Declaration * decl = extr->build();
    966955                                if ( decl ) {
     956                                        // hoist the structure declaration
    967957                                        decl->location = cur->location;
    968958                                        * 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                                 decl->location = cur->location;
    976                                 * out++ = 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;
     997                                } // if
    977998                        } // if
    978                 } catch( SemanticErrorException &e ) {
     999                } catch( SemanticErrorException & e ) {
    9791000                        errors.append( e );
    9801001                } // try
    981         } // while
     1002        } // for
    9821003
    9831004        if ( ! errors.isEmpty() ) {
     
    9861007} // buildList
    9871008
    988 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > &outputList ) {
     1009// currently only builds assertions, function parameters, and return values
     1010void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList ) {
    9891011        SemanticErrorException errors;
    9901012        std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );
     
    9931015                try {
    9941016                        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;
    1010                                 } // if
     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;
    10111040                        } // if
    1012                 } catch( SemanticErrorException &e ) {
     1041                } catch( SemanticErrorException & e ) {
    10131042                        errors.append( e );
    10141043                } // try
     
    10201049} // buildList
    10211050
    1022 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > &outputList ) {
     1051void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) {
    10231052        SemanticErrorException errors;
    10241053        std::back_insert_iterator< std::list< Type * > > out( outputList );
     
    10281057                try {
    10291058                        * out++ = cur->buildType();
    1030                 } catch( SemanticErrorException &e ) {
     1059                } catch( SemanticErrorException & e ) {
    10311060                        errors.append( e );
    10321061                } // try
     
    10641093                if ( type->kind != TypeData::Function && funcSpecs.any() ) {
    10651094                        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 " );
    10661103                } // if
    10671104                bool isDelete = initializer && initializer->get_isDelete();
  • src/Parser/ExpressionNode.cc

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  4 21:24:45 2018
    13 // Update Count     : 802
     12// Last Modified On : Sun Aug  4 20:57:55 2019
     13// Update Count     : 978
    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 checkL( char c ) { return c == 'l' || c == 'L'; }
    55 static inline bool checkZ( char c ) { return c == 'z' || c == 'Z'; }
    56 static inline bool checkU( char c ) { return c == 'u' || c == 'U'; }
     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'; }
    5756static inline bool checkF( char c ) { return c == 'f' || c == 'F'; }
    5857static inline bool checkD( char c ) { return c == 'd' || c == 'D'; }
     58static inline bool checkF80( char c ) { return c == 'w' || c == 'W'; }
     59static inline bool checkF128( char c ) { return c == 'q' || c == 'Q'; }
     60static inline bool checkL( char c ) { return c == 'l' || c == 'L'; }
    5961static inline bool checkI( char c ) { return c == 'i' || c == 'I'; }
    6062static inline bool checkB( char c ) { return c == 'b' || c == 'B'; }
    6163static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
    62 
    63 static 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 
    68 static 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;
     64// static inline bool checkN( char c ) { return c == 'n' || c == 'N'; }
     65
     66void 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;
    7982                } else {                                                                                // 128
    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
     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
     90void 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
    95109
    96110Expression * build_constantInteger( string & str ) {
    97111        static const BasicType::Kind kind[2][6] = {
    98                 // short (h) must be before char (hh)
     112                // short (h) must be before char (hh) because shorter type has the longer suffix
    99113                { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },
    100114                { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt128, },
    101115        };
    102116
    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
     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
    106121
    107122        unsigned long long int v;                                                       // converted integral value
    108123        size_t last = str.length() - 1;                                         // last subscript of constant
    109124        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
    110130
    111131        // special constants
     
    119139        } // if
    120140
    121         // Cannot be "0"
     141        // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
    122142
    123143        if ( str[0] == '0' ) {                                                          // radix character ?
     
    127147                        //printf( "%llx %llu\n", v, v );
    128148                } else if ( checkB( str[1] ) ) {                                // binary constant ?
    129                         v = 0;
    130                         for ( unsigned int i = 2;; i += 1 ) {           // compute value
     149                        v = 0;                                                                          // compute value
     150                        for ( unsigned int i = 2;; ) {                          // ignore prefix
    131151                                if ( str[i] == '1' ) v |= 1;
    132                           if ( i == last ) break;
     152                                i += 1;
     153                          if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
    133154                                v <<= 1;
    134155                        } // for
    135                         //printf( "%llx %llu\n", v, v );
     156                        //printf( "%#llx %llu\n", v, v );
    136157                } else {                                                                                // octal constant
    137158                        sscanf( (char *)str.c_str(), "%llo", &v );
    138                         //printf( "%llo %llu\n", v, v );
     159                        //printf( "%#llo %llu\n", v, v );
    139160                } // if
    140161        } else {                                                                                        // decimal constant ?
    141162                sscanf( (char *)str.c_str(), "%llu", &v );
    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;
     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
     209        // 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 ?
     212                // 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 ) );
    170221                        } // 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 );
    209         // Constant type is correct for overload resolving.
    210         ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][size] ), str, v ) );
    211         if ( Unsigned && size < 2 ) {                                           // hh or h, less than int ?
    212                 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
    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 
     222                } // if
     223        } // if
     224
     225  CLEANUP: ;
    224226        delete &str;                                                                            // created by lex
    225227        return ret;
     
    227229
    228230
    229 static inline void checkLNFloat( string & str, int & lnth, int & size ) {
    230         string::size_type posn = str.find_first_of( "lL" ), start = posn;
     231static 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
    231240  if ( posn == string::npos ) return;
    232         size = 2;                                                                                       // assume largest size
    233         lnth = 0;
     241        explnth = true;
    234242        posn += 1;                                                                                      // advance to size
    235243        if ( str[posn] == '3' ) {                                                       // 32
    236                 size = 0;
     244                if ( str[last] != 'x' ) type = 6;
     245                else type = 7;
    237246        } else if ( str[posn] == '6' ) {                                        // 64
    238                 size = 1;
    239         } else if ( str[posn] == '8' || str[posn] == '1' ) { // 80, 128
    240                 size = 2;
    241                 if ( str[posn] == '1' ) posn += 1;
     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
    242258        } else {
    243259                assertf( false, "internal error, bad floating point length %s", str.c_str() );
    244260        } // if
    245         posn += 1;
    246         str.erase( start, posn - start + 1 );                           // remove length suffix
    247 } // checkLNFloat
     261} // checkFnxFloat
    248262
    249263
    250264Expression * build_constantFloat( string & str ) {
    251         static const BasicType::Kind kind[2][3] = {
    252                 { BasicType::Float, BasicType::Double, BasicType::LongDouble },
    253                 { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex },
     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 },
    254268        };
    255269
    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
     270        // floating-point constant has minimum of 2 characters 1. or .1
    260271        size_t last = str.length() - 1;
    261272        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
    262276
    263277        sscanf( str.c_str(), "%lg", &v );
     
    269283
    270284        if ( checkF( str[last] ) ) {                                            // float ?
    271                 size = 0;
     285                type = 0;
    272286        } else if ( checkD( str[last] ) ) {                                     // double ?
    273                 size = 1;
     287                type = 1;
    274288        } else if ( checkL( str[last] ) ) {                                     // long double ?
    275                 size = 2;
     289                type = 2;
     290        } else if ( checkF80( str[last] ) ) {                           // __float80 ?
     291                type = 3;
     292        } else if ( checkF128( str[last] ) ) {                          // __float128 ?
     293                type = 4;
    276294        } else {
    277                 size = 1;                                                                               // double (default)
    278                 checkLNFloat( str, lnth, size );
    279         } // if
     295                type = 1;                                                                               // double (default if no suffix)
     296                checkFnxFloat( str, last, explnth, type );
     297        } // if
     298
    280299        if ( ! complx && checkI( str[last - 1] ) ) {            // imaginary ?
    281300                complx = true;
    282301        } // if
    283302
    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 );
     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 );
    288307        } // if
    289308
     
    338357                                                                        new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
    339358                                                                        false, false );
    340         Expression * ret = new ConstantExpr( Constant( at, str, (unsigned long long int)0 ) ); // constant 0 is ignored for pure string value
     359        Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) );
    341360        if ( units.length() != 0 ) {
    342361                ret = new UntypedExpr( new NameExpr( units ), { ret } );
  • src/Parser/LinkageSpec.cc

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 13:22:09 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul  7 11:11:00 2017
    13 // Update Count     : 25
     12// Last Modified On : Thr Spt 12 15:59:00 2018
     13// Update Count     : 26
    1414//
    1515
     
    2323
    2424namespace LinkageSpec {
    25 
    26 Spec 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 }
    3925
    4026Spec linkageUpdate( CodeLocation location, Spec old_spec, const string * cmd ) {
  • src/Parser/LinkageSpec.h

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 13:24:28 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:32:16 2017
    13 // Update Count     : 14
     12// Last Modified On : Wed Jul 10 16:02:34 2019
     13// Update Count     : 18
    1414//
    1515
     
    2222namespace LinkageSpec {
    2323        // All linkage specs are some combination of these flags:
    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         };
     24        enum { Mangle = 1 << 0, Generate = 1 << 1, Overrideable = 1 << 2, Builtin = 1 << 3, GccBuiltin = 1 << 4, NoOfSpecs = 1 << 5, };
    3325
    3426        union Spec {
     
    4234                };
    4335                constexpr Spec( unsigned int val ) : val( val ) {}
    44                 constexpr Spec( Spec const &other ) : val( other.val ) {}
     36                constexpr Spec( Spec const & other ) : val( other.val ) {}
     37                constexpr Spec & operator=( const Spec & ) = default;
    4538                // Operators may go here.
    4639                // Supports == and !=
    47                 constexpr operator unsigned int () const { return val; }
     40                constexpr operator unsigned int() const { return val; }
    4841        };
    4942
    5043
    51         Spec linkageCheck( CodeLocation location, const std::string * );
    52         // Returns the Spec with the given name (limited to C, Cforall & BuiltinC)
    5344        Spec linkageUpdate( CodeLocation location, Spec old_spec, const std::string * cmd );
    5445        /* If cmd = "C" returns a Spec that is old_spec with is_mangled = false
  • src/Parser/ParseNode.h

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun  6 16:17:18 2018
    13 // Update Count     : 843
     12// Last Modified On : Thu Jul 25 22:17:10 2019
     13// Update Count     : 876
    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() << std::endl;
    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();
     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
    138140  private:
    139141        bool extension = false;
    140         std::unique_ptr<Expression> expr;
    141142}; // ExpressionNode
    142143
     
    205206class DeclarationNode : public ParseNode {
    206207  public:
    207         // These enumerations must harmonize with their names.
    208         enum BasicType { Void, Bool, Char, Int, Float, Double, LongDouble, Int128, Float80, Float128, NoBasicType };
     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 };
    209212        static const char * basicTypeNames[];
    210         enum ComplexType { Complex, Imaginary, NoComplexType };
     213        enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message
    211214        static const char * complexTypeNames[];
    212215        enum Signedness { Signed, Unsigned, NoSignedness };
     
    218221        enum TypeClass { Otype, Dtype, Ftype, Ttype, NoTypeClass };
    219222        static const char * typeClassNames[];
    220         enum BuiltinType { Valist, Zero, One, NoBuiltinType };
     223        enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };
    221224        static const char * builtinTypeNames[];
    222225
     
    231234        static DeclarationNode * newForall( DeclarationNode * );
    232235        static DeclarationNode * newFromTypedef( const std::string * );
     236        static DeclarationNode * newFromGlobalScope();
     237        static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );
    233238        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    234239        static DeclarationNode * newAggregate( Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
     
    246251        static DeclarationNode * newBitfield( ExpressionNode * size );
    247252        static DeclarationNode * newTuple( DeclarationNode * members );
    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
     253        static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );
    251254        static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    252255        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
     
    288291        }
    289292
    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;
     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;
    292295
    293296        Declaration * build() const;
     
    301304        bool get_extension() const { return extension; }
    302305        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; }
    303309  public:
    304310        DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
     
    325331        StaticAssert_t assert;
    326332
    327         BuiltinType builtin;
    328 
    329         TypeData * type;
    330 
     333        BuiltinType builtin = NoBuiltinType;
     334
     335        TypeData * type = nullptr;
     336
     337        bool inLine = false;
    331338        Type::FuncSpecifiers funcSpecs;
    332339        Type::StorageClasses storageClasses;
    333340
    334         ExpressionNode * bitfieldWidth;
     341        ExpressionNode * bitfieldWidth = nullptr;
    335342        std::unique_ptr<ExpressionNode> enumeratorValue;
    336         bool hasEllipsis;
     343        bool hasEllipsis = false;
    337344        LinkageSpec::Spec linkage;
    338         Expression * asmName;
     345        Expression * asmName = nullptr;
    339346        std::list< Attribute * > attributes;
    340         InitializerNode * initializer;
     347        InitializerNode * initializer = nullptr;
    341348        bool extension = false;
    342349        std::string error;
    343         StatementNode * asmStmt;
     350        StatementNode * asmStmt = nullptr;
    344351
    345352        static UniqueName anonymous;
     
    375382        virtual StatementNode * append_last_case( StatementNode * );
    376383
    377         virtual void print( std::ostream &os, __attribute__((unused)) int indent = 0 ) const override {
     384        virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {
    378385                os << stmt.get() << std::endl;
    379386        }
     
    384391Statement * build_expr( ExpressionNode * ctl );
    385392
    386 struct IfCtl {
    387         IfCtl( DeclarationNode * decl, ExpressionNode * condition ) :
     393struct IfCtrl {
     394        IfCtrl( DeclarationNode * decl, ExpressionNode * condition ) :
    388395                init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}
    389396
     
    392399};
    393400
    394 struct ForCtl {
    395         ForCtl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :
     401struct ForCtrl {
     402        ForCtrl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :
    396403                init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {}
    397         ForCtl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :
     404        ForCtrl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :
    398405                init( new StatementNode( decl ) ), condition( condition ), change( change ) {}
    399406
     
    403410};
    404411
    405 Expression * build_if_control( IfCtl * ctl, std::list< Statement * > & init );
    406 Statement * build_if( IfCtl * ctl, StatementNode * then_stmt, StatementNode * else_stmt );
     412Expression * build_if_control( IfCtrl * ctl, std::list< Statement * > & init );
     413Statement * build_if( IfCtrl * ctl, StatementNode * then_stmt, StatementNode * else_stmt );
    407414Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
    408415Statement * build_case( ExpressionNode * ctl );
    409416Statement * build_default();
    410 Statement * build_while( IfCtl * ctl, StatementNode * stmt );
     417Statement * build_while( IfCtrl * ctl, StatementNode * stmt );
    411418Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt );
    412 Statement * build_for( ForCtl * forctl, StatementNode * stmt );
     419Statement * build_for( ForCtrl * forctl, StatementNode * stmt );
    413420Statement * build_branch( BranchStmt::Type kind );
    414421Statement * build_branch( std::string * identifier, BranchStmt::Type kind );
     
    428435WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );
    429436WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
    430 WithStmt * build_with( ExpressionNode * exprs, StatementNode * stmt );
     437Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
    431438
    432439//##############################################################################
    433440
    434441template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >
    435 void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > &outputList ) {
     442void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > & outputList ) {
    436443        SemanticErrorException errors;
    437444        std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );
     
    447454                                assertf(false, "buildList unknown type");
    448455                        } // if
    449                 } catch( SemanticErrorException &e ) {
     456                } catch( SemanticErrorException & e ) {
    450457                        errors.append( e );
    451458                } // try
     
    458465
    459466// in DeclarationNode.cc
    460 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > &outputList );
    461 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > &outputList );
    462 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > &outputList );
     467void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList );
     468void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList );
     469void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList );
    463470
    464471template< typename SynTreeType, typename NodeType >
    465 void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > &outputList ) {
     472void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > & outputList ) {
    466473        buildList( firstNode, outputList );
    467474        delete firstNode;
  • src/Parser/StatementNode.cc

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

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun  6 17:40:33 2018
    13 // Update Count     : 604
     12// Last Modified On : Wed Feb 13 18:16:23 2019
     13// Update Count     : 649
    1414//
    1515
     
    3737          case Reference:
    3838          case EnumConstant:
     39          case GlobalScope:
    3940                // nothing else to initialize
    4041                break;
     
    6263                enumeration.constants = nullptr;
    6364                enumeration.body = false;
     65                enumeration.anon = false;
    6466                break;
    6567          case Aggregate:
     
    7375                aggregate.tagged = false;
    7476                aggregate.parent = nullptr;
     77                aggregate.anon = false;
    7578                break;
    7679          case AggregateInst:
     
    7881                aggInst.aggregate = nullptr;
    7982                aggInst.params = nullptr;
    80                 aggInst.hoistType = false;;
     83                aggInst.hoistType = false;
    8184                break;
    8285          case Symbolic:
     
    9396                break;
    9497          case Typeof:
     98          case Basetypeof:
    9599                // typeexpr = new Typeof_t;
    96100                typeexpr = nullptr;
     
    98102          case Builtin:
    99103                // builtin = new Builtin_t;
     104                case Qualified:
     105                qualified.parent = nullptr;
     106                qualified.child = nullptr;
    100107                break;
    101108        } // switch
     
    112119          case Reference:
    113120          case EnumConstant:
     121          case GlobalScope:
    114122                // nothing to destroy
    115123                break;
     
    159167                break;
    160168          case Typeof:
     169          case Basetypeof:
    161170                // delete typeexpr->expr;
    162171                delete typeexpr;
     
    165174                // delete builtin;
    166175                break;
     176          case Qualified:
     177                delete qualified.parent;
     178                delete qualified.child;
    167179        } // switch
    168180} // TypeData::~TypeData
     
    180192          case Pointer:
    181193          case Reference:
     194          case GlobalScope:
    182195                // nothing else to copy
    183196                break;
     
    207220                newtype->aggregate.fields = maybeClone( aggregate.fields );
    208221                newtype->aggregate.body = aggregate.body;
     222                newtype->aggregate.anon = aggregate.anon;
    209223                newtype->aggregate.tagged = aggregate.tagged;
    210224                newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;
     
    219233                newtype->enumeration.constants = maybeClone( enumeration.constants );
    220234                newtype->enumeration.body = enumeration.body;
     235                newtype->enumeration.anon = enumeration.anon;
    221236                break;
    222237          case Symbolic:
     
    232247                break;
    233248          case Typeof:
     249          case Basetypeof:
    234250                newtype->typeexpr = maybeClone( typeexpr );
    235251                break;
     
    237253                assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One );
    238254                newtype->builtintype = builtintype;
     255                break;
     256                case Qualified:
     257                newtype->qualified.parent = maybeClone( qualified.parent );
     258                newtype->qualified.child = maybeClone( qualified.child );
    239259                break;
    240260        } // switch
     
    254274
    255275        switch ( kind ) {
    256           case Unknown:
    257                 os << "entity of unknown type ";
     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
    258287                break;
    259288          case Pointer:
     
    264293                } // if
    265294                break;
    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 ] << " ";
     295          case Reference:
     296                os << "reference ";
     297                if ( base ) {
     298                        os << "to ";
     299                        base->print( os, indent );
     300                } // if
    275301                break;
    276302          case Array:
     
    296322                        function.params->printList( os, indent + 4 );
    297323                } else {
    298                         os << string( indent + 2, ' ' ) << "with no parameters " << endl;
     324                        os << string( indent + 2, ' ' ) << "with no parameters" << endl;
    299325                } // if
    300326                if ( function.idList ) {
     
    321347                os << DeclarationNode::aggregateNames[ aggregate.kind ] << ' ' << *aggregate.name << endl;
    322348                if ( aggregate.params ) {
    323                         os << string( indent + 2, ' ' ) << "with type parameters " << endl;
     349                        os << string( indent + 2, ' ' ) << "with type parameters" << endl;
    324350                        aggregate.params->printList( os, indent + 4 );
    325351                } // if
    326352                if ( aggregate.actuals ) {
    327                         os << string( indent + 2, ' ' ) << "instantiated with actual parameters " << endl;
     353                        os << string( indent + 2, ' ' ) << "instantiated with actual parameters" << endl;
    328354                        aggregate.actuals->printList( os, indent + 4 );
    329355                } // if
    330356                if ( aggregate.fields ) {
    331                         os << string( indent + 2, ' ' ) << "with members " << endl;
     357                        os << string( indent + 2, ' ' ) << "with members" << endl;
    332358                        aggregate.fields->printList( os, indent + 4 );
    333359                } // if
    334360                if ( aggregate.body ) {
    335                         os << string( indent + 2, ' ' ) << " with body " << endl;
     361                        os << string( indent + 2, ' ' ) << " with body" << endl;
    336362                } // if
    337363                break;
     
    344370                } // if
    345371                if ( aggInst.params ) {
    346                         os << string( indent + 2, ' ' ) << "with parameters " << endl;
     372                        os << string( indent + 2, ' ' ) << "with parameters" << endl;
    347373                        aggInst.params->printList( os, indent + 2 );
    348374                } // if
     
    355381                } // if
    356382                if ( enumeration.body ) {
    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
     383                        os << string( indent + 2, ' ' ) << " with body" << endl;
     384                } // if
     385                break;
     386          case EnumConstant:
     387                os << "enumeration constant ";
    366388                break;
    367389          case Symbolic:
     
    385407                } // if
    386408                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;
    387417          case Tuple:
    388418                os << "tuple ";
    389419                if ( tuple ) {
    390                         os << "with members " << endl;
     420                        os << "with members" << endl;
    391421                        tuple->printList( os, indent + 2 );
    392422                } // if
    393423                break;
     424          case Basetypeof:
     425                os << "base-";
     426                #if defined(__GNUC__) && __GNUC__ >= 7
     427                        __attribute__((fallthrough));
     428                #endif
    394429          case Typeof:
    395430                os << "type-of expression ";
     
    400435          case Builtin:
    401436                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 ";
    402447                break;
    403448          default:
     
    406451        } // switch
    407452} // TypeData::print
     453
     454const 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}
    408483
    409484
     
    447522        switch ( td->kind ) {
    448523          case TypeData::Unknown:
    449                 // fill in implicit int
    450                 return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
     524                        // fill in implicit int
     525                        return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
    451526          case TypeData::Basic:
    452                 return buildBasicType( td );
     527                        return buildBasicType( td );
    453528          case TypeData::Pointer:
    454                 return buildPointer( td );
     529                        return buildPointer( td );
    455530          case TypeData::Array:
    456                 return buildArray( td );
     531                        return buildArray( td );
    457532          case TypeData::Reference:
    458                 return buildReference( td );
     533                        return buildReference( td );
    459534          case TypeData::Function:
    460                 return buildFunction( td );
     535                        return buildFunction( td );
    461536          case TypeData::AggregateInst:
    462                 return buildAggInst( td );
     537                        return buildAggInst( td );
    463538          case TypeData::EnumConstant:
    464                 // the name gets filled in later -- by SymTab::Validate
    465                 return new EnumInstType( buildQualifiers( td ), "" );
     539                        // the name gets filled in later -- by SymTab::Validate
     540                        return new EnumInstType( buildQualifiers( td ), "" );
    466541          case TypeData::SymbolicInst:
    467                 return buildSymbolicInst( td );;
     542                        return buildSymbolicInst( td );
    468543          case TypeData::Tuple:
    469                 return buildTuple( td );
     544                        return buildTuple( td );
    470545          case TypeData::Typeof:
    471                 return buildTypeof( td );
     546          case TypeData::Basetypeof:
     547                        return buildTypeof( td );
    472548          case TypeData::Builtin:
    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                 }
     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 ) );
    482562          case TypeData::Symbolic:
    483563          case TypeData::Enum:
    484564          case TypeData::Aggregate:
    485                 assert( false );
     565                        assert( false );
    486566        } // switch
     567
    487568        return nullptr;
    488569} // typebuild
     
    585666
    586667          case DeclarationNode::Float:
    587           case DeclarationNode::Float80:
    588           case DeclarationNode::Float128:
    589668          case DeclarationNode::Double:
    590669          case DeclarationNode::LongDouble:                                     // not set until below
    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 },
     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, },
    595682                };
    596683
     
    605692                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    606693                } // 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
    607700                if ( td->length == DeclarationNode::Long ) {
    608701                        const_cast<TypeData *>(td)->basictype = DeclarationNode::LongDouble;
    609702                } // if
    610703
    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 
    620704                ret = floattype[ td->complextype ][ td->basictype - DeclarationNode::Float ];
     705                //printf( "XXXX %d %d %d %d\n", td->complextype, td->basictype, DeclarationNode::Float, ret );
    621706                break;
    622707
     
    858943
    859944TypeofType * buildTypeof( const TypeData * td ) {
    860         assert( td->kind == TypeData::Typeof );
     945        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
    861946        assert( td->typeexpr );
    862947        // assert( td->typeexpr->expr );
    863         return new TypeofType( buildQualifiers( td ), td->typeexpr->build() );
     948        return new TypeofType{
     949                buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof };
    864950} // buildTypeof
    865951
     
    893979        assert( td->kind == TypeData::Function );
    894980        FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis );
    895         buildList( td->function.params, ft->get_parameters() );
    896         buildForall( td->forall, ft->get_forall() );
     981        buildList( td->function.params, ft->parameters );
     982        buildForall( td->forall, ft->forall );
    897983        if ( td->base ) {
    898984                switch ( td->base->kind ) {
    899985                  case TypeData::Tuple:
    900                         buildList( td->base->tuple, ft->get_returnVals() );
     986                        buildList( td->base->tuple, ft->returnVals );
    901987                        break;
    902988                  default:
  • src/Parser/TypeData.h

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 15:18:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 22 15:21:23 2018
    13 // Update Count     : 191
     12// Last Modified On : Thu Nov  1 20:56:46 2018
     13// Update Count     : 196
    1414//
    1515
     
    2626
    2727struct TypeData {
    28         enum Kind { Basic, Pointer, Array, Reference, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
    29                                 SymbolicInst, Tuple, Typeof, Builtin, Unknown };
     28        enum Kind { Basic, Pointer, Reference, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
     29                                SymbolicInst, Tuple, Typeof, Basetypeof, Builtin, GlobalScope, Qualified, Unknown };
    3030
    3131        struct Aggregate_t {
    3232                DeclarationNode::Aggregate kind;
    33                 const std::string * name;
    34                 DeclarationNode * params;
    35                 ExpressionNode * actuals;                                               // holds actual parameters later applied to AggInst
    36                 DeclarationNode * fields;
     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;
    3737                bool body;
     38                bool anon;
    3839
    3940                bool tagged;
    40                 const std::string * parent;
     41                const std::string * parent = nullptr;
    4142        };
    4243
    4344        struct AggInst_t {
    44                 TypeData * aggregate;
    45                 ExpressionNode * params;
     45                TypeData * aggregate = nullptr;
     46                ExpressionNode * params = nullptr;
    4647                bool hoistType;
    4748        };
    4849
    4950        struct Array_t {
    50                 ExpressionNode * dimension;
     51                ExpressionNode * dimension = nullptr;
    5152                bool isVarLen;
    5253                bool isStatic;
     
    5455
    5556        struct Enumeration_t {
    56                 const std::string * name;
    57                 DeclarationNode * constants;
     57                const std::string * name = nullptr;
     58                DeclarationNode * constants = nullptr;
    5859                bool body;
     60                bool anon;
    5961        };
    6062
    6163        struct Function_t {
    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
     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
    6769        };
    6870
    6971        struct Symbolic_t {
    70                 const std::string * name;
     72                const std::string * name = nullptr;
    7173                bool isTypedef;                                                                 // false => TYPEGENname, true => TYPEDEFname
    72                 DeclarationNode * params;
    73                 ExpressionNode * actuals;
    74                 DeclarationNode * assertions;
     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;
    7582        };
    7683
     
    8693
    8794        Type::Qualifiers qualifiers;
    88         DeclarationNode * forall;
     95        DeclarationNode * forall = nullptr;
    8996
    90         // Basic_t basic;
    9197        Aggregate_t aggregate;
    9298        AggInst_t aggInst;
    9399        Array_t array;
    94100        Enumeration_t enumeration;
    95         // Variable_t variable;
    96101        Function_t function;
    97102        Symbolic_t symbolic;
    98         DeclarationNode * tuple;
    99         ExpressionNode * typeexpr;
     103        Qualified_t qualified;
     104        DeclarationNode * tuple = nullptr;
     105        ExpressionNode * typeexpr = nullptr;
    100106
    101107        TypeData( Kind k = Unknown );
     
    103109        void print( std::ostream &, int indent = 0 ) const;
    104110        TypeData * clone() const;
     111
     112        const std::string * leafName() const;
    105113};
    106114
     
    120128TupleType * buildTuple( const TypeData * );
    121129TypeofType * buildTypeof( const TypeData * );
    122 Declaration * 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 * >() );
     130Declaration * 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 * >() );
    123132FunctionType * buildFunction( const TypeData * );
    124133void buildKRFunction( const TypeData::Function_t & function );
  • src/Parser/TypedefTable.cc

    r7951100 rb067d9b  
    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 : Thu Jun  7 13:17:56 2018
    13 // Update Count     : 192
     12// Last Modified On : Wed Jul 25 15:32:35 2018
     13// Update Count     : 258
    1414//
    1515
     
    5151} // TypedefTable::exists
    5252
     53bool TypedefTable::existsCurr( const string & identifier ) {
     54        return kindTable.findAt( kindTable.currentScope() - 1, identifier ) != kindTable.end();
     55} // TypedefTable::exists
     56
    5357int TypedefTable::isKind( const string & identifier ) const {
    5458        KindTable::const_iterator posn = kindTable.find( identifier );
     
    7781        auto scope = kindTable.currentScope();
    7882        debugPrint( cerr << "Adding current at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl );
    79         auto ret = kindTable.insertAt( scope, identifier, kind );
    80         if ( ! ret.second ) ret.first->second = kind;           // exists => update
     83        kindTable.insertAt( scope, identifier, kind );
    8184} // TypedefTable::addToScope
    8285
    8386void TypedefTable::addToEnclosingScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    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 );
     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 );
    8790        auto ret = kindTable.insertAt( scope, identifier, kind );
    88         if ( ! ret.second ) ret.first->second = kind;           // exists => update
     91        if ( ! ret.second ) ret.first->second = kind;   // exists => update
    8992} // TypedefTable::addToEnclosingScope
    9093
    9194void TypedefTable::enterScope() {
    92         kindTable.beginScope();
    93         debugPrint( cerr << "Entering scope " << kindTable.currentScope() << endl );
    94         debugPrint( print() );
     95        kindTable.beginScope( (Note){ 0, false } );
     96        debugPrint( cerr << "Entering scope " << kindTable.currentScope() << " level " << level << endl; print() );
    9597} // TypedefTable::enterScope
    9698
    9799void TypedefTable::leaveScope() {
    98         debugPrint( cerr << "Leaving scope " << kindTable.currentScope() << endl );
    99         debugPrint( print() );
     100        debugPrint( cerr << "Leaving scope " << kindTable.currentScope() << endl; print() );
    100101        kindTable.endScope();
    101102} // TypedefTable::leaveScope
    102103
     104void 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
     110void TypedefTable::down() {
     111        level -= 1;
     112        debugPrint( cerr << "Down " << " level " << level << " note " << kindTable.getNote( level ).level << endl; );
     113} // TypedefTable::down
     114
    103115void TypedefTable::print( void ) const {
    104116        KindTable::size_type scope = kindTable.currentScope();
    105         debugPrint( cerr << "[" << scope << "]" );
     117        debugPrint( cerr << "[" << scope << "] " << kindTable.getNote( scope ).level << ", " << kindTable.getNote( scope ).forall << ":" );
    106118        for ( KindTable::const_iterator i = kindTable.begin(); i != kindTable.end(); i++ ) {
    107119                while ( i.get_level() != scope ) {
    108120                        --scope;
    109                         debugPrint( cerr << endl << "[" << scope << "]" );
     121                        debugPrint( cerr << endl << "[" << scope << "] " << kindTable.getNote( scope ).level << ", " << kindTable.getNote( scope ).forall << ":" );
    110122                } // while
    111123                debugPrint( cerr << " " << (*i).first << ":" << kindName( (*i).second ) );
     
    113125        while ( scope > 0 ) {
    114126                --scope;
    115                 debugPrint( cerr << endl << "[" << scope << "]" );
    116         }
     127                debugPrint( cerr << endl << "[" << scope << "] " << kindTable.getNote( scope ).level << ", " << kindTable.getNote( scope ).forall << ":" );
     128        } // while
    117129        debugPrint( cerr << endl );
    118 }
     130} // TypedefTable::print
    119131
    120132// Local Variables: //
  • src/Parser/TypedefTable.h

    r7951100 rb067d9b  
    1010// Created On       : Sat May 16 15:24:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun  7 12:10:17 2018
    13 // Update Count     : 85
     12// Last Modified On : Wed Jul 25 15:33:55 2018
     13// Update Count     : 114
    1414//
    1515
     
    2323
    2424class TypedefTable {
    25         typedef ScopedMap< std::string, int > KindTable;
     25        struct Note { size_t level; bool forall; };
     26        typedef ScopedMap< std::string, int, Note > KindTable;
    2627        KindTable kindTable;   
     28        unsigned int level = 0;
    2729  public:
    2830        ~TypedefTable();
    2931
    3032        bool exists( const std::string & identifier );
     33        bool existsCurr( const std::string & identifier );
    3134        int isKind( const std::string & identifier ) const;
    3235        void makeTypedef( const std::string & name, int kind = TYPEDEFname );
    3336        void addToScope( const std::string & identifier, int kind, const char * );
    3437        void addToEnclosingScope( const std::string & identifier, int kind, const char * );
     38        bool getEnclForall() { return kindTable.getNote( kindTable.currentScope() -  1 ).forall; }
    3539
    3640        void enterScope();
    3741        void leaveScope();
     42
     43        void up( bool );
     44        void down();
    3845
    3946        void print( void ) const;
  • src/Parser/lex.ll

    r7951100 rb067d9b  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Thu Jun  7 08:27:40 2018
    13  * Update Count     : 679
     12 * Last Modified On : Sun Aug  4 20:53:47 2019
     13 * Update Count     : 719
    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 : "";
    2735unsigned 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
    2936
    3037#include <string>
     
    3239using namespace std;
    3340
     41#include "config.h"                                                                             // configure info
    3442#include "ParseNode.h"
    3543#include "TypedefTable.h"
     
    4957#define NUMERIC_RETURN(x)       rm_underscore(); RETURN_VAL( x ) // numeric constant
    5058#define KEYWORD_RETURN(x)       RETURN_CHAR( x )                        // keyword
    51 #define QKEYWORD_RETURN(x)      typedefTable.isKind( yytext ); RETURN_VAL(x); // quasi-keyword
     59#define QKEYWORD_RETURN(x)      RETURN_VAL(x);                          // quasi-keyword
    5260#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    53 #define ATTRIBUTE_RETURN()      RETURN_VAL( ATTR_IDENTIFIER )
     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
    5467
    5568void rm_underscore() {
     
    7992identifier ([a-zA-Z_$]|{universal_char})([0-9a-zA-Z_$]|{universal_char})*
    8093
    81                                 // attribute identifier, GCC: $ in identifier
    82 attr_identifier "@"{identifier}
    83 
    8494                                // numeric constants, CFA: '_' in constant
    8595hex_quad {hex}("_"?{hex}){3}
    8696size_opt (8|16|32|64|128)?
    87 length ("ll"|"LL"|[lL]{size_opt})|("hh"|"HH"|[hH])
    88 integer_suffix_opt ("_"?(([uU]({length}?[iI]?)|([iI]{length}))|([iI]({length}?[uU]?)|([uU]{length}))|({length}([iI]?[uU]?)|([uU][iI]))|[zZ]))?
     97                                // CFA: explicit l8/l16/l32/l64/l128, char 'hh', short 'h', int 'n'
     98length ("ll"|"LL"|[lL]{size_opt})|("hh"|"HH"|[hHnN])
     99                                // CFA: size_t 'z', pointer 'p', which define a sign and length
     100integer_suffix_opt ("_"?(([uU]({length}?[iI]?)|([iI]{length}))|([iI]({length}?[uU]?)|([uU]{length}))|({length}([iI]?[uU]?)|([uU][iI]))|[zZ]|[pP]))?
    89101
    90102octal_digits ({octal})|({octal}({octal}|"_")*{octal})
     
    105117                                // GCC: D (double) and iI (imaginary) suffixes, and DL (long double)
    106118exponent "_"?[eE]"_"?[+-]?{decimal_digits}
    107 floating_size 32|64|80|128
    108 floating_length ([fFdDlL]|[lL]{floating_size})
     119floating_size 16|32|32x|64|64x|80|128|128x
     120floating_length ([fFdDlLwWqQ]|[fF]{floating_size})
    109121floating_suffix ({floating_length}?[iI]?)|([iI]{floating_length})
    110122floating_suffix_opt ("_"?({floating_suffix}|"DL"))?
     
    202214__attribute__   { KEYWORD_RETURN(ATTRIBUTE); }                  // GCC
    203215auto                    { KEYWORD_RETURN(AUTO); }
     216__auto_type             { KEYWORD_RETURN(AUTO_TYPE); }
     217basetypeof              { KEYWORD_RETURN(BASETYPEOF); }                 // CFA
    204218_Bool                   { KEYWORD_RETURN(BOOL); }                               // C99
    205219break                   { KEYWORD_RETURN(BREAK); }
     
    209223char                    { KEYWORD_RETURN(CHAR); }
    210224choose                  { KEYWORD_RETURN(CHOOSE); }                             // CFA
     225coerce                  { KEYWORD_RETURN(COERCE); }                             // CFA
    211226_Complex                { KEYWORD_RETURN(COMPLEX); }                    // C99
    212227__complex               { KEYWORD_RETURN(COMPLEX); }                    // GCC
     
    232247finally                 { KEYWORD_RETURN(FINALLY); }                    // CFA
    233248float                   { KEYWORD_RETURN(FLOAT); }
    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
    239 float80                 { KEYWORD_RETURN(FLOAT80); }                    // GCC
    240 _Float128               { KEYWORD_RETURN(FLOAT128); }                   // GCC
    241 _Float128x              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    242 __float128              { KEYWORD_RETURN(FLOAT128); }                   // GCC
    243 float128                { KEYWORD_RETURN(FLOAT128); }                   // GCC
     249__float80               { KEYWORD_RETURN(uuFLOAT80); }                  // GCC
     250float80                 { KEYWORD_RETURN(uuFLOAT80); }                  // GCC
     251__float128              { KEYWORD_RETURN(uuFLOAT128); }                 // GCC
     252float128                { 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
    244260for                             { KEYWORD_RETURN(FOR); }
    245261forall                  { KEYWORD_RETURN(FORALL); }                             // CFA
    246262fortran                 { KEYWORD_RETURN(FORTRAN); }
    247263ftype                   { KEYWORD_RETURN(FTYPE); }                              // CFA
     264generator               { KEYWORD_RETURN(GENERATOR); }                  // CFA
    248265_Generic                { KEYWORD_RETURN(GENERIC); }                    // C11
    249266goto                    { KEYWORD_RETURN(GOTO); }
     
    256273__inline__              { KEYWORD_RETURN(INLINE); }                             // GCC
    257274int                             { KEYWORD_RETURN(INT); }
     275int128                  { KEYWORD_RETURN(INT128); }                             // CFA
    258276__int128                { KEYWORD_RETURN(INT128); }                             // GCC
    259 int128                  { KEYWORD_RETURN(INT128); }                             // GCC
     277__int128_t              { KEYWORD_RETURN(INT128); }                             // GCC
    260278__label__               { KEYWORD_RETURN(LABEL); }                              // GCC
    261279long                    { KEYWORD_RETURN(LONG); }
     
    272290__restrict__    { KEYWORD_RETURN(RESTRICT); }                   // GCC
    273291return                  { KEYWORD_RETURN(RETURN); }
     292        /* resume                       { KEYWORD_RETURN(RESUME); }                             // CFA */
    274293short                   { KEYWORD_RETURN(SHORT); }
    275294signed                  { KEYWORD_RETURN(SIGNED); }
     
    280299_Static_assert  { KEYWORD_RETURN(STATICASSERT); }               // C11
    281300struct                  { KEYWORD_RETURN(STRUCT); }
     301        /* suspend                      { KEYWORD_RETURN(SUSPEND); }                    // CFA */
    282302switch                  { KEYWORD_RETURN(SWITCH); }
    283303thread                  { KEYWORD_RETURN(THREAD); }                             // C11
     
    294314__typeof__              { KEYWORD_RETURN(TYPEOF); }                             // GCC
    295315union                   { KEYWORD_RETURN(UNION); }
     316__uint128_t             { KEYWORD_RETURN(UINT128); }                    // GCC
    296317unsigned                { KEYWORD_RETURN(UNSIGNED); }
    297318__builtin_va_list { KEYWORD_RETURN(VALIST); }                   // GCC
     
    313334        IDENTIFIER_RETURN();
    314335}
    315 {attr_identifier} { ATTRIBUTE_RETURN(); }
    316336
    317337                                /* numeric constants */
     
    404424
    405425"@="                    { NAMEDOP_RETURN(ATassign); }                   // CFA
     426"~="                    { NAMEDOP_RETURN(ErangeUpEq); }                 // CFA
     427"-~"                    { NAMEDOP_RETURN(ErangeDown); }                 // CFA
     428"-~="                   { NAMEDOP_RETURN(ErangeDownEq); }               // CFA
    406429
    407430                                /* CFA, operator identifier */
     
    457480void yyerror( const char * errmsg ) {
    458481        SemanticErrorThrow = true;
    459         cout << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
     482        cerr << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
    460483                 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
    461484}
  • src/Parser/module.mk

    r7951100 rb067d9b  
    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 MAINTAINERCLEANFILES += Parser/parser.output
     33SRCDEMANGLE += \
     34        Parser/LinkageSpec.cc
     35
     36
     37MOSTLYCLEANFILES += Parser/lex.cc Parser/parser.cc Parser/parser.hh Parser/parser.output
  • src/Parser/parser.yy

    r7951100 rb067d9b  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun  7 10:07:12 2018
    13 // Update Count     : 3527
     12// Last Modified On : Sun Aug  4 21:48:23 2019
     13// Update Count     : 4364
    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         //cur->addType( specifier );
    102         for ( cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
     101        for ( cur = dynamic_cast<DeclarationNode *>( cur->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
    103102                cl->cloneBaseType( cur );
    104103        } // for
    105104        declList->addType( cl );
    106 //      delete cl;
    107105        return declList;
    108106} // distAttr
     
    114112        } // for
    115113} // distExt
     114
     115void 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
     122void 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
    116151
    117152// There is an ambiguity for inline generic-routine return-types and generic routines.
     
    136171} // build_postfix_name
    137172
    138 bool forall = false, xxx = false;                                               // aggregate have one or more forall qualifiers ?
     173DeclarationNode * 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
     186ForCtrl * 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
     199ForCtrl * 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
     214bool forall = false, yyy = false;                                               // aggregate have one or more forall qualifiers ?
    139215
    140216// https://www.gnu.org/software/bison/manual/bison.html#Location-Type
     
    156232
    157233// Types declaration for productions
    158 %union
    159 {
     234%union {
    160235        Token tok;
    161236        ParseNode * pn;
     
    167242        WaitForStmt * wfs;
    168243        Expression * constant;
    169         IfCtl * ifctl;
    170         ForCtl * fctl;
     244        IfCtrl * ifctl;
     245        ForCtrl * fctl;
     246        enum OperKinds compop;
    171247        LabelNode * label;
    172248        InitializerNode * in;
     
    189265%token RESTRICT                                                                                 // C99
    190266%token ATOMIC                                                                                   // C11
    191 %token FORALL MUTEX VIRTUAL                                                             // CFA
     267%token FORALL MUTEX VIRTUAL COERCE                                              // CFA
    192268%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
    193269%token BOOL COMPLEX IMAGINARY                                                   // C99
    194 %token INT128 FLOAT80 FLOAT128                                                  // GCC
     270%token INT128 UINT128 uuFLOAT80 uuFLOAT128                              // GCC
     271%token uFLOAT16 uFLOAT32 uFLOAT32X uFLOAT64 uFLOAT64X uFLOAT128 // GCC
    195272%token ZERO_T ONE_T                                                                             // CFA
    196273%token VALIST                                                                                   // GCC
    197 %token TYPEOF LABEL                                                                             // GCC
     274%token AUTO_TYPE                                                                                // GCC
     275%token TYPEOF BASETYPEOF LABEL                                                  // GCC
    198276%token ENUM STRUCT UNION
    199277%token EXCEPTION                                                                                // CFA
    200 %token COROUTINE MONITOR THREAD                                                 // CFA
     278%token GENERATOR COROUTINE MONITOR THREAD                               // CFA
    201279%token OTYPE FTYPE DTYPE TTYPE TRAIT                                    // CFA
    202280%token SIZEOF OFFSETOF
     281// %token SUSPEND RESUME                                                                        // CFA
    203282%token ATTRIBUTE EXTENSION                                                              // GCC
    204283%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
     
    210289%token<tok> IDENTIFIER                  QUOTED_IDENTIFIER               TYPEDEFname                             TYPEGENname
    211290%token<tok> TIMEOUT                             WOR
    212 %token<tok> ATTR_IDENTIFIER             ATTR_TYPEDEFname                ATTR_TYPEGENname
    213291%token<tok> INTEGERconstant             CHARACTERconstant               STRINGliteral
    214292%token<tok> DIRECTIVE
     
    231309%token ANDassign        ERassign        ORassign                                // &=   ^=      |=
    232310
     311%token ErangeUpEq       ErangeDown      ErangeDownEq                    // ~=   -~      -~=
    233312%token ATassign                                                                                 // @=
    234313
    235 %type<tok> identifier  no_attr_identifier
    236 %type<tok> identifier_or_type_name  no_attr_identifier_or_type_name  attr_name
     314%type<tok> identifier
     315%type<tok> identifier_or_type_name  attr_name
    237316%type<tok> quasi_keyword
    238317%type<constant> string_literal
     
    252331%type<en> argument_expression_list              argument_expression                     default_initialize_opt
    253332%type<ifctl> if_control_expression
    254 %type<fctl> for_control_expression
     333%type<fctl> for_control_expression              for_control_expression_list
     334%type<compop> inclexcl
    255335%type<en> subrange
    256336%type<decl> asm_name_opt
    257 %type<en> asm_operands_opt asm_operands_list asm_operand
     337%type<en> asm_operands_opt                              asm_operands_list                       asm_operand
    258338%type<label> label_list
    259339%type<en> asm_clobbers_list_opt
    260340%type<flag> asm_volatile_opt
    261341%type<en> handler_predicate_opt
    262 %type<genexpr> generic_association generic_assoc_list
     342%type<genexpr> generic_association              generic_assoc_list
    263343
    264344// statements
     
    304384%type<en> enumerator_value_opt
    305385
    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
     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
    310392
    311393%type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
     
    320402%type<decl> cfa_array_parameter_1st_dimension
    321403
    322 %type<decl> cfa_trait_declaring_list cfa_declaration cfa_field_declaring_list
     404%type<decl> cfa_trait_declaring_list cfa_declaration cfa_field_declaring_list cfa_field_abstract_list
    323405%type<decl> cfa_function_declaration cfa_function_return cfa_function_specifier
    324406
     
    355437%type<decl> type_parameter type_parameter_list type_initializer_opt
    356438
    357 %type<en> type_list
     439%type<en> type_parameters_opt type_list
    358440
    359441%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
     
    390472//   Foo ( *fp )( int );
    391473//   `---'                                              matches start of TYPEGENname '('
    392 // Must be:
     474// must be:
    393475//   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 );
    394480
    395481// Order of these lines matters (low-to-high precedence).
    396482%precedence TYPEGENname
     483%precedence '}'
    397484%precedence '('
     485
     486// %precedence RESUME
     487// %precedence '{'
     488// %precedence ')'
    398489
    399490%locations                                                                                              // support location tracking for error messages
     
    457548identifier:
    458549        IDENTIFIER
    459         | ATTR_IDENTIFIER                                                                       // CFA
    460550        | quasi_keyword
    461         ;
    462 
    463 no_attr_identifier:
    464         IDENTIFIER
    465         | quasi_keyword
     551        | '@'                                                                                           // CFA
     552                { Token tok = { new string( DeclarationNode::anonymous.newName() ), yylval.tok.loc }; $$ = tok; }
    466553        ;
    467554
     
    502589        | '(' comma_expression ')' '`' IDENTIFIER                       // CFA, postfix call
    503590                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $5 ) ), $2 ) ); }
    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; }
     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; }
    510595        | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
    511596                {
     
    514599                        $$ = new ExpressionNode( $5 );
    515600                }
     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; }
    516605        ;
    517606
     
    553642        | postfix_expression '(' argument_expression_list ')'
    554643                { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
    555         | postfix_expression '.' no_attr_identifier
     644        | postfix_expression '.' identifier
    556645                { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
    557646        | postfix_expression '.' INTEGERconstant                        // CFA, tuple index
     
    559648        | postfix_expression FLOATING_FRACTIONconstant          // CFA, tuple index
    560649                { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
    561         | postfix_expression '.' '[' field_list ']'                     // CFA, tuple field selector
     650        | postfix_expression '.' '[' field_name_list ']'        // CFA, tuple field selector
    562651                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    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                 }
     652        | postfix_expression ARROW identifier
     653                { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
    567654        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    568655                { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
    569         | postfix_expression ARROW '[' field_list ']'           // CFA, tuple field selector
     656        | postfix_expression ARROW '[' field_name_list ']'      // CFA, tuple field selector
    570657                { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
    571658        | postfix_expression ICR
     
    586673
    587674argument_expression_list:
    588         argument_expression
     675        // empty
     676                { $$ = nullptr; }
     677        | argument_expression
    589678        | argument_expression_list ',' argument_expression
    590679                { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
     
    592681
    593682argument_expression:
    594         // empty
    595                 { $$ = nullptr; }
    596         // | '@'                                                                                                // use default argument
    597         //      { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
     683        '@'                                                                                                     // CFA, default parameter
     684                { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
     685                // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
    598686        | assignment_expression
    599687        ;
    600688
    601 field_list:                                                                                             // CFA, tuple field selector
     689field_name_list:                                                                                // CFA, tuple field selector
    602690        field
    603         | field_list ',' field                                          { $$ = (ExpressionNode *)$1->set_last( $3 ); }
     691        | field_name_list ',' field                                     { $$ = (ExpressionNode *)$1->set_last( $3 ); }
    604692        ;
    605693
     
    608696        | FLOATING_DECIMALconstant field
    609697                { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }
    610         | FLOATING_DECIMALconstant '[' field_list ']'
     698        | FLOATING_DECIMALconstant '[' field_name_list ']'
    611699                { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple( $3 ) ) ); }
    612700        | field_name '.' field
    613701                { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
    614         | field_name '.' '[' field_list ']'
     702        | field_name '.' '[' field_name_list ']'
    615703                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    616704        | field_name ARROW field
    617705                { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
    618         | field_name ARROW '[' field_list ']'
     706        | field_name ARROW '[' field_name_list ']'
    619707                { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
    620708        ;
     
    625713        | FLOATINGconstant fraction_constants_opt
    626714                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
    627         | no_attr_identifier fraction_constants_opt
     715        | identifier fraction_constants_opt
    628716                {
    629717                        $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     
    683771        | ALIGNOF '(' type_no_function ')'                                      // GCC, type alignment
    684772                { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); }
    685         | OFFSETOF '(' type_no_function ',' no_attr_identifier ')'
     773        | OFFSETOF '(' type_no_function ',' identifier ')'
    686774                { $$ = 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 ) ) ); }
    693775        ;
    694776
     
    711793        | '(' type_no_function ')' cast_expression
    712794                { $$ = 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 ) ); }
    713798        | '(' COROUTINE '&' ')' cast_expression                         // CFA
    714799                { $$ = new ExpressionNode( build_keyword_cast( KeywordCastExpr::Coroutine, $5 ) ); }
     
    722807        | '(' VIRTUAL type_no_function ')' cast_expression      // CFA
    723808                { $$ = 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; }
    724815//      | '(' type_no_function ')' tuple
    725816//              { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
     817        ;
     818
     819qualifier_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
     826cast_modifier:
     827        '-'
     828        | '+'
    726829        ;
    727830
     
    9041007
    9051008labeled_statement:
    906                 // labels cannot be identifiers 0 or 1 or ATTR_IDENTIFIER
     1009                // labels cannot be identifiers 0 or 1
    9071010        identifier_or_type_name ':' attribute_list_opt statement
    908                 {
    909                         $$ = $4->add_label( $1, $3 );
    910                 }
     1011                { $$ = $4->add_label( $1, $3 ); }
    9111012        ;
    9121013
     
    9241025        statement_decl
    9251026        | statement_decl_list statement_decl
    926                 { if ( $1 != 0 ) { $1->set_last( $2 ); $$ = $1; } }
     1027                { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
    9271028        ;
    9281029
     
    9311032                { $$ = new StatementNode( $1 ); }
    9321033        | EXTENSION declaration                                                         // GCC
    933                 {
    934                         distExt( $2 );
    935                         $$ = new StatementNode( $2 );
    936                 }
     1034                { distExt( $2 ); $$ = new StatementNode( $2 ); }
    9371035        | function_definition
    9381036                { $$ = new StatementNode( $1 ); }
    9391037        | EXTENSION function_definition                                         // GCC
    940                 {
    941                         distExt( $2 );
    942                         $$ = new StatementNode( $2 );
    943                 }
     1038                { distExt( $2 ); $$ = new StatementNode( $2 ); }
    9441039        | statement
    9451040        ;
     
    9481043        statement
    9491044        | statement_list_nodecl statement
    950                 { if ( $1 != 0 ) { $1->set_last( $2 ); $$ = $1; } }
     1045                { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
    9511046        ;
    9521047
     
    9921087if_control_expression:
    9931088        comma_expression
    994                 { $$ = new IfCtl( nullptr, $1 ); }
     1089                { $$ = new IfCtrl( nullptr, $1 ); }
    9951090        | c_declaration                                                                         // no semi-colon
    996                 { $$ = new IfCtl( $1, nullptr ); }
     1091                { $$ = new IfCtrl( $1, nullptr ); }
    9971092        | cfa_declaration                                                                       // no semi-colon
    998                 { $$ = new IfCtl( $1, nullptr ); }
     1093                { $$ = new IfCtrl( $1, nullptr ); }
    9991094        | declaration comma_expression                                          // semi-colon separated
    1000                 { $$ = new IfCtl( $1, $2 ); }
     1095                { $$ = new IfCtrl( $1, $2 ); }
    10011096        ;
    10021097
     
    10541149        WHILE '(' push if_control_expression ')' statement pop
    10551150                { $$ = 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 ) ); }
    10561153        | DO statement WHILE '(' comma_expression ')' ';'
    10571154                { $$ = new StatementNode( build_do_while( $5, $2 ) ); }
    1058         | FOR '(' push for_control_expression ')' statement pop
     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
    10591158                { $$ = 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
     1163for_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                }
    10601184        ;
    10611185
    10621186for_control_expression:
    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 ); }
     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
     1222inclexcl:
     1223        '~'
     1224                { $$ = OperKinds::LThan; }
     1225        | ErangeUpEq
     1226                { $$ = OperKinds::LEThan; }
     1227        | ErangeDown
     1228                { $$ = OperKinds::GThan; }
     1229        | ErangeDownEq
     1230                { $$ = OperKinds::GEThan; }
    10671231        ;
    10681232
     
    10971261        | RETURN comma_expression_opt ';'
    10981262                { $$ = new StatementNode( build_return( $2 ) ); }
    1099         | RETURN '{' initializer_list_opt comma_opt '}'
     1263        | RETURN '{' initializer_list_opt comma_opt '}' ';'
    11001264                { 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; }
    11011269        | THROW assignment_expression_opt ';'                           // handles rethrow
    11021270                { $$ = new StatementNode( build_throw( $2 ) ); }
     
    11361304
    11371305waitfor:
    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                 }
     1306        WAITFOR '(' cast_expression ')'
     1307                { $$ = $3; }
     1308        | WAITFOR '(' cast_expression ',' argument_expression_list ')'
     1309                { $$ = (ExpressionNode *)$3->set_last( $5 ); }
    11491310        ;
    11501311
     
    11631324                { $$ = build_waitfor_timeout( nullptr, $3, $1 ); }
    11641325                // "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; }
    11651328        | when_clause_opt timeout statement WOR when_clause ELSE statement
    11661329                { $$ = build_waitfor_timeout( $2, $3, $1, $7, $5 ); }
     
    11841347
    11851348handler_clause:
    1186         handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement pop
     1349        handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
    11871350                { $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); }
    1188         | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement pop
     1351        | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
    11891352                { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $5, $7, $9 ) ) ); }
    11901353        ;
     
    12121375        | type_specifier_nobody variable_abstract_declarator
    12131376                { $$ = $2->addType( $1 ); }
    1214         | cfa_abstract_declarator_tuple no_attr_identifier      // CFA
     1377        | cfa_abstract_declarator_tuple identifier                      // CFA
    12151378                { $$ = $1->addName( $2 ); }
    12161379        | cfa_abstract_declarator_tuple                                         // CFA
     
    12761439
    12771440label_list:
    1278         no_attr_identifier
     1441        identifier
    12791442                {
    12801443                        $$ = new LabelNode(); $$->labels.push_back( *$1 );
    12811444                        delete $1;                                                                      // allocated by lexer
    12821445                }
    1283         | label_list ',' no_attr_identifier
     1446        | label_list ',' identifier
    12841447                {
    12851448                        $$ = $1; $1->labels.push_back( *$3 );
     
    13261489
    13271490local_label_list:                                                                               // GCC, local label
    1328         no_attr_identifier_or_type_name
    1329         | local_label_list ',' no_attr_identifier_or_type_name
     1491        identifier_or_type_name
     1492        | local_label_list ',' identifier_or_type_name
    13301493        ;
    13311494
     
    14491612                        $$ = $2->addTypedef();
    14501613                }
    1451         | cfa_typedef_declaration pop ',' push no_attr_identifier
     1614        | cfa_typedef_declaration pop ',' push identifier
    14521615                {
    14531616                        typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "3" );
     
    14891652typedef_expression:
    14901653                // GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
    1491         TYPEDEF no_attr_identifier '=' assignment_expression
     1654        TYPEDEF identifier '=' assignment_expression
    14921655                {
    14931656                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
    14941657                        SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
    14951658                }
    1496         | typedef_expression pop ',' push no_attr_identifier '=' assignment_expression
     1659        | typedef_expression pop ',' push identifier '=' assignment_expression
    14971660                {
    14981661                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
     
    16631826        | INT128
    16641827                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 ); }
     1828        | UINT128
     1829                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ); }
    16651830        | FLOAT
    16661831                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
    1667         | FLOAT80
    1668                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Float80 ); }
    1669         | FLOAT128
    1670                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Float128 ); }
    16711832        | DOUBLE
    16721833                { $$ = 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 ); }
    16731850        | COMPLEX                                                                                       // C99
    16741851                { $$ = DeclarationNode::newComplexType( DeclarationNode::Complex ); }
     
    16851862        | VALIST                                                                                        // GCC, __builtin_va_list
    16861863                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Valist ); }
     1864        | AUTO_TYPE
     1865                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::AutoType ); }
    16871866        ;
    16881867
     
    17181897
    17191898indirect_type:
    1720         TYPEOF '(' type ')'                                                                     // GCC: typeof(x) y;
     1899        TYPEOF '(' type ')'                                                                     // GCC: typeof( x ) y;
    17211900                { $$ = $3; }
    1722         | TYPEOF '(' comma_expression ')'                                       // GCC: typeof(a+b) y;
     1901        | TYPEOF '(' comma_expression ')'                                       // GCC: typeof( a+b ) y;
    17231902                { $$ = DeclarationNode::newTypeof( $3 ); }
    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 ); }
     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 ); }
    17281907        | ZERO_T                                                                                        // CFA
    17291908                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Zero ); }
     
    17491928                { $$ = $3->addQualifiers( $1 ); }
    17501929        | sue_type_specifier type_qualifier
    1751                 { $$ = $1->addQualifiers( $2 ); }
     1930                {
     1931                        if ( $2->type != nullptr && $2->type->forall ) forall = true; // remember generic type
     1932                        $$ = $1->addQualifiers( $2 );
     1933                }
    17521934        ;
    17531935
     
    17921974                { $$ = DeclarationNode::newFromTypedef( $1 ); }
    17931975        | '.' TYPEDEFname
    1794                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1976                { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), DeclarationNode::newFromTypedef( $2 ) ); }
    17951977        | type_name '.' TYPEDEFname
    1796                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1978                { $$ = DeclarationNode::newQualifiedType( $1, DeclarationNode::newFromTypedef( $3 ) ); }
    17971979        | typegen_name
    17981980        | '.' typegen_name
    1799                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1981                { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), $2 ); }
    18001982        | type_name '.' typegen_name
    1801                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     1983                { $$ = DeclarationNode::newQualifiedType( $1, $3 ); }
    18021984        ;
    18031985
     
    18212003        ;
    18222004
     2005fred:
     2006        // empty
     2007                { yyy = false; }
     2008        ;
     2009
    18232010aggregate_type:                                                                                 // struct, union
    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
     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
    18302018                        forall = false;                                                         // reset
    18312019                }
    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
     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
    18382026                        forall = false;                                                         // reset
    18392027                }
    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 ); }
     2028          '{' field_declaration_list_opt '}' type_parameters_opt
     2029                { $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $9, $7, true )->addQualifiers( $2 ); }
    18442030        | aggregate_type_nobody
    18452031        ;
    18462032
     2033type_parameters_opt:
     2034        // empty
     2035                { $$ = nullptr; }                                                               %prec '}'
     2036        | '(' type_list ')'
     2037                { $$ = $2; }
     2038        ;
     2039
    18472040aggregate_type_nobody:                                                                  // struct, union - {...}
    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
     2041        aggregate_key attribute_list_opt identifier fred
     2042                {
     2043                        typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname );
    18522044                        forall = false;                                                         // reset
    18532045                        $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
    18542046                }
    1855         | aggregate_key attribute_list_opt type_name
    1856                 {
     2047        | aggregate_key attribute_list_opt type_name fred
     2048                {
     2049                        forall = false;                                                         // reset
    18572050                        // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is
    18582051                        // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and
     
    18672060aggregate_key:
    18682061        STRUCT
    1869                 { $$ = DeclarationNode::Struct; }
     2062                { yyy = true; $$ = DeclarationNode::Struct; }
    18702063        | UNION
    1871                 { $$ = DeclarationNode::Union; }
     2064                { yyy = true; $$ = DeclarationNode::Union; }
    18722065        | EXCEPTION
    1873                 { $$ = DeclarationNode::Exception; }
     2066                { yyy = true; $$ = DeclarationNode::Exception; }
     2067        | GENERATOR
     2068                { yyy = true; $$ = DeclarationNode::Coroutine; }
    18742069        | COROUTINE
    1875                 { $$ = DeclarationNode::Coroutine; }
     2070                { yyy = true; $$ = DeclarationNode::Coroutine; }
    18762071        | MONITOR
    1877                 { $$ = DeclarationNode::Monitor; }
     2072                { yyy = true; $$ = DeclarationNode::Monitor; }
    18782073        | THREAD
    1879                 { $$ = DeclarationNode::Thread; }
     2074                { yyy = true; $$ = DeclarationNode::Thread; }
    18802075        ;
    18812076
     
    18882083
    18892084field_declaration:
    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
     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                }
    18942098        | typedef_declaration ';'                                                       // CFA
    1895                 { SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
    18962099        | cfa_field_declaring_list ';'                                          // CFA, new style field declaration
    18972100        | EXTENSION cfa_field_declaring_list ';'                        // GCC
    18982101                { 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
    18992104        | cfa_typedef_declaration ';'                                           // CFA
    1900                 { SemanticError( yylloc, "Typedef in aggregate is currently unimplemented." ); $$ = nullptr; }
    19012105        | static_assert                                                                         // C11
    19022106        ;
    19032107
    1904 cfa_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 
    1914 field_declaring_list:
    1915         field_declarator_opt
    1916         | field_declaring_list ',' attribute_list_opt field_declarator_opt
     2108field_declaring_list_opt:
     2109        // empty
     2110                { $$ = nullptr; }
     2111        | field_declarator
     2112        | field_declaring_list_opt ',' attribute_list_opt field_declarator
    19172113                { $$ = $1->appendList( $4->addQualifiers( $3 ) ); }
    19182114        ;
    19192115
    1920 field_declarator_opt:
    1921         // empty
    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
     2116field_declarator:
     2117        bit_subrange_size                                                                       // C special case, no field name
    19262118                { $$ = DeclarationNode::newBitfield( $1 ); }
    19272119        | variable_declarator bit_subrange_size_opt
    1928                 // A semantic check is required to ensure bit_subrange only appears on base type int.
     2120                // A semantic check is required to ensure bit_subrange only appears on integral types.
    19292121                { $$ = $1->addBitfield( $2 ); }
    19302122        | variable_type_redeclarator bit_subrange_size_opt
    1931                 // A semantic check is required to ensure bit_subrange only appears on base type int.
     2123                // A semantic check is required to ensure bit_subrange only appears on integral types.
    19322124                { $$ = $1->addBitfield( $2 ); }
    1933         | variable_abstract_declarator                                          // CFA, no field name
     2125        ;
     2126
     2127field_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
     2135field_abstract:
     2136                //      no bit fields
     2137        variable_abstract_declarator
     2138        ;
     2139
     2140cfa_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
     2148cfa_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 ) ); }
    19342153        ;
    19352154
     
    19412160
    19422161bit_subrange_size:
    1943         ':' constant_expression
     2162        ':' assignment_expression
    19442163                { $$ = $2; }
    19452164        ;
     
    19472166enum_type:                                                                                              // enum
    19482167        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    1949                 { $$ = DeclarationNode::newEnum( new string( DeclarationNode::anonymous.newName() ), $4, true )->addQualifiers( $2 ); }
    1950         | ENUM attribute_list_opt no_attr_identifier
     2168                { $$ = DeclarationNode::newEnum( nullptr, $4, true )->addQualifiers( $2 ); }
     2169        | ENUM attribute_list_opt identifier
    19512170                { typedefTable.makeTypedef( *$3 ); }
    19522171          '{' enumerator_list comma_opt '}'
     
    19592178
    19602179enum_type_nobody:                                                                               // enum - {...}
    1961         ENUM attribute_list_opt no_attr_identifier
     2180        ENUM attribute_list_opt identifier
    19622181                {
    19632182                        typedefTable.makeTypedef( *$3 );
     
    19722191
    19732192enumerator_list:
    1974         no_attr_identifier_or_type_name enumerator_value_opt
     2193        identifier_or_type_name enumerator_value_opt
    19752194                { $$ = DeclarationNode::newEnumConstant( $1, $2 ); }
    1976         | enumerator_list ',' no_attr_identifier_or_type_name enumerator_value_opt
     2195        | enumerator_list ',' identifier_or_type_name enumerator_value_opt
    19772196                { $$ = $1->appendList( DeclarationNode::newEnumConstant( $3, $4 ) ); }
    19782197        ;
     
    20822301
    20832302identifier_list:                                                                                // K&R-style parameter list => no types
    2084         no_attr_identifier
     2303        identifier
    20852304                { $$ = DeclarationNode::newName( $1 ); }
    2086         | identifier_list ',' no_attr_identifier
     2305        | identifier_list ',' identifier
    20872306                { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
    20882307        ;
     
    20902309identifier_or_type_name:
    20912310        identifier
    2092         | TYPEDEFname
    2093         | TYPEGENname
    2094         ;
    2095 
    2096 no_attr_identifier_or_type_name:
    2097         no_attr_identifier
    20982311        | TYPEDEFname
    20992312        | TYPEGENname
     
    21502363designation:
    21512364        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    2152         | no_attr_identifier ':'                                                        // GCC, field name
     2365        | identifier ':'                                                                        // GCC, field name
    21532366                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    21542367        ;
     
    21622375
    21632376designator:
    2164         '.' no_attr_identifier                                                          // C99, field name
     2377        '.' identifier                                                                          // C99, field name
    21652378                { $$ = new ExpressionNode( build_varref( $2 ) ); }
    21662379        | '[' push assignment_expression pop ']'                        // C99, single array element
     
    21712384        | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
    21722385                { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild< Expression >( $3 ), maybeMoveBuild< Expression >( $5 ) ) ); }
    2173         | '.' '[' push field_list pop ']'                                       // CFA, tuple field selector
     2386        | '.' '[' push field_name_list pop ']'                          // CFA, tuple field selector
    21742387                { $$ = $4; }
    21752388        ;
     
    22072420
    22082421type_parameter:                                                                                 // CFA
    2209         type_class no_attr_identifier_or_type_name
     2422        type_class identifier_or_type_name
    22102423                { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
    22112424          type_initializer_opt assertion_list_opt
     
    22402453
    22412454assertion:                                                                                              // CFA
    2242         '|' no_attr_identifier_or_type_name '(' type_list ')'
     2455        '|' identifier_or_type_name '(' type_list ')'
    22432456                { $$ = DeclarationNode::newTraitUse( $2, $4 ); }
    22442457        | '|' '{' push trait_declaration_list pop '}'
     
    22522465                { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
    22532466        | assignment_expression
     2467                { SemanticError( yylloc, toString("Expression generic parameters are currently unimplemented: ", $1->build()) ); $$ = nullptr; }
    22542468        | type_list ',' type
    22552469                { $$ = (ExpressionNode *)( $1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) ) ); }
    22562470        | type_list ',' assignment_expression
    2257                 { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
     2471                { SemanticError( yylloc, toString("Expression generic parameters are currently unimplemented: ", $3->build()) ); $$ = nullptr; }
     2472                // { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
    22582473        ;
    22592474
     
    22752490
    22762491type_declarator_name:                                                                   // CFA
    2277         no_attr_identifier_or_type_name
     2492        identifier_or_type_name
    22782493                {
    22792494                        typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
    22802495                        $$ = DeclarationNode::newTypeDecl( $1, 0 );
    22812496                }
    2282         | no_attr_identifier_or_type_name '(' type_parameter_list ')'
     2497        | identifier_or_type_name '(' type_parameter_list ')'
    22832498                {
    22842499                        typedefTable.addToEnclosingScope( *$1, TYPEGENname, "11" );
     
    22882503
    22892504trait_specifier:                                                                                // CFA
    2290         TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' '}'
     2505        TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    22912506                { $$ = DeclarationNode::newTrait( $2, $4, 0 ); }
    2292         | TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
     2507        | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    22932508                { $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
    22942509        ;
     
    23222537
    23232538translation_unit:
    2324         // empty
    2325                 {}                                                                                              // empty input file
     2539        // empty, input file
    23262540        | external_definition_list
    23272541                { parseTree = parseTree ? parseTree->appendList( $1 ) : $1;     }
     
    23312545        push external_definition pop
    23322546                { $$ = $2; }
    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.
    2345 external_definition_list_no_pop_push:
    2346         external_definition
    2347         | external_definition_list_no_pop_push
    2348                 { forall = xxx; }
    2349           external_definition
     2547        | external_definition_list push external_definition pop
    23502548                { $$ = $1 ? $1->appendList( $3 ) : $3; }
    23512549        ;
     
    23542552        // empty
    23552553                { $$ = nullptr; }
    2356         | external_definition_list_no_pop_push
     2554        | external_definition_list
     2555        ;
     2556
     2557up:
     2558                { typedefTable.up( forall ); forall = false; }
     2559        ;
     2560
     2561down:
     2562                { typedefTable.down(); }
    23572563        ;
    23582564
     
    23742580                        linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
    23752581                }
    2376           '{' external_definition_list_opt '}'
     2582          '{' up external_definition_list_opt down '}'
    23772583                {
    23782584                        linkage = linkageStack.top();
    23792585                        linkageStack.pop();
     2586                        $$ = $6;
     2587                }
     2588        | 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;
    23802597                        $$ = $5;
    23812598                }
    2382         | type_qualifier_list
    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                 }
    23952599        | 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;
     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;
    24072609                }
    24082610        | declaration_qualifier_list type_qualifier_list
    24092611                {
    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;
    2424                         $$ = $5;
     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;
    24252620                }
    24262621        ;
     
    27322927        typedef
    27332928                // hide type name in enclosing scope by variable name
    2734                 { typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER, "ID" ); }
     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                }
    27352936        | '(' paren_type ')'
    27362937                { $$ = $2; }
     
    27432944                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    27442945        | '(' type_ptr ')' attribute_list_opt
    2745                 { $$ = $2->addQualifiers( $4 ); }
     2946                { $$ = $2->addQualifiers( $4 ); }                               // redundant parenthesis
    27462947        ;
    27472948
  • src/ResolvExpr/AdjustExprType.cc

    r7951100 rb067d9b  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // AdjustExprType.cc --
     7// AdjustExprType_old.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"
    1621#include "Common/PassVisitor.h"
    1722#include "SymTab/Indexer.h"       // for Indexer
     
    2227
    2328namespace ResolvExpr {
    24         class AdjustExprType : public WithShortCircuiting {
    25           public:
    26                 AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer );
     29
     30namespace {
     31        class AdjustExprType_old final : public WithShortCircuiting {
     32                public:
     33                AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer );
    2734                void premutate( VoidType * ) { visit_children = false; }
    2835                void premutate( BasicType * ) { visit_children = false; }
     
    4047                void premutate( OneType * ) { visit_children = false; }
    4148
    42                 Type * postmutate( ArrayType *arrayType );
    43                 Type * postmutate( FunctionType *functionType );
    44                 Type * postmutate( TypeInstType *aggregateUseType );
     49                Type * postmutate( ArrayType * arrayType );
     50                Type * postmutate( FunctionType * functionType );
     51                Type * postmutate( TypeInstType * aggregateUseType );
    4552
    46           private:
     53                private:
    4754                const TypeEnvironment & env;
    4855                const SymTab::Indexer & indexer;
    4956        };
    5057
    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 )
     58        AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer )
    6459                : env( env ), indexer( indexer ) {
    6560        }
    6661
    67         Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
    68                 PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
     62        Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) {
     63                PointerType * pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
    6964                arrayType->base = nullptr;
    7065                delete arrayType;
     
    7267        }
    7368
    74         Type * AdjustExprType::postmutate( FunctionType * functionType ) {
     69        Type * AdjustExprType_old::postmutate( FunctionType * functionType ) {
    7570                return new PointerType{ Type::Qualifiers(), functionType };
    7671        }
    7772
    78         Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
    79                 if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) {
     73        Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) {
     74                if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
    8075                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    8176                                return new PointerType{ Type::Qualifiers(), typeInst };
    8277                        }
    83                 } else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
    84                         if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
     78                } else if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
     79                        if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl * >( ntDecl ) ) {
    8580                                if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
    8681                                        return new PointerType{ Type::Qualifiers(), typeInst };
     
    9085                return typeInst;
    9186        }
     87} // anonymous namespace
     88
     89void 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
     95void adjustExprType( Type *& type ) {
     96        TypeEnvironment env;
     97        SymTab::Indexer indexer;
     98        adjustExprType( type, env, indexer );
     99}
     100
     101namespace {
     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
     150const 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
    92157} // namespace ResolvExpr
    93158
  • src/ResolvExpr/Alternative.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:44:23 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 16 23:54:23 2015
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Thu Oct 11 10:55:00 2018
     13// Update Count     : 3
    1414//
    1515
     
    2020#include <utility>                       // for move
    2121
    22 #include "Common/utility.h"              // for maybeClone
     22#include "Common/utility.h"              // for cloneAll
    2323#include "ResolvExpr/Cost.h"             // for Cost, Cost::zero, operator<<
    2424#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     
    2727
    2828namespace ResolvExpr {
    29         Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {}
     29        Alternative::Alternative()
     30        : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {}
    3031
    31         Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
    32                 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {}
     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 ); }
    3338
    34         Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost )
    35                 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
     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 ); }
    3643
    37         Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
    38         }
     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 ); }
    3974
    4075        Alternative &Alternative::operator=( const Alternative &other ) {
     
    4580                expr = maybeClone( other.expr );
    4681                env = other.env;
     82                openVars = other.openVars;
     83                need.clear();
     84                cloneAll( other.need, need );
    4785                return *this;
    4886        }
    4987
    50         Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) {
    51                 other.expr = nullptr;
    52         }
     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; }
    5392
    5493        Alternative & Alternative::operator=( Alternative && other ) {
     
    5998                expr = other.expr;
    6099                env = std::move( other.env );
     100                openVars = std::move( other.openVars );
     101                need = std::move( other.need );
    61102                other.expr = nullptr;
    62103                return *this;
     
    64105
    65106        Alternative::~Alternative() {
     107                for ( AssertionItem& n : need ) { delete n.decl; }
    66108                delete expr;
    67109        }
     
    78120                        os << "Null expression!" << std::endl;
    79121                } // if
    80                 os << indent << "Environment: ";
     122                os << indent << "Environment:";
    81123                env.print( os, indent+1 );
    82124                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 );
    96125        }
    97126
  • src/ResolvExpr/Alternative.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:45:43 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:36:36 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Thu Oct 11 10:55:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2020
    2121#include "Cost.h"             // for Cost
    22 #include "TypeEnvironment.h"  // for TypeEnvironment
     22#include "TypeEnvironment.h"  // for TypeEnvironment, AssertionSetValue
     23
     24#include "Common/utility.h"   // for maybeClone
    2325
    2426class Expression;
    2527
    2628namespace 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
    2770        struct Alternative {
    2871                Alternative();
    29                 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost );
    30                 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost );
     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 );
    3186                Alternative( const Alternative &other );
    3287                Alternative &operator=( const Alternative &other );
     
    4499                }
    45100
    46                 Cost cost;
    47                 Cost cvtCost;
    48                 Expression *expr;
    49                 TypeEnvironment env;
     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
    50110        };
    51111
    52112        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 );
    59113
    60114        static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) {
  • src/ResolvExpr/AlternativeFinder.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:52:08 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:39 2018
    13 // Update Count     : 33
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Aug  8 16:35:00 2019
     13// Update Count     : 38
    1414//
    1515
     
    2525#include <vector>                  // for vector
    2626
     27#include "CompilationState.h"      // for resolvep
    2728#include "Alternative.h"           // for AltList, Alternative
    2829#include "AlternativeFinder.h"
     30#include "AST/Expr.hpp"
     31#include "AST/SymbolTable.hpp"
     32#include "AST/Type.hpp"
    2933#include "Common/SemanticError.h"  // for SemanticError
    3034#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
     
    3337#include "InitTweak/InitTweak.h"   // for getFunctionName
    3438#include "RenameVars.h"            // for RenameVars, global_renamer
     39#include "ResolveAssertions.h"     // for resolveAssertions
    3540#include "ResolveTypeof.h"         // for resolveTypeof
    3641#include "Resolver.h"              // for resolveStmtExpr
     
    4954#include "typeops.h"               // for adjustExprType, polyCost, castCost
    5055
    51 extern bool resolvep;
    5256#define PRINT( text ) if ( resolvep ) { text }
    5357//#define DEBUG_COST
    54 
    55 using std::move;
    56 
    57 /// copies any copyable type
    58 template<typename T>
    59 T copy(const T& x) { return x; }
    6058
    6159namespace ResolvExpr {
     
    8179                void postvisit( OffsetofExpr * offsetofExpr );
    8280                void postvisit( OffsetPackExpr * offsetPackExpr );
    83                 void postvisit( AttrExpr * attrExpr );
    8481                void postvisit( LogicalExpr * logicalExpr );
    8582                void postvisit( ConditionalExpr * conditionalExpr );
     
    10299                void addAnonConversions( const Alternative & alt );
    103100                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    104                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
     101                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
    105102                /// Adds alternatives for member expressions where the left side has tuple type
    106                 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
     103                void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
    107104                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    108105                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    112109                /// Finds matching alternatives for a function, given a set of arguments
    113110                template<typename OutputIterator>
    114                 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    115                 /// Checks if assertion parameters match for a new alternative
     111                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out );
     112                /// Sets up parameter inference for an output alternative
    116113                template< typename OutputIterator >
    117                 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     114                void inferParameters( Alternative &newAlt, OutputIterator out );
    118115        private:
    119116                AlternativeFinder & altFinder;
     
    133130
    134131        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) {
    135                 Indenter indent = { Indenter::tabsize, indentAmt };
     132                Indenter indent = { indentAmt };
    136133                for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    137134                        i->print( os, indent );
     
    176173                                                selected[ mangleName ] = current;
    177174                                        } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
    178                                                 PRINT(
    179                                                         std::cerr << "marking ambiguous" << std::endl;
    180                                                 )
    181                                                 mapPlace->second.isAmbiguous = true;
     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                                                }
    182189                                        } else {
    183190                                                PRINT(
     
    234241        }
    235242
    236         void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
     243        void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
    237244                PassVisitor<Finder> finder( *this );
    238245                expr->accept( finder );
    239                 if ( failFast && alternatives.empty() ) {
     246                if ( mode.failFast && alternatives.empty() ) {
    240247                        PRINT(
    241248                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    243250                        SemanticError( expr, "No reasonable alternatives for expression " );
    244251                }
    245                 if ( prune ) {
     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 ) {
    246275                        auto oldsize = alternatives.size();
    247276                        PRINT(
     
    251280                        AltList pruned;
    252281                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    253                         if ( failFast && pruned.empty() ) {
     282                        if ( mode.failFast && pruned.empty() ) {
    254283                                std::ostringstream stream;
    255284                                AltList winners;
     
    270299                }
    271300                // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    272                 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    273                         if ( adjust ) {
    274                                 adjustExprType( i->expr->get_result(), i->env, indexer );
     301                if ( mode.adjust ) {
     302                        for ( Alternative& i : alternatives ) {
     303                                adjustExprType( i.expr->get_result(), i.env, indexer );
    275304                        }
    276305                }
     
    284313
    285314        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    286                 find( expr, true );
     315                find( expr, ResolvMode::withAdjustment() );
    287316        }
    288317
    289318        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    290                 find( expr, true, false );
     319                find( expr, ResolvMode::withoutPrune() );
    291320        }
    292321
    293322        void AlternativeFinder::maybeFind( Expression * expr ) {
    294                 find( expr, true, true, false );
     323                find( expr, ResolvMode::withoutFailFast() );
    295324        }
    296325
     
    306335                }
    307336
    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, "" );
     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, "" );
    312341                } // if
    313342        }
    314343
    315344        template< typename StructOrUnionType >
    316         void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
     345        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
    317346                std::list< Declaration* > members;
    318347                aggInst->lookup( name, members );
    319348
    320349                for ( Declaration * decl : members ) {
    321                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
     350                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
    322351                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    323352                                // can't construct in place and use vector::back
    324                                 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
     353                                Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
    325354                                renameTypes( newAlt.expr );
    326355                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    332361        }
    333362
    334         void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
     363        void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) {
    335364                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    336365                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    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;
     366                        auto val = constantExpr->intValue();
    341367                        std::string tmp;
    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
     368                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
     369                                alternatives.push_back( Alternative{
     370                                        alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
    346371                        } // 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                         }
    355372                } // if
    356373        }
    357374
    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 ) {
     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 ) {
    363381                PRINT(
    364382                        std::cerr << std::endl << "converting ";
     
    370388                        std::cerr << std::endl;
    371389                )
    372                 Cost convCost = conversionCost( actualType, formalType, indexer, env );
     390                Cost convCost = conversionCost( actualType, formalType, actualIsLvalue, indexer, env );
    373391                PRINT(
    374392                        std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    385403
    386404        Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
    387                 Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env );
     405                Cost convCost = computeConversionCost(
     406                        actualExpr->result, formalType, actualExpr->get_lvalue(), indexer, env );
    388407
    389408                // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion.
     
    413432        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    414433                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
    415                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    416                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
     434                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
     435                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
    417436
    418437                Cost convCost = Cost::zero;
    419                 std::list< DeclarationWithType* >& formals = function->get_parameters();
     438                std::list< DeclarationWithType* >& formals = function->parameters;
    420439                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    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();
     440                std::list< Expression* >& actuals = appExpr->args;
     441
     442                for ( Expression*& actualExpr : actuals ) {
     443                        Type * actualType = actualExpr->result;
    425444                        PRINT(
    426445                                std::cerr << "actual expression:" << std::endl;
    427                                 (*actualExpr)->print( std::cerr, 8 );
     446                                actualExpr->print( std::cerr, 8 );
    428447                                std::cerr << "--- results are" << std::endl;
    429448                                actualType->print( std::cerr, 8 );
    430449                        )
    431450                        if ( formal == formals.end() ) {
    432                                 if ( function->get_isVarArgs() ) {
     451                                if ( function->isVarArgs ) {
    433452                                        convCost.incUnsafe();
    434453                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    435454                                        // convert reference-typed expressions to value-typed expressions
    436                                         referenceToRvalueConversion( *actualExpr, convCost );
     455                                        referenceToRvalueConversion( actualExpr, convCost );
    437456                                        continue;
    438457                                } else {
     
    440459                                }
    441460                        }
     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
    442469                        Type * formalType = (*formal)->get_type();
    443                         convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
     470                        convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
     471                        convCost.decSpec( specCost( formalType ) );
    444472                        ++formal; // can't be in for-loop update because of the continue
    445473                }
     
    448476                }
    449477
    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 );
     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() );
    452490                }
    453491
     
    462500                                needAssertions[ *assert ].isUsed = true;
    463501                        }
    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         }
     502                }
     503        }
     504
     505        /// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp)
     506        extern UniqueId globalResnSlot;
    580507
    581508        template< typename OutputIterator >
    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 //          )
     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;
    608525        }
    609526
     
    611528        ConstantExpr* getDefaultValue( Initializer* init ) {
    612529                if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    613                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
    614                                 return dynamic_cast<ConstantExpr*>( ce->get_arg() );
     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 );
    615534                        }
    616535                }
     
    659578
    660579                /// Gets the list of exploded alternatives for this pack
    661                 const ExplodedActual& getExpl( const ExplodedArgs& args ) const {
     580                const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const {
    662581                        return args[nextArg-1][explAlt];
    663582                }
     
    683602        /// Instantiates an argument to match a formal, returns false if no results left
    684603        bool instantiateArgument( Type* formalType, Initializer* initializer,
    685                         const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
     604                        const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart,
    686605                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    687606                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    873792                                                                indexer ) ) {
    874793                                                        results.emplace_back(
    875                                                                 i, cnstExpr, move(env), move(need), move(have),
     794                                                                i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
    876795                                                                move(openVars), nextArg, nTuples );
    877796                                                }
     
    944863                }
    945864                // build and validate new alternative
    946                 Alternative newAlt( appExpr, result.env, cost );
     865                Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
    947866                PRINT(
    948867                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    950869                        printAssertionSet( result.need, std::cerr, 8 );
    951870                )
    952                 inferParameters( result.need, result.have, newAlt, result.openVars, out );
     871                inferParameters( newAlt, out );
    953872        }
    954873
    955874        template<typename OutputIterator>
    956875        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    957                         FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
     876                        FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) {
    958877                OpenVarSet funcOpenVars;
    959878                AssertionSet funcNeed, funcHave;
     
    1065984                funcFinder.findWithAdjustment( untypedExpr->function );
    1066985                // 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.
    1067987                if ( funcFinder.alternatives.empty() ) return;
    1068988
     
    10861006
    10871007                // pre-explode arguments
    1088                 ExplodedArgs argExpansions;
     1008                ExplodedArgs_old argExpansions;
    10891009                argExpansions.reserve( argAlternatives.size() );
    10901010
     
    10921012                        argExpansions.emplace_back();
    10931013                        auto& argE = argExpansions.back();
    1094                         argE.reserve( arg.alternatives.size() );
     1014                        // argE.reserve( arg.alternatives.size() );
    10951015
    10961016                        for ( const Alternative& actual : arg ) {
     
    11781098                                std::cerr << "bindings are:" << std::endl;
    11791099                                withFunc.env.print( std::cerr, 8 );
     1100                                std::cerr << "cost is: " << withFunc.cost << std::endl;
    11801101                                std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    11811102                        )
     
    11931114
    11941115                // function may return struct or union value, in which case we need to add alternatives
    1195                 // for implicitconversions to each of the anonymous members, must happen after findMinCost
     1116                // for implicit conversions to each of the anonymous members, must happen after findMinCost
    11961117                // since anon conversions are never the cheapest expression
    11971118                for ( const Alternative & alt : winners ) {
     
    12161137        bool isLvalue( Expression *expr ) {
    12171138                // xxx - recurse into tuples?
    1218                 return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
     1139                return expr->result && ( expr->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
    12191140        }
    12201141
     
    12251146                        if ( isLvalue( alt.expr ) ) {
    12261147                                alternatives.push_back(
    1227                                         Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
     1148                                        Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
    12281149                        } // if
    12291150                } // for
     
    12311152
    12321153        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1233                 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
     1154                alternatives.push_back( Alternative{ expr->clone(), env } );
    12341155        }
    12351156
     
    12671188                assert( toType );
    12681189                toType = resolveTypeof( toType, indexer );
     1190                assert(!dynamic_cast<TypeofType *>(toType));
    12691191                SymTab::validateType( toType, &indexer );
    12701192                adjustExprType( toType, env, indexer );
     
    12761198                AltList candidates;
    12771199                for ( Alternative & alt : finder.alternatives ) {
    1278                         AssertionSet needAssertions, haveAssertions;
    1279                         OpenVarSet openVars;
     1200                        AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
     1201                        AssertionSet haveAssertions;
     1202                        OpenVarSet openVars{ alt.openVars };
    12801203
    12811204                        alt.env.extractOpenVars( openVars );
     
    12921215                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12931216                                haveAssertions, openVars, indexer );
    1294                         Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,
    1295                                 alt.env );
     1217                        Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),
     1218                                indexer, alt.env );
    12961219                        PRINT(
    12971220                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     
    13051228                                // count one safe conversion for each value that is thrown away
    13061229                                thisCost.incSafe( discardedValues );
    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 ) );
     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 ) );
    13111234                        } // if
    13121235                } // for
     
    13211244
    13221245        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1323                 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
     1246                assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
    13241247                AlternativeFinder finder( indexer, env );
    13251248                // don't prune here, since it's guaranteed all alternatives will have the same type
    13261249                finder.findWithoutPrune( castExpr->get_arg() );
    13271250                for ( Alternative & alt : finder.alternatives ) {
    1328                         alternatives.push_back( Alternative(
    1329                                 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),
    1330                                 alt.env, alt.cost ) );
     1251                        alternatives.push_back( Alternative{
     1252                                alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
     1253                                alt.cost } );
    13311254                }
    13321255        }
     
    13351258                /// Gets name from untyped member expression (member must be NameExpr)
    13361259                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
    13371263                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
    13381264                        assert( nameExpr );
     
    13531279                        // find member of the given type
    13541280                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1355                                 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1281                                addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13561282                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1357                                 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1283                                addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13581284                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1359                                 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
     1285                                addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
    13601286                        } // if
    13611287                } // for
     
    13631289
    13641290        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1365                 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
     1291                alternatives.push_back( Alternative{ memberExpr->clone(), env } );
    13661292        }
    13671293
     
    13761302                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13771303                        // can't construct in place and use vector::back
    1378                         Alternative newAlt( newExpr, env, Cost::zero, cost );
     1304                        Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
    13791305                        PRINT(
    13801306                                std::cerr << "decl is ";
     
    13941320                // not sufficient to clone here, because variable's type may have changed
    13951321                // since the VariableExpr was originally created.
    1396                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
     1322                alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
    13971323        }
    13981324
    13991325        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1400                 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
     1326                alternatives.push_back( Alternative{ constantExpr->clone(), env } );
    14011327        }
    14021328
     
    14041330                if ( sizeofExpr->get_isType() ) {
    14051331                        Type * newType = sizeofExpr->get_type()->clone();
    1406                         alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1332                        alternatives.push_back( Alternative{
     1333                                new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14071334                } else {
    14081335                        // find all alternatives for the argument to sizeof
     
    14181345                        Alternative &choice = winners.front();
    14191346                        referenceToRvalueConversion( choice.expr, choice.cost );
    1420                         alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1347                        alternatives.push_back( Alternative{
     1348                                choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
    14211349                } // if
    14221350        }
     
    14251353                if ( alignofExpr->get_isType() ) {
    14261354                        Type * newType = alignofExpr->get_type()->clone();
    1427                         alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1355                        alternatives.push_back( Alternative{
     1356                                new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14281357                } else {
    14291358                        // find all alternatives for the argument to sizeof
     
    14391368                        Alternative &choice = winners.front();
    14401369                        referenceToRvalueConversion( choice.expr, choice.cost );
    1441                         alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1370                        alternatives.push_back( Alternative{
     1371                                choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
    14421372                } // if
    14431373        }
     
    14491379                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    14501380                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1451                                 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
     1381                                alternatives.push_back( Alternative{
     1382                                        new OffsetofExpr{ aggInst->clone(), dwt }, env } );
    14521383                                renameTypes( alternatives.back().expr );
    14531384                        } else {
     
    14681399
    14691400        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1470                 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
     1401                alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
    14711402        }
    14721403
    14731404        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    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 ) {
     1405                alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
     1406        }
     1407
     1408        void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) {
    15401409                AlternativeFinder firstFinder( indexer, env );
    15411410                firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
     
    15461415                for ( const Alternative & first : firstFinder.alternatives ) {
    15471416                        for ( const Alternative & second : secondFinder.alternatives ) {
    1548                                 TypeEnvironment compositeEnv;
    1549                                 compositeEnv.simpleCombine( first.env );
     1417                                TypeEnvironment compositeEnv{ first.env };
    15501418                                compositeEnv.simpleCombine( second.env );
    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 ) );
     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 } );
    15541430                        }
    15551431                }
     
    15721448                        for ( const Alternative & second : secondFinder.alternatives ) {
    15731449                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1574                                         TypeEnvironment compositeEnv;
    1575                                         compositeEnv.simpleCombine( first.env );
     1450                                        TypeEnvironment compositeEnv{ first.env };
    15761451                                        compositeEnv.simpleCombine( second.env );
    15771452                                        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;
    15781461
    15791462                                        // 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 );
    15831463                                        Type* commonType = nullptr;
    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() );
     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() };
    15861468                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15871469                                                // convert both options to the conditional result type
    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 ) );
     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 ) );
    15921480                                        } // if
    15931481                                } // for
     
    16021490                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    16031491                for ( const Alternative & alt : secondFinder.alternatives ) {
    1604                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
     1492                        alternatives.push_back( Alternative{
     1493                                alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
    16051494                } // for
    16061495                delete newFirstArg;
     
    16171506                for ( const Alternative & first : firstFinder.alternatives ) {
    16181507                        for ( const Alternative & second : secondFinder.alternatives ) {
    1619                                 TypeEnvironment compositeEnv;
    1620                                 compositeEnv.simpleCombine( first.env );
     1508                                TypeEnvironment compositeEnv{ first.env };
    16211509                                compositeEnv.simpleCombine( second.env );
    1622                                 OpenVarSet openVars;
    1623                                 AssertionSet needAssertions, haveAssertions;
    1624                                 Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
     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
    16251517                                Type* commonType = nullptr;
    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() );
     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() };
    16281522                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1629                                         newAlt.expr = newExpr;
    1630                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     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 ) );
    16311527                                } // if
    16321528                        } // for
     
    16461542
    16471543                        TypeEnvironment compositeEnv;
    1648                         simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    1649                         alternatives.push_back(
    1650                                 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
     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 ) } );
    16511555                } // for
    16521556        }
    16531557
    16541558        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1655                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1559                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16561560        }
    16571561
    16581562        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1659                 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
     1563                alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
    16601564        }
    16611565
     
    16661570                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16671571                for ( Alternative & alt : finder.alternatives ) {
    1668                         alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
     1572                        alternatives.push_back( Alternative{
     1573                                alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
    16691574                }
    16701575        }
    16711576
    16721577        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1673                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1578                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16741579        }
    16751580
    16761581        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1677                 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
     1582                alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
    16781583        }
    16791584
     
    16841589                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16851590                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1686                         alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
     1591                        alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
    16871592                }
    16881593        }
     
    16921597                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    16931598                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1694                 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
     1599                alternatives.push_back( Alternative{ newStmtExpr, env } );
    16951600        }
    16961601
     
    17141619                        for ( Alternative & alt : finder.get_alternatives() ) {
    17151620                                TypeEnvironment newEnv( alt.env );
    1716                                 AssertionSet needAssertions, haveAssertions;
    1717                                 OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
     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?
    17181627                                PRINT(
    17191628                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    17201629                                )
    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.
     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.
    17251635                                int discardedValues = alt.expr->result->size() - toType->size();
    17261636                                if ( discardedValues < 0 ) continue;
    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]))
     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
    17291641                                // unification run for side-effects
    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 );
     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 );
    17331647                                if ( thisCost != Cost::infinity ) {
    17341648                                        // count one safe conversion for each value that is thrown away
    17351649                                        thisCost.incSafe( discardedValues );
    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 ) );
     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 ) );
    17381656                                }
    17391657                        }
  • src/ResolvExpr/AlternativeFinder.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:56:12 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul 26 11:24:00 2017
    13 // Update Count     : 4
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct -5 10:01:00 2018
     13// Update Count     : 5
    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
    2627#include "SynTree/Visitor.h"             // for Visitor
    2728#include "SynTree/SynTree.h"             // for Visitor Nodes
     
    3637        /// First index is which argument, second index is which alternative for that argument,
    3738        /// third index is which exploded element of that alternative
    38         using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;
     39        using ExplodedArgs_old = std::vector< std::vector< ExplodedActual > >;
    3940
    4041        class AlternativeFinder {
     
    6869                }
    6970
    70                 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true );
     71                void find( Expression *expr, ResolvMode mode = ResolvMode{} );
    7172                /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types
    7273                void findWithAdjustment( Expression *expr );
  • src/ResolvExpr/CastCost.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 06:57:43 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  2 15:34:36 2016
    13 // Update Count     : 7
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Aug  8 16:12:00 2019
     13// Update Count     : 8
    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"
    1822#include "ConversionCost.h"              // for ConversionCost
    1923#include "Cost.h"                        // for Cost, Cost::infinity
     
    3135
    3236namespace ResolvExpr {
    33         struct CastCost : public ConversionCost {
     37        struct CastCost_old : public ConversionCost {
    3438          public:
    35                 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
     39                CastCost_old( const Type * dest, bool srcIsLvalue,
     40                        const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    3641
    3742                using ConversionCost::previsit;
    3843                using ConversionCost::postvisit;
    39                 void postvisit( BasicType * basicType );
    40                 void postvisit( PointerType * pointerType );
     44                void postvisit( const BasicType * basicType );
     45                void postvisit( const PointerType * pointerType );
    4146        };
    4247
    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() ) ) {
     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 ) ) {
    4652                                if ( eqvClass->type ) {
    47                                         return castCost( src, eqvClass->type, indexer, env );
     53                                        return castCost( src, eqvClass->type, srcIsLvalue, indexer, env );
    4854                                } else {
    4955                                        return Cost::infinity;
    5056                                }
    51                         } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) {
     57                        } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    5258                                // all typedefs should be gone by this point
    53                                 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );
     59                                const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType );
    5460                                if ( type->base ) {
    55                                         return castCost( src, type->base, indexer, env ) + Cost::safe;
     61                                        return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe;
    5662                                } // if
    5763                        } // if
     
    7076                        PRINT( std::cerr << "compatible!" << std::endl; )
    7177                        return Cost::zero;
    72                 } else if ( dynamic_cast< VoidType* >( dest ) ) {
     78                } else if ( dynamic_cast< const VoidType * >( dest ) ) {
    7379                        return Cost::safe;
    74                 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     80                } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
    7581                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    76                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     82                        return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    7783                                return ptrsCastable( t1, t2, env, indexer );
    7884                        });
    7985                } else {
    80                         PassVisitor<CastCost> converter( dest, indexer, env, castCost );
     86                        PassVisitor<CastCost_old> converter(
     87                                dest, srcIsLvalue, indexer, env,
     88                                (Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & ))
     89                                        castCost );
    8190                        src->accept( converter );
    8291                        if ( converter.pass.get_cost() == Cost::infinity ) {
     
    8998        }
    9099
    91         CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    92                 : ConversionCost( dest, indexer, env, costFunc ) {
    93         }
    94 
    95         void CastCost::postvisit( BasicType *basicType ) {
    96                 PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
     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 ) {
     103        }
     104
     105        void CastCost_old::postvisit( const BasicType * basicType ) {
     106                const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest );
    97107                if ( destAsPointer && basicType->isInteger() ) {
    98                         // necessary for, e.g. unsigned long => void*
     108                        // necessary for, e.g. unsigned long => void *
    99109                        cost = Cost::unsafe;
    100110                } else {
    101                         cost = conversionCost( basicType, dest, indexer, env );
     111                        cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env );
    102112                } // if
    103113        }
    104114
    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 ) ) {
     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 ) ) {
    108118                                cost = Cost::safe;
    109119                        } else {
     
    118128                                } // if
    119129                        } // if
    120                 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
     130                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    121131                        if ( destAsBasic->isInteger() ) {
    122                                 // necessary for, e.g. void* => unsigned long
     132                                // necessary for, e.g. void * => unsigned long
    123133                                cost = Cost::unsafe;
    124134                        } // if
    125135                }
    126136        }
     137
     138namespace {
     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
     187Cost 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
    127244} // namespace ResolvExpr
    128245
  • src/ResolvExpr/CommonType.cc

    r7951100 rb067d9b  
    1010// Created On       : Sun May 17 06:59:27 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 15:18:17 2017
    13 // Update Count     : 9
     12// Last Modified On : Thu Feb 14 17:10:10 2019
     13// Update Count     : 24
    1414//
    1515
     
    1818#include <utility>                       // for pair
    1919
     20#include "AST/Decl.hpp"
     21#include "AST/Type.hpp"
    2022#include "Common/PassVisitor.h"
    2123#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
     
    2426#include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    2527#include "SynTree/Visitor.h"             // for Visitor
    26 #include "Unify.h"                       // for unifyExact, bindVar, WidenMode
     28#include "Unify.h"                       // for unifyExact, WidenMode
    2729#include "typeops.h"                     // for isFtype
    2830
     
    3537
    3638namespace ResolvExpr {
    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; }
     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; }
    4042
    4143                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     
    5860
    5961          private:
    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
     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
    6567                bool widenFirst, widenSecond;
    6668                const SymTab::Indexer &indexer;
     
    7880                                std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
    7981                        )
    80                         if ( (widenFirst || t2->get_qualifiers() <= t1->get_qualifiers()) && (widenSecond || t1->get_qualifiers() <= t2->get_qualifiers()) ) {
     82                        if ( (widenFirst || t2->tq <= t1->tq) && (widenSecond || t1->tq <= t2->tq) ) {
    8183                                PRINT(
    8284                                        std::cerr << "widen okay" << std::endl;
    8385                                )
    84                                 common->get_qualifiers() |= t1->get_qualifiers();
    85                                 common->get_qualifiers() |= t2->get_qualifiers();
     86                                common->tq |= t1->tq;
     87                                common->tq |= t2->tq;
    8688                                return common;
    8789                        }
     
    9395        }
    9496
    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 );
     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 );
    9799
    98100                int depth1 = type1->referenceDepth();
     
    125127                                                std::cerr << "formal is reference; result should be reference" << std::endl;
    126128                                        )
    127                                         result = new ReferenceType( ref1->get_qualifiers(), result );
     129                                        result = new ReferenceType( ref1->tq, result );
    128130                                }
    129131                                PRINT(
     
    136138
    137139                type1->accept( visitor );
    138                 Type *result = visitor.pass.get_result();
     140                Type * result = visitor.pass.get_result();
    139141                if ( ! result ) {
    140142                        // this appears to be handling for opaque type declarations
    141143                        if ( widenSecond ) {
    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 );
     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 );
    145147                                                if ( type->get_base() ) {
    146                                                         Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
     148                                                        Type::Qualifiers tq1 = type1->tq, tq2 = type2->tq;
    147149                                                        AssertionSet have, need;
    148150                                                        OpenVarSet newOpen( openVars );
    149                                                         type1->get_qualifiers() = Type::Qualifiers();
    150                                                         type->get_base()->get_qualifiers() = tq1;
     151                                                        type1->tq = Type::Qualifiers();
     152                                                        type->get_base()->tq = tq1;
    151153                                                        if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) {
    152154                                                                result = type1->clone();
    153                                                                 result->get_qualifiers() = tq1 | tq2;
     155                                                                result->tq = tq1 | tq2;
    154156                                                        } // if
    155                                                         type1->get_qualifiers() = tq1;
    156                                                         type->get_base()->get_qualifiers() = Type::Qualifiers();
     157                                                        type1->tq = tq1;
     158                                                        type->get_base()->tq = Type::Qualifiers();
    157159                                                } // if
    158160                                        } // if
     
    176178        }
    177179
    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         };
     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
    207482        static_assert(
    208                 sizeof(combinedType)/sizeof(combinedType[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
     483                sizeof(commonTypes)/sizeof(commonTypes[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
    209484                "Each basic type kind should have a corresponding row in the combined type matrix"
    210485        );
    211486
    212         CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     487        CommonType_old::CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    213488                : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    214489        }
    215490
    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 );
     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 );
    223498                        } // if
    224                 } else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
     499                } else if ( dynamic_cast< EnumInstType * > ( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    225500                        // use signed int in lieu of the enum/zero/one type
    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 );
     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 );
    229504                        } // if
    230505                } // if
     
    232507
    233508        template< typename Pointer >
    234         void CommonType::getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ) {
    235                 if ( TypeInstType* var = dynamic_cast< TypeInstType* >( otherPointer->get_base() ) ) {
     509        void CommonType_old::getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ) {
     510                if ( TypeInstType * var = dynamic_cast< TypeInstType * >( otherPointer->get_base() ) ) {
    236511                        OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
    237512                        if ( entry != openVars.end() ) {
    238513                                AssertionSet need, have;
    239514                                WidenMode widen( widenFirst, widenSecond );
    240                                 if ( entry != openVars.end() && ! bindVar(var, voidPointer->get_base(), entry->second, env, need, have, openVars, widen, indexer ) ) return;
     515                                if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
    241516                        }
    242517                }
    243518                result = voidPointer->clone();
    244                 result->get_qualifiers() |= otherPointer->get_qualifiers();
    245         }
    246 
    247         void CommonType::postvisit( PointerType *pointerType ) {
    248                 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
     519                result->tq |= otherPointer->tq;
     520        }
     521
     522        void CommonType_old::postvisit( PointerType * pointerType ) {
     523                if ( PointerType * otherPointer = dynamic_cast< PointerType * >( type2 ) ) {
    249524                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
    250                         if ( widenFirst && dynamic_cast< VoidType* >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
     525                        if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
    251526                                getCommonWithVoidPointer( otherPointer, pointerType );
    252                         } else if ( widenSecond && dynamic_cast< VoidType* >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
     527                        } else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
    253528                                getCommonWithVoidPointer( pointerType, otherPointer );
    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 ) ) {
     529                        } else if ( ( pointerType->get_base()->tq >= otherPointer->get_base()->tq || widenFirst )
     530                                           && ( pointerType->get_base()->tq <= otherPointer->get_base()->tq || widenSecond ) ) {
    256531                                // std::cerr << "middle case" << std::endl;
    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();
     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();
    260535                                AssertionSet have, need;
    261536                                OpenVarSet newOpen( openVars );
     
    267542                                                result = otherPointer->clone();
    268543                                        } // if
    269                                         result->get_qualifiers() = tq1 | tq2;
     544                                        strict_dynamic_cast<PointerType *>(result)->base->tq = tq1 | tq2;
    270545                                } else {
    271546                                        /// std::cerr << "place for ptr-to-type" << std::endl;
    272547                                } // if
    273                                 pointerType->get_base()->get_qualifiers() = tq1;
    274                                 otherPointer->get_base()->get_qualifiers() = tq2;
     548                                pointerType->get_base()->tq = tq1;
     549                                otherPointer->get_base()->tq = tq2;
    275550                        } // if
    276                 } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
     551                } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    277552                        result = pointerType->clone();
    278                         result->get_qualifiers() |= type2->get_qualifiers();
     553                        result->tq |= type2->tq;
    279554                } // if
    280555        }
    281556
    282         void CommonType::postvisit( ArrayType * ) {}
    283 
    284         void CommonType::postvisit( ReferenceType *refType ) {
    285                 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
     557        void CommonType_old::postvisit( ArrayType * ) {}
     558
     559        void CommonType_old::postvisit( ReferenceType * refType ) {
     560                if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( type2 ) ) {
    286561                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
    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()) ) {
     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()) ) {
    289564                                getCommonWithVoidPointer( otherRef, refType );
    290                         } else if ( widenSecond && dynamic_cast< VoidType* >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
     565                        } else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
    291566                                getCommonWithVoidPointer( refType, otherRef );
    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 ) ) {
     567                        } else if ( ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst )
     568                                           && ( refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond ) ) {
    294569                                // std::cerr << "middle case" << std::endl;
    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();
     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();
    298573                                AssertionSet have, need;
    299574                                OpenVarSet newOpen( openVars );
     
    304579                                                result = otherRef->clone();
    305580                                        } // if
    306                                         result->get_qualifiers() = tq1 | tq2;
     581                                        strict_dynamic_cast<ReferenceType *>(result)->base->tq = tq1 | tq2;
    307582                                } else {
    308583                                        /// std::cerr << "place for ptr-to-type" << std::endl;
    309584                                } // if
    310                                 refType->get_base()->get_qualifiers() = tq1;
    311                                 otherRef->get_base()->get_qualifiers() = tq2;
     585                                refType->get_base()->tq = tq1;
     586                                otherRef->get_base()->tq = tq2;
    312587                        } // if
    313                 } else if ( widenSecond && dynamic_cast< ZeroType* >( type2 ) ) {
     588                } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    314589                        result = refType->clone();
    315                         result->get_qualifiers() |= type2->get_qualifiers();
     590                        result->tq |= type2->tq;
    316591                } // if
    317592        }
    318593
    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 ) ) {
     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 ) ) {
    325600                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    326601                        result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
     
    328603        }
    329604
    330         void CommonType::postvisit( TraitInstType * ) {
    331         }
    332 
    333         void CommonType::postvisit( TypeInstType *inst ) {
     605        void CommonType_old::postvisit( TraitInstType * ) {
     606        }
     607
     608        void CommonType_old::postvisit( TypeInstType * inst ) {
    334609                if ( widenFirst ) {
    335                         NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
     610                        const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() );
    336611                        if ( nt ) {
    337                                 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( nt );
     612                                const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
    338613                                if ( type->get_base() ) {
    339                                         Type::Qualifiers tq1 = inst->get_qualifiers(), tq2 = type2->get_qualifiers();
     614                                        Type::Qualifiers tq1 = inst->tq, tq2 = type2->tq;
    340615                                        AssertionSet have, need;
    341616                                        OpenVarSet newOpen( openVars );
    342                                         type2->get_qualifiers() = Type::Qualifiers();
    343                                         type->get_base()->get_qualifiers() = tq1;
     617                                        type2->tq = Type::Qualifiers();
     618                                        type->get_base()->tq = tq1;
    344619                                        if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) {
    345620                                                result = type2->clone();
    346                                                 result->get_qualifiers() = tq1 | tq2;
     621                                                result->tq = tq1 | tq2;
    347622                                        } // if
    348                                         type2->get_qualifiers() = tq2;
    349                                         type->get_base()->get_qualifiers() = Type::Qualifiers();
     623                                        type2->tq = tq2;
     624                                        type->get_base()->tq = Type::Qualifiers();
    350625                                } // if
    351626                        } // if
     
    353628        }
    354629
    355         void CommonType::postvisit( TupleType * ) {}
    356         void CommonType::postvisit( VarArgsType * ) {}
    357 
    358         void CommonType::postvisit( ZeroType *zeroType ) {
     630        void CommonType_old::postvisit( TupleType * ) {}
     631        void CommonType_old::postvisit( VarArgsType * ) {}
     632
     633        void CommonType_old::postvisit( ZeroType * zeroType ) {
    359634                if ( widenFirst ) {
    360                         if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
    361                                 if ( widenSecond || zeroType->get_qualifiers() <= type2->get_qualifiers() ) {
     635                        if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
     636                                if ( widenSecond || zeroType->tq <= type2->tq ) {
    362637                                        result = type2->clone();
    363                                         result->get_qualifiers() |= zeroType->get_qualifiers();
    364                                 }
    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 ) {
     638                                        result->tq |= zeroType->tq;
     639                                }
     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 ) {
    373648                if ( widenFirst ) {
    374                         if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
    375                                 if ( widenSecond || oneType->get_qualifiers() <= type2->get_qualifiers() ) {
     649                        if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
     650                                if ( widenSecond || oneType->tq <= type2->tq ) {
    376651                                        result = type2->clone();
    377                                         result->get_qualifiers() |= oneType->get_qualifiers();
    378                                 }
    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         }
     652                                        result->tq |= oneType->tq;
     653                                }
     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
    385999} // namespace ResolvExpr
    3861000
  • src/ResolvExpr/ConversionCost.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 07:06:19 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 15:43:34 2017
    13 // Update Count     : 10
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Aug 12 10:21:00 2019
     13// Update Count     : 27
    1414//
    1515
     
    2828
    2929namespace ResolvExpr {
    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 );
     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
    3641
    3742#if 0
     
    4045#define PRINT(x)
    4146#endif
    42         Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    43                 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
     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 ) ) {
    4451                        PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
    45                         if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->name ) ) {
     52                        if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
    4653                                if ( eqvClass->type ) {
    47                                         return conversionCost( src, eqvClass->type, indexer, env );
     54                                        return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
    4855                                } else {
    4956                                        return Cost::infinity;
    5057                                }
    51                         } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {
     58                        } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    5259                                PRINT( std::cerr << " found" << std::endl; )
    53                                 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
     60                                const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
    5461                                // all typedefs should be gone by this point
    5562                                assert( type );
    5663                                if ( type->base ) {
    57                                         return conversionCost( src, type->base, indexer, env ) + Cost::safe;
     64                                        return conversionCost( src, type->base, srcIsLvalue, indexer, env )
     65                                                + Cost::safe;
    5866                                } // if
    5967                        } // if
     
    7179                        PRINT( std::cerr << "compatible!" << std::endl; )
    7280                        return Cost::zero;
    73                 } else if ( dynamic_cast< VoidType* >( dest ) ) {
     81                } else if ( dynamic_cast< const VoidType * >( dest ) ) {
    7482                        return Cost::safe;
    75                 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     83                } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
    7684                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    77                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
     85                        return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
    7886                                return ptrsAssignable( t1, t2, env );
    7987                        });
    8088                } else {
    81                         PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
     89                        PassVisitor<ConversionCost> converter(
     90                                dest, srcIsLvalue, indexer, env,
     91                                (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
     92                                        conversionCost );
    8293                        src->accept( converter );
    8394                        if ( converter.pass.get_cost() == Cost::infinity ) {
     
    89100        }
    90101
    91         Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
     102        static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
     103                        int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    92104                PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
    93105                if ( diff > 0 ) {
    94106                        // TODO: document this
    95                         Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
     107                        Cost cost = convertToReferenceCost(
     108                                strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
     109                                diff-1, indexer, env, func );
    96110                        cost.incReference();
    97111                        return cost;
    98112                } else if ( diff < -1 ) {
    99113                        // TODO: document this
    100                         Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func );
     114                        Cost cost = convertToReferenceCost(
     115                                src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
     116                                diff+1, indexer, env, func );
    101117                        cost.incReference();
    102118                        return cost;
    103119                } else if ( diff == 0 ) {
    104                         ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
    105                         ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     120                        const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
     121                        const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
    106122                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
    107123                                PRINT( std::cerr << "converting between references" << std::endl; )
    108                                 Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers();
    109                                 Type::Qualifiers tq2 = destAsRef->base->get_qualifiers();
     124                                Type::Qualifiers tq1 = srcAsRef->base->tq;
     125                                Type::Qualifiers tq2 = destAsRef->base->tq;
    110126                                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
    111127                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     
    128144                        } else {
    129145                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    130                                 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
     146                                PassVisitor<ConversionCost> converter(
     147                                        dest, srcIsLvalue, indexer, env,
     148                                        (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
     149                                                conversionCost );
    131150                                src->accept( converter );
    132151                                return converter.pass.get_cost();
    133152                        } // if
    134153                } else {
    135                         ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
     154                        const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
    136155                        assert( diff == -1 && destAsRef );
    137156                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    138157                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
    139158                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
    140                                 if ( src->get_lvalue() ) {
     159                                if ( srcIsLvalue ) {
    141160                                        PRINT(
    142161                                                std::cerr << "lvalue to reference conversion" << std::endl;
     
    144163                                        )
    145164                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
    146                                         if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
     165                                        if ( src->tq == destAsRef->base->tq ) {
    147166                                                return Cost::reference; // cost needs to be non-zero to add cast
    148                                         } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
     167                                        } if ( src->tq < destAsRef->base->tq ) {
    149168                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    150169                                        } else {
     
    166185        }
    167186
    168         Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
     187        Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
     188                        const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    169189                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
    170                 Cost cost = convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
     190                Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
    171191                PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
    172192                return cost;
    173193        }
    174194
    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         };
     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
    261267        static_assert(
    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"
     268                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
     269                "Missing row in the cost matrix"
    264270        );
    265271
    266 
    267         void ConversionCost::postvisit( VoidType * ) {
     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 * ) {
    268320                cost = Cost::infinity;
    269321        }
    270322
    271         void ConversionCost::postvisit(BasicType *basicType) {
    272                 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
    273                         int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
     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 ];
    274326                        if ( tableResult == -1 ) {
    275327                                cost = Cost::unsafe;
     
    277329                                cost = Cost::zero;
    278330                                cost.incSafe( tableResult );
    279                         } // if
    280                 } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
     331                                cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
     332                        } // if
     333                } else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
    281334                        // xxx - not positive this is correct, but appears to allow casting int => enum
    282335                        cost = Cost::unsafe;
     
    285338        }
    286339
    287         void ConversionCost::postvisit( PointerType * pointerType ) {
    288                 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
     340        void ConversionCost::postvisit( const PointerType * pointerType ) {
     341                if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
    289342                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
    290                         Type::Qualifiers tq1 = pointerType->base->get_qualifiers();
    291                         Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers();
     343                        Type::Qualifiers tq1 = pointerType->base->tq;
     344                        Type::Qualifiers tq2 = destAsPtr->base->tq;
    292345                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    293346                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     
    298351                                        // types are the same, except otherPointer has more qualifiers
    299352                                        cost = Cost::safe;
    300                                 }
     353                                } // if
    301354                        } else {
    302355                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
     
    318371        }
    319372
    320         void ConversionCost::postvisit( ArrayType * ) {}
    321 
    322         void ConversionCost::postvisit( ReferenceType * refType ) {
     373        void ConversionCost::postvisit( const ArrayType * ) {}
     374
     375        void ConversionCost::postvisit( const ReferenceType * refType ) {
    323376                // Note: dest can never be a reference, since it would have been caught in an earlier check
    324                 assert( ! dynamic_cast< ReferenceType * >( dest ) );
     377                assert( ! dynamic_cast< const ReferenceType * >( dest ) );
    325378                // convert reference to rvalue: cv T1 & => T2
    326379                // recursively compute conversion cost from T1 to T2.
    327380                // cv can be safely dropped because of 'implicit dereference' behavior.
    328                 cost = costFunc( refType->base, dest, indexer, env );
    329                 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
     381                cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
     382                if ( refType->base->tq == dest->tq ) {
    330383                        cost.incReference();  // prefer exact qualifiers
    331                 } else if ( refType->base->get_qualifiers() < dest->get_qualifiers() ) {
     384                } else if ( refType->base->tq < dest->tq ) {
    332385                        cost.incSafe(); // then gaining qualifiers
    333386                } else {
     
    337390        }
    338391
    339         void ConversionCost::postvisit( FunctionType * ) {}
    340 
    341         void ConversionCost::postvisit( StructInstType * inst ) {
    342                 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
     392        void ConversionCost::postvisit( const FunctionType * ) {}
     393
     394        void ConversionCost::postvisit( const StructInstType * inst ) {
     395                if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
    343396                        if ( inst->name == destAsInst->name ) {
    344397                                cost = Cost::zero;
     
    347400        }
    348401
    349         void ConversionCost::postvisit( UnionInstType * inst ) {
    350                 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
     402        void ConversionCost::postvisit( const UnionInstType * inst ) {
     403                if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
    351404                        if ( inst->name == destAsInst->name ) {
    352405                                cost = Cost::zero;
     
    355408        }
    356409
    357         void ConversionCost::postvisit( EnumInstType * ) {
     410        void ConversionCost::postvisit( const EnumInstType * ) {
    358411                static Type::Qualifiers q;
    359412                static BasicType integer( q, BasicType::SignedInt );
    360                 cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
     413                cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
    361414                if ( cost < Cost::unsafe ) {
    362415                        cost.incSafe();
     
    364417        }
    365418
    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 ) ) {
     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 ) ) {
    372425                        if ( inst->name == destAsInst->name ) {
    373426                                cost = Cost::zero;
    374427                        }
    375                 } else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) {
    376                         TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
     428                } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
     429                        const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
    377430                        // all typedefs should be gone by this point
    378431                        assert( type );
    379432                        if ( type->base ) {
    380                                 cost = costFunc( type->base, dest, indexer, env ) + Cost::safe;
    381                         } // if
    382                 } // if
    383         }
    384 
    385         void ConversionCost::postvisit( TupleType * tupleType ) {
     433                                cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
     434                        } // if
     435                } // if
     436        }
     437
     438        void ConversionCost::postvisit( const TupleType * tupleType ) {
    386439                Cost c = Cost::zero;
    387                 if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
     440                if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
    388441                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
    389442                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
    390443                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
    391                                 Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env );
     444                                Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
    392445                                if ( newCost == Cost::infinity ) {
    393446                                        return;
     
    403456        }
    404457
    405         void ConversionCost::postvisit( VarArgsType * ) {
    406                 if ( dynamic_cast< VarArgsType* >( dest ) ) {
    407                         cost = Cost::zero;
    408                 }
    409         }
    410 
    411         void ConversionCost::postvisit( ZeroType * ) {
    412                 if ( dynamic_cast< ZeroType * >( dest ) ) {
    413                         cost = Cost::zero;
    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() ];
     458        void ConversionCost::postvisit( const VarArgsType * ) {
     459                if ( dynamic_cast< const VarArgsType * >( dest ) ) {
     460                        cost = Cost::zero;
     461                }
     462        }
     463
     464        void ConversionCost::postvisit( const ZeroType * ) {
     465                if ( dynamic_cast< const ZeroType * >( dest ) ) {
     466                        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 ];
    417470                        if ( tableResult == -1 ) {
    418471                                cost = Cost::unsafe;
     
    420473                                cost = Cost::zero;
    421474                                cost.incSafe( tableResult + 1 );
    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 ) ) {
    430                         cost = Cost::zero;
    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() ];
     475                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
     476                        } // if
     477                } else if ( dynamic_cast< const PointerType * >( dest ) ) {
     478                        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 ];
    434489                        if ( tableResult == -1 ) {
    435490                                cost = Cost::unsafe;
     
    437492                                cost = Cost::zero;
    438493                                cost.incSafe( tableResult + 1 );
     494                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
     495                        } // if
     496                } // if
     497        }
     498
     499static 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.
     506static 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
     511Cost 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;
    439521                        }
    440                 }
    441         }
     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;
     527                        }
     528                }
     529        }
     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
     544static 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
     608Cost 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
     615void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
     616        (void)voidType;
     617        cost = Cost::infinity;
     618}
     619
     620void 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
     636void 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
     662void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
     663        (void)arrayType;
     664}
     665
     666void 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
     679void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
     680        (void)functionType;
     681}
     682
     683void 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
     692void 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
     701void 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
     710void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
     711        (void)traitInstType;
     712}
     713
     714void 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
     731void 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
     753void 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
     760void 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
     777void 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
    442798} // namespace ResolvExpr
    443799
  • src/ResolvExpr/ConversionCost.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:37:28 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:38:24 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Aug  8 16:13:00 2019
     13// Update Count     : 6
    1414//
    1515
     
    2020#include "Cost.h"             // for Cost
    2121
     22#include "AST/Fwd.hpp"
     23#include "AST/Pass.hpp"       // for WithShortCircuiting
    2224#include "Common/PassVisitor.h"
    2325#include "SynTree/Visitor.h"  // for Visitor
     
    3133        class TypeEnvironment;
    3234
    33         typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
     35        typedef std::function<Cost(const Type *, const Type *, bool,
     36                const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
     37
    3438        struct ConversionCost : public WithShortCircuiting {
    3539          public:
    36                 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
     40                ConversionCost( const Type * dest, bool srcIsLvalue,
     41                        const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
    3742
    3843                Cost get_cost() const { return cost; }
    3944
    40                 void previsit( BaseSyntaxNode * ) { visit_children = false; }
     45                void previsit( const BaseSyntaxNode * ) { visit_children = false; }
    4146
    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 );
     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 );
    5762          protected:
    58                 Type *dest;
     63                const Type * dest;
     64                bool srcIsLvalue;
    5965                const SymTab::Indexer &indexer;
    6066                Cost cost;
     
    6369        };
    6470
    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 );
     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.
     76using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
     77        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
     78using 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.
     82class ConversionCost_new : public ast::WithShortCircuiting {
     83protected:
     84        const ast::Type * dst;
     85        const ast::SymbolTable & symtab;
     86        const ast::TypeEnvironment & env;
     87        CostCalculation costCalc;
     88public:
     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
     115Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
     116        const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
     117
    67118} // namespace ResolvExpr
    68119
  • src/ResolvExpr/Cost.h

    r7951100 rb067d9b  
    77// Cost.h --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Peter Buhr and Aaron Moss
    1010// Created On       : Sun May 17 09:39:50 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:35:55 2017
    13 // Update Count     : 5
     12// Last Modified On : Fri Jun 21 11:39:13 2019
     13// Update Count     : 63
    1414//
    1515
     
    1717
    1818#include <iostream>
     19#include <cassert>
     20#include <climits>
    1921
    2022namespace 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.
     25
    2126        class Cost {
    22           private:
    23                 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
     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
     47          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                }; //'
    2460
    25           public:
    26                 Cost & incUnsafe( int inc = 1 );
    27                 Cost & incPoly( int inc = 1 );
    28                 Cost & incSafe( int inc = 1 );
    29                 Cost & incReference( int inc = 1 );
     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                }
    3079
    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; }
     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; }
    3587
    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 );
     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 );
    4397
    44                 static const Cost zero;
    45                 static const Cost infinity;
     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
     107                        return *this;
     108                }
    46109
    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;
     110                Cost incUnsafe( int inc = 1 ) {
     111                        if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; }
     112                        return *this;
     113                }
    53114
    54                 int unsafeCost;
    55                 int polyCost;
    56                 int safeCost;
    57                 int referenceCost;
     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 );
    58146        };
    59147
    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;
     148        inline bool operator==( const Cost lhs, const Cost rhs ) {
     149                return lhs.all == rhs.all;
    66150        }
    67151
    68         inline Cost & Cost::incPoly( int inc ) {
    69                 if ( *this == infinity ) return *this;
    70                 polyCost += inc;
    71                 return *this;
     152        inline bool operator!=( const Cost lhs, const Cost rhs ) {
     153                return !( lhs.all == rhs.all );
    72154        }
    73155
    74         inline Cost & Cost::incSafe( int inc ) {
    75                 if ( *this == infinity ) return *this;
    76                 safeCost += inc;
    77                 return *this;
     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;
    78160        }
    79161
    80         inline Cost & Cost::incReference( int inc ) {
    81                 if ( *this == infinity ) return *this;
    82                 referenceCost += inc;
    83                 return *this;
     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
    84165        }
    85166
    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;
    100                         return *this;
    101                 }
    102                 unsafeCost += other.unsafeCost;
    103                 polyCost += other.polyCost;
    104                 safeCost += other.safeCost;
    105                 referenceCost += other.referenceCost;
    106                 return *this;
    107         }
    108 
    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
    132         }
    133 
    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;
    139         }
    140 
    141         inline bool Cost::operator!=( const Cost &other ) const {
    142                 return !( *this == other );
    143         }
    144 
    145         inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    146                 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
    147                 return os;
     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() << " )";
    148171        }
    149172} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    r7951100 rb067d9b  
    1616#include <stddef.h>                    // for size_t
    1717#include <cassert>                     // for assertf, assert, safe_dynamic_...
     18#include <deque>
    1819#include <iostream>                    // for ostream, operator<<, basic_ost...
    1920#include <stack>                       // for stack
    2021#include <string>                      // for string, operator<<, allocator
    2122
     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"
    2228#include "Common/Indenter.h"           // for Indenter, operator<<
    2329#include "Common/SemanticError.h"      // for SemanticError
     
    139145                ArrayIterator( ArrayType * at ) : array( at ) {
    140146                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    141                         base = at->get_base();
     147                        base = at->base;
    142148                        memberIter = createMemberIterator( base );
    143                         if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=" );
    144                         setSize( at->get_dimension() );
     149                        if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
     150                        setSize( at->dimension );
    145151                }
    146152
     
    150156
    151157        private:
    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                                 }
     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;
    169162                        } else {
    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
     163                                SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
    171164                        }
    172165                }
     
    592585} // namespace ResolvExpr
    593586
     587namespace 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
    5941065// Local Variables: //
    5951066// tab-width: 4 //
  • src/ResolvExpr/CurrentObject.h

    r7951100 rb067d9b  
    1616#pragma once
    1717
     18#include <deque>
    1819#include <list>   // for list
     20#include <memory> // for unique_ptr
    1921#include <stack>  // for stack
     22#include <vector>
     23
     24#include "AST/Node.hpp"  // for ptr
     25#include "Common/CodeLocation.h"
    2026
    2127class Designation;
     
    5258} // namespace ResolvExpr
    5359
     60namespace 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
    54131// Local Variables: //
    55132// tab-width: 4 //
  • src/ResolvExpr/ExplodedActual.cc

    r7951100 rb067d9b  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Alternative.h --
     7// ExplodedActual.cc --
    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

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

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:42:48 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 17 09:45:25 2015
    13 // Update Count     : 3
     11// Last Modified By : Andrew
     12// Last Modified On : Fri Jul 12 14:18:00 2019
     13// Update Count     : 4
    1414//
    1515
     
    1919#include <map>                    // for map<>::mapped_type
    2020
     21#include "AST/Pass.hpp"
     22#include "AST/Type.hpp"
    2123#include "Common/PassVisitor.h"
    2224#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
     
    2426
    2527namespace ResolvExpr {
    26         struct FindOpenVars : public WithGuards {
    27                 FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
     28        struct FindOpenVars_old : public WithGuards {
     29                FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    2830
    29                 void previsit( PointerType * pointerType );
    30                 void previsit( ArrayType * arrayType );
    31                 void previsit( FunctionType * functionType );
    32                 void previsit( TupleType * tupleType );
     31                void previsit( const PointerType * pointerType );
     32                void previsit( const ArrayType * arrayType );
     33                void previsit( const FunctionType * functionType );
     34                void previsit( const TupleType * tupleType );
    3335
    34                 void common_action( Type *type );
     36                void common_action( const Type *type );
    3537
    3638                OpenVarSet &openVars, &closedVars;
     
    3941        };
    4042
    41         void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    42                 PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
     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 );
    4345                type->accept( finder );
    4446        }
    4547
    46         FindOpenVars::FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
     48        FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
    4749                : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) {
    4850        }
    4951
    50         void FindOpenVars::common_action( Type *type ) {
     52        void FindOpenVars_old::common_action( const Type * type ) {
    5153                if ( nextIsOpen ) {
    52                         for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
     54                        for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    5355                                openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    5456                                for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
     
    5961                        }
    6062                } else {
    61                         for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
     63                        for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    6264                                closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    6365                                for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
     
    7678        }
    7779
    78         void FindOpenVars::previsit(PointerType *pointerType) {
     80        void FindOpenVars_old::previsit(const PointerType * pointerType) {
    7981                common_action( pointerType );
    8082        }
    8183
    82         void FindOpenVars::previsit(ArrayType *arrayType) {
     84        void FindOpenVars_old::previsit(const ArrayType * arrayType) {
    8385                common_action( arrayType );
    8486        }
    8587
    86         void FindOpenVars::previsit(FunctionType *functionType) {
     88        void FindOpenVars_old::previsit(const FunctionType * functionType) {
    8789                common_action( functionType );
    8890                nextIsOpen = ! nextIsOpen;
     
    9092        }
    9193
    92         void FindOpenVars::previsit(TupleType *tupleType) {
     94        void FindOpenVars_old::previsit(const TupleType * tupleType) {
    9395                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 );
    94142        }
    95143} // namespace ResolvExpr
  • src/ResolvExpr/FindOpenVars.h

    r7951100 rb067d9b  
    1616#pragma once
    1717
     18#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    1819#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    1920
    2021class Type;
     22namespace ast {
     23        class Type;
     24}
    2125
    2226namespace ResolvExpr {
    2327        // Updates open and closed variables and their associated assertions
    24         void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
     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 );
    2536} // namespace ResolvExpr
    2637
  • src/ResolvExpr/Occurs.cc

    r7951100 rb067d9b  
    2424        struct Occurs : public WithVisitorRef<Occurs> {
    2525                Occurs( std::string varName, const TypeEnvironment &env );
    26                 void previsit( TypeInstType * typeInst );
     26                void previsit( const TypeInstType * typeInst );
    2727
    2828                bool result;
     
    3131        };
    3232
    33         bool occurs( Type *type, std::string varName, const TypeEnvironment &env ) {
     33        bool occurs( const Type *type, const std::string & varName, const TypeEnvironment &env ) {
    3434                PassVisitor<Occurs> occur( varName, env );
    3535                type->accept( occur );
     
    4545        }
    4646
    47         void Occurs::previsit( TypeInstType * typeInst ) {
     47        void Occurs::previsit( const 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

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:50:12 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 17 09:52:02 2015
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jun 19 10:45:00 2019
     13// Update Count     : 4
    1414//
    1515
     16#include "AST/SymbolTable.hpp"
     17#include "AST/Type.hpp"
     18#include "AST/TypeEnvironment.hpp"
    1619#include "Common/PassVisitor.h"
    1720#include "SymTab/Indexer.h"   // for Indexer
     
    5457        }
    5558
     59// TODO: When the old PolyCost is torn out get rid of the _new suffix.
     60struct 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
     83int 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
    5691} // namespace ResolvExpr
    5792
  • src/ResolvExpr/PtrsAssignable.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 11:44:11 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  2 17:36:05 2016
    13 // Update Count     : 8
    14 //
    15 
     11// Last Modified By : Andrew
     12// Last Modified On : Mon Jun 24 15:29:00 2019
     13// Update Count     : 9
     14//
     15
     16#include "typeops.h"
     17
     18#include "AST/Pass.hpp"
     19#include "AST/Type.hpp"
     20#include "AST/TypeEnvironment.hpp"
    1621#include "Common/PassVisitor.h"
    1722#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    2227namespace ResolvExpr {
    2328        struct PtrsAssignable : public WithShortCircuiting {
    24                 PtrsAssignable( Type *dest, const TypeEnvironment &env );
     29                PtrsAssignable( const Type * dest, const TypeEnvironment &env );
    2530
    2631                int get_result() const { return result; }
    2732
    28                 void previsit( Type * ) { visit_children = false; }
    29 
    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 );
     33                void previsit( const Type * ) { visit_children = false; }
     34
     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 );
    4449          private:
    45                 Type *dest;
     50                const Type * dest;
    4651                int result;
    4752                const TypeEnvironment &env;
    4853        };
    4954
    50         int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) {
     55        int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) {
    5156                // std::cerr << "assignable: " << src << " | " << dest << std::endl;
    52                 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    53                         if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     57                if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
     58                        if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    5459                                return ptrsAssignable( src, eqvClass->type, env );
    5560                        } // if
    5661                } // if
    57                 if ( dynamic_cast< VoidType* >( dest ) ) {
     62                if ( dynamic_cast< const VoidType* >( dest ) ) {
    5863                        // void * = T * for any T is unsafe
    5964                        // xxx - this should be safe, but that currently breaks the build
     
    6671        }
    6772
    68         PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
    69 
    70         void PtrsAssignable::postvisit( VoidType * ) {
     73        PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
     74
     75        void PtrsAssignable::postvisit( const VoidType * ) {
    7176                // T * = void * is disallowed - this is a change from C, where any
    7277                // void * can be assigned or passed to a non-void pointer without a cast.
    7378        }
    7479
    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 ) {}
    79 
    80         void PtrsAssignable::postvisit(  __attribute__((unused)) StructInstType *inst ) {}
    81         void PtrsAssignable::postvisit(  __attribute__((unused)) UnionInstType *inst ) {}
    82 
    83         void PtrsAssignable::postvisit( EnumInstType * ) {
    84                 if ( dynamic_cast< BasicType* >( dest ) ) {
     80        void PtrsAssignable::postvisit( const BasicType * ) {}
     81        void PtrsAssignable::postvisit( const PointerType * ) {}
     82        void PtrsAssignable::postvisit( const ArrayType * ) {}
     83        void PtrsAssignable::postvisit( const FunctionType * ) {}
     84
     85        void PtrsAssignable::postvisit( const StructInstType * ) {}
     86        void PtrsAssignable::postvisit( const UnionInstType * ) {}
     87
     88        void PtrsAssignable::postvisit( const EnumInstType * ) {
     89                if ( dynamic_cast< const BasicType* >( dest ) ) {
    8590                        // int * = E *, etc. is safe. This isn't technically correct, as each
    8691                        // enum has one basic type that it is compatible with, an that type can
     
    9297        }
    9398
    94         void PtrsAssignable::postvisit(  __attribute__((unused)) TraitInstType *inst ) {}
    95         void PtrsAssignable::postvisit( TypeInstType *inst ) {
    96                 if ( const EqvClass *eqvClass = env.lookup( inst->get_name() ) ) {
     99        void PtrsAssignable::postvisit(  const TraitInstType * ) {}
     100        void PtrsAssignable::postvisit( const TypeInstType * inst ) {
     101                if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
    97102                        if ( eqvClass->type ) {
    98103                                // T * = S * for any S depends on the type bound to T
     
    102107        }
    103108
    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 ) {}
     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.
     115struct 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
     145int 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}
    108193
    109194} // namespace ResolvExpr
  • src/ResolvExpr/PtrsCastable.cc

    r7951100 rb067d9b  
    1414//
    1515
     16#include "AST/Decl.hpp"
     17#include "AST/Pass.hpp"
     18#include "AST/Type.hpp"
     19#include "AST/TypeEnvironment.hpp"
    1620#include "Common/PassVisitor.h"
    1721#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    2327
    2428namespace ResolvExpr {
    25         struct PtrsCastable : public WithShortCircuiting  {
     29        struct PtrsCastable_old : public WithShortCircuiting  {
    2630          public:
    27                 PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     31                PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    2832
    2933                int get_result() const { return result; }
    3034
    31                 void previsit( Type * ) { visit_children = false; }
    32 
    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 );
     35                void previsit( const Type * ) { visit_children = false; }
     36
     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 );
    4751          private:
    48                 Type *dest;
     52                const Type * dest;
    4953                int result;
    5054                const TypeEnvironment &env;
     
    5357
    5458        namespace {
    55                 int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    56                         if ( dynamic_cast< FunctionType* >( src ) ) {
     59                int objectCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     60                        if ( dynamic_cast< const FunctionType* >( src ) ) {
    5761                                return -1;
    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 ) {
     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 ) {
    6266                                                        return -1;
    6367                                                } // if
    6468                                        } //if
    65                                 } else if ( const EqvClass *eqvClass = env.lookup( typeInst->get_name() ) ) {
     69                                } else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
    6670                                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    6771                                                return -1;
     
    7175                        return 1;
    7276                }
    73                 int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     77                int functionCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    7478                        return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
    7579                }
    7680        }
    7781
    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() ) ) {
     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() ) ) {
    8185                                // xxx - should this be ptrsCastable?
    8286                                return ptrsAssignable( src, eqvClass->type, env );
    8387                        } // if
    8488                } // if
    85                 if ( dynamic_cast< VoidType* >( dest ) ) {
     89                if ( dynamic_cast< const VoidType* >( dest ) ) {
    8690                        return objectCast( src, env, indexer );
    8791                } else {
    88                         PassVisitor<PtrsCastable> ptrs( dest, env, indexer );
     92                        PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer );
    8993                        src->accept( ptrs );
    9094                        return ptrs.pass.get_result();
     
    9296        }
    9397
    94         PtrsCastable::PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
     98        PtrsCastable_old::PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
    9599                : dest( dest ), result( 0 ), env( env ), indexer( indexer )     {
    96100        }
    97101
    98         void PtrsCastable::postvisit( VoidType * ) {
    99                 result = objectCast( dest, env, indexer );
    100         }
    101 
    102         void PtrsCastable::postvisit( BasicType * ) {
    103                 result = objectCast( dest, env, indexer );
    104         }
    105 
    106         void PtrsCastable::postvisit( PointerType * ) {
    107                 result = objectCast( dest, env, indexer );
    108         }
    109 
    110         void PtrsCastable::postvisit( ArrayType * ) {
    111                 result = objectCast( dest, env, indexer );
    112         }
    113 
    114         void PtrsCastable::postvisit( FunctionType * ) {
     102        void PtrsCastable_old::postvisit( const VoidType * ) {
     103                result = objectCast( dest, env, indexer );
     104        }
     105
     106        void PtrsCastable_old::postvisit( const BasicType * ) {
     107                result = objectCast( dest, env, indexer );
     108        }
     109
     110        void PtrsCastable_old::postvisit( const PointerType * ) {
     111                result = objectCast( dest, env, indexer );
     112        }
     113
     114        void PtrsCastable_old::postvisit( const ArrayType * ) {
     115                result = objectCast( dest, env, indexer );
     116        }
     117
     118        void PtrsCastable_old::postvisit( const FunctionType * ) {
    115119                // result = -1;
    116120                result = functionCast( dest, env, indexer );
    117121        }
    118122
    119         void PtrsCastable::postvisit( StructInstType * ) {
    120                 result = objectCast( dest, env, indexer );
    121         }
    122 
    123         void PtrsCastable::postvisit( UnionInstType * ) {
    124                 result = objectCast( dest, env, indexer );
    125         }
    126 
    127         void PtrsCastable::postvisit( EnumInstType * ) {
    128                 if ( dynamic_cast< EnumInstType* >( dest ) ) {
     123        void PtrsCastable_old::postvisit( const StructInstType * ) {
     124                result = objectCast( dest, env, indexer );
     125        }
     126
     127        void PtrsCastable_old::postvisit( const UnionInstType * ) {
     128                result = objectCast( dest, env, indexer );
     129        }
     130
     131        void PtrsCastable_old::postvisit( const EnumInstType * ) {
     132                if ( dynamic_cast< const EnumInstType * >( dest ) ) {
    129133                        result = 1;
    130                 } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {
    131                         if ( bt->get_kind() == BasicType::SignedInt ) {
     134                } else if ( const BasicType * bt = dynamic_cast< const BasicType * >( dest ) ) {
     135                        if ( bt->kind == BasicType::SignedInt ) {
    132136                                result = 0;
    133137                        } else {
     
    139143        }
    140144
    141         void PtrsCastable::postvisit( TraitInstType * ) {}
    142 
    143         void PtrsCastable::postvisit(TypeInstType *inst) {
     145        void PtrsCastable_old::postvisit( const TraitInstType * ) {}
     146
     147        void PtrsCastable_old::postvisit( const TypeInstType *inst ) {
    144148                //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
    145149                result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
    146150        }
    147151
    148         void PtrsCastable::postvisit( TupleType * ) {
    149                 result = objectCast( dest, env, indexer );
    150         }
    151 
    152         void PtrsCastable::postvisit( VarArgsType * ) {
    153                 result = objectCast( dest, env, indexer );
    154         }
    155 
    156         void PtrsCastable::postvisit( ZeroType * ) {
    157                 result = objectCast( dest, env, indexer );
    158         }
    159 
    160         void PtrsCastable::postvisit( OneType * ) {
    161                 result = objectCast( dest, env, indexer );
    162         }
     152        void PtrsCastable_old::postvisit( const TupleType * ) {
     153                result = objectCast( dest, env, indexer );
     154        }
     155
     156        void PtrsCastable_old::postvisit( const VarArgsType * ) {
     157                result = objectCast( dest, env, indexer );
     158        }
     159
     160        void PtrsCastable_old::postvisit( const ZeroType * ) {
     161                result = objectCast( dest, env, indexer );
     162        }
     163
     164        void PtrsCastable_old::postvisit( const OneType * ) {
     165                result = objectCast( dest, env, indexer );
     166        }
     167
     168namespace {
     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
     280int 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
    163299} // namespace ResolvExpr
    164300
  • src/ResolvExpr/RenameVars.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:05:18 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  2 17:36:32 2016
    13 // Update Count     : 5
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Jun 20 17:39:00 2019
     13// Update Count     : 8
    1414//
    1515
     
    1919#include <utility>                 // for pair
    2020
     21#include "AST/Pass.hpp"
     22#include "AST/Type.hpp"
    2123#include "Common/PassVisitor.h"
     24#include "Common/ScopedMap.h"
    2225#include "Common/SemanticError.h"  // for SemanticError
    2326#include "RenameVars.h"
     
    2831
    2932namespace ResolvExpr {
    30         namespace {
    31                 struct RenameVars {
    32                         RenameVars();
    33                         void reset();
    3433
    35                         void previsit( TypeInstType * instType );
    36                         void previsit( Type * );
    37                         void postvisit( Type * );
     34namespace {
     35        class RenamingData {
     36                int level = 0;
     37                int resetCount = 0;
     38                ScopedMap< std::string, std::string > nameMap;
    3839
    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 >() );
     40        public:
     41                void reset() {
     42                        level = 0;
     43                        ++resetCount;
    5844                }
    5945
    60                 void RenameVars::reset() {
    61                         level = 0;
    62                         resetCount++;
     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                        }
    6353                }
    6454
    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 ) {
     55                void openLevel( Type * type ) {
    7456                        if ( ! type->forall.empty() ) {
    75                                 // copies current name mapping into new mapping
    76                                 mapStack.push_front( mapStack.front() );
     57                                nameMap.beginScope();
    7758                                // renames all "forall" type names to `_${level}_${name}'
    7859                                for ( auto td : type->forall ) {
     
    8061                                        output << "_" << resetCount << "_" << level << "_" << td->name;
    8162                                        std::string newname( output.str() );
    82                                         mapStack.front()[ td->get_name() ] = newname;
     63                                        nameMap[ td->get_name() ] = newname;
    8364                                        td->name = newname;
    8465                                        // ditto for assertion names, the next level in
     
    8970                }
    9071
    91                 void RenameVars::postvisit( Type * type ) {
    92                         // clears name mapping added by typeBefore()
    93                         if ( ! type->forall.empty() ) {
    94                                 mapStack.pop_front();
    95                         } // if
     72                void closeLevel( Type * type ) {
     73                        if ( !type->forall.empty() ) {
     74                                nameMap.endScope();
     75                        }
    9676                }
    97         } // namespace
     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
     155void renameTyVars( Type * t ) {
     156        PassVisitor<RenameVars> renamer;
     157        t->accept( renamer );
     158}
     159
     160const ast::Type * renameTyVars( const ast::Type * t ) {
     161        ast::Pass<RenameVars> renamer;
     162        return t->accept( renamer );
     163}
     164
     165void resetTyVarRenaming() {
     166        renaming.reset();
     167}
     168
    98169} // namespace ResolvExpr
    99170
  • src/ResolvExpr/RenameVars.h

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

    r7951100 rb067d9b  
    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"
    2025#include "Common/PassVisitor.h"  // for PassVisitor
     26#include "Common/utility.h"      // for copy
    2127#include "Resolver.h"            // for resolveInVoidContext
    2228#include "SynTree/Expression.h"  // for Expression
     
    4248        }
    4349
    44         class ResolveTypeof : public WithShortCircuiting {
     50        class ResolveTypeof_old : public WithShortCircuiting {
    4551          public:
    46                 ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
     52                ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
    4753                void premutate( TypeofType *typeofType );
    4854                Type * postmutate( TypeofType *typeofType );
     
    5359
    5460        Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
    55                 PassVisitor<ResolveTypeof> mutator( indexer );
     61                PassVisitor<ResolveTypeof_old> mutator( indexer );
    5662                return type->acceptMutator( mutator );
    5763        }
    5864
    59         void ResolveTypeof::premutate( TypeofType * ) {
     65        void ResolveTypeof_old::premutate( TypeofType * ) {
    6066                visit_children = false;
    6167        }
    6268
    63         Type * ResolveTypeof::postmutate( TypeofType *typeofType ) {
     69        Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
    6470#if 0
    6571                std::cerr << "resolving typeof: ";
     
    6773                std::cerr << std::endl;
    6874#endif
    69                 if ( typeofType->expr ) {
     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
    7089                        Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
    7190                        assert( newExpr->result && ! newExpr->result->isVoid() );
    72                         Type * newType = newExpr->result;
     91                        newType = newExpr->result;
    7392                        newExpr->result = nullptr;
    7493                        delete typeofType;
    7594                        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;
     114        }
     115
     116namespace {
     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
    76155                        return newType;
    77                 } // if
    78                 return typeofType;
    79         }
     156                }
     157        };
     158} // anonymous namespace
     159
     160const 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
    80165} // namespace ResolvExpr
    81166
  • src/ResolvExpr/ResolveTypeof.h

    r7951100 rb067d9b  
    2020class Indexer;
    2121}  // namespace SymTab
     22namespace ast {
     23        class Type;
     24        class SymbolTable;
     25}
    2226
    2327namespace ResolvExpr {
    2428        Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
     29        const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & );
    2530} // namespace ResolvExpr
    2631
  • src/ResolvExpr/Resolver.cc

    r7951100 rb067d9b  
    77// Resolver.cc --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Aaron B. Moss
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:40 2018
    13 // Update Count     : 213
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Wed May 29 11:00:00 2019
     13// Update Count     : 241
    1414//
    1515
    16 #include <stddef.h>                      // for NULL
    1716#include <cassert>                       // for strict_dynamic_cast, assert
    1817#include <memory>                        // for allocator, allocator_traits<...
    1918#include <tuple>                         // for get
    20 #include <vector>
     19#include <vector>                        // for vector
    2120
    2221#include "Alternative.h"                 // for Alternative, AltList
    2322#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"
    2438#include "Common/PassVisitor.h"          // for PassVisitor
    2539#include "Common/SemanticError.h"        // for SemanticError
    2640#include "Common/utility.h"              // for ValueGuard, group_iterate
    27 #include "CurrentObject.h"               // for CurrentObject
    2841#include "InitTweak/GenInit.h"
    2942#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
    30 #include "RenameVars.h"                  // for RenameVars, global_renamer
    3143#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    32 #include "ResolveTypeof.h"               // for resolveTypeof
    33 #include "Resolver.h"
    3444#include "SymTab/Autogen.h"              // for SizeType
    3545#include "SymTab/Indexer.h"              // for Indexer
     
    4252#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    4353#include "Tuples/Tuples.h"
    44 #include "typeops.h"                     // for extractResultType
    45 #include "Unify.h"                       // for unify
     54#include "Validate/FindSpecialDecls.h"   // for SizeType
    4655
    4756using namespace std;
    4857
    4958namespace ResolvExpr {
    50         struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {
    51                 Resolver() {}
    52                 Resolver( const SymTab::Indexer & other ) {
     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 ) {
    5362                        indexer = other;
    5463                }
    5564
    56                 void previsit( FunctionDecl *functionDecl );
    57                 void postvisit( FunctionDecl *functionDecl );
    58                 void previsit( ObjectDecl *objectDecll );
    59                 void previsit( TypeDecl *typeDecl );
     65                void previsit( FunctionDecl * functionDecl );
     66                void postvisit( FunctionDecl * functionDecl );
     67                void previsit( ObjectDecl * objectDecll );
    6068                void previsit( EnumDecl * enumDecl );
    6169                void previsit( StaticAssertDecl * assertDecl );
     
    6472                void previsit( PointerType * at );
    6573
    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 );
     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 );
    7886                void previsit( WaitForStmt * stmt );
    79                 void previsit( WithStmt * withStmt );
    80 
    81                 void previsit( SingleInit *singleInit );
    82                 void previsit( ListInit *listInit );
    83                 void previsit( ConstructorInit *ctorInit );
     87
     88                void previsit( SingleInit * singleInit );
     89                void previsit( ListInit * listInit );
     90                void previsit( ConstructorInit * ctorInit );
    8491          private:
    8592                typedef std::list< Initializer * >::iterator InitIterator;
     
    8895                void handlePtrType( PtrType * type );
    8996
    90                 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    9197                void fallbackInit( ConstructorInit * ctorInit );
    9298
     
    96102        };
    97103
     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
    98111        void resolve( std::list< Declaration * > translationUnit ) {
    99                 PassVisitor<Resolver> resolver;
     112                PassVisitor<Resolver_old> resolver;
    100113                acceptAll( translationUnit, resolver );
    101114        }
    102115
    103         void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
    104                 PassVisitor<Resolver> resolver( indexer );
     116        void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
     117                PassVisitor<Resolver_old> resolver( indexer );
    105118                maybeAccept( decl, resolver );
    106119        }
    107120
    108121        namespace {
    109                 struct DeleteFinder : public WithShortCircuiting        {
     122                struct DeleteFinder_old : public WithShortCircuiting    {
    110123                        DeletedExpr * delExpr = nullptr;
    111124                        void previsit( DeletedExpr * expr ) {
     
    121134
    122135        DeletedExpr * findDeletedExpr( Expression * expr ) {
    123                 PassVisitor<DeleteFinder> finder;
     136                PassVisitor<DeleteFinder_old> finder;
    124137                expr->accept( finder );
    125138                return finder.pass.delExpr;
     
    127140
    128141        namespace {
    129                 struct StripCasts {
     142                struct StripCasts_old {
    130143                        Expression * postmutate( CastExpr * castExpr ) {
    131144                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     
    140153
    141154                        static void strip( Expression *& expr ) {
    142                                 PassVisitor<StripCasts> stripper;
     155                                PassVisitor<StripCasts_old> stripper;
    143156                                expr = expr->acceptMutator( stripper );
    144157                        }
    145158                };
    146159
    147                 void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
     160                void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
    148161                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    149162                        env.makeSubstitution( *expr->env );
    150                         StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
     163                        StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
    151164                }
    152165
    153166                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    154167                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    155                                 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     168                                if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    156169                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
    157170                                        expr = castExpr->arg;
     
    165178
    166179        namespace {
    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) {
     180                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
    168181                        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;
    169187                        TypeEnvironment env;
    170188                        AlternativeFinder finder( indexer, env );
    171                         finder.find( untyped, adjust, prune, failFast );
     189                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     190                        --recursion_level;
    172191
    173192                        #if 0
     
    182201                        #endif
    183202
     203                        // produce filtered list of alternatives
    184204                        AltList candidates;
    185205                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    189209                        }
    190210
    191                         // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
    192                         // choose the lowest cost expression among the candidates
     211                        // produce invalid error if no candidates
     212                        if ( candidates.empty() ) {
     213                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     214                        }
     215
     216                        // search for cheapest candidate
    193217                        AltList winners;
    194                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    195                         if ( winners.size() == 0 ) {
    196                                 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    197                         } else if ( winners.size() != 1 ) {
     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 ) {
    198250                                std::ostringstream stream;
    199251                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    204256                        }
    205257
    206                         // there is one unambiguous interpretation - move the expression into the with statement
    207                         Alternative & choice = winners.front();
    208                         if ( findDeletedExpr( choice.expr ) ) {
     258                        // single selected choice
     259                        Alternative& choice = winners.front();
     260
     261                        // fail on only expression deleted
     262                        if ( ! seen_undeleted ) {
    209263                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    210264                        }
     265
     266                        // xxx - check for ambiguous expressions
     267
     268                        // output selected choice
    211269                        alt = std::move( choice );
    212270                }
    213271
    214272                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    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) {
     273                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
    216274                        if ( ! untyped ) return;
    217275                        Alternative choice;
    218                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     276                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
    219277                        finishExpr( choice.expr, choice.env, untyped->env );
    220278                        delete untyped;
     
    231289
    232290        // used in resolveTypeof
    233         Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
     291        Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
    234292                TypeEnvironment env;
    235293                return resolveInVoidContext( expr, indexer, env );
    236294        }
    237295
    238         Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
     296        Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
    239297                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    240298                // interpretations, an exception has already been thrown.
    241299                assertf( expr, "expected a non-null expression." );
    242300
    243                 static CastExpr untyped( nullptr ); // cast to void
    244                 untyped.location = expr->location;
     301                CastExpr * untyped = new CastExpr( expr ); // cast to void
     302                untyped->location = expr->location;
    245303
    246304                // set up and resolve expression cast to void
    247                 untyped.arg = expr;
    248305                Alternative choice;
    249                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     306                findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
    250307                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
     308                assert( castExpr );
    251309                env = std::move( choice.env );
    252310
     
    256314
    257315                // unlink the arg so that it isn't deleted twice at the end of the program
    258                 untyped.arg = nullptr;
     316                untyped->arg = nullptr;
    259317                return ret;
    260318        }
    261319
    262         void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
     320        void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    263321                resetTyVarRenaming();
    264322                TypeEnvironment env;
     
    269327        }
    270328
    271         void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
     329        void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    272330                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    273331        }
     
    288346                        if ( dynamic_cast< EnumInstType * >( type ) ) {
    289347                                return true;
    290                         } else if ( BasicType *bt = dynamic_cast< BasicType * >( type ) ) {
     348                        } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
    291349                                return bt->isInteger();
    292350                        } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
     
    297355                }
    298356
    299                 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
     357                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    300358                        findKindExpression( untyped, indexer, "condition", isIntegralType );
    301359                }
    302360        }
    303361
    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 
     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 ) {
    354398                {
    355399                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
     
    367411        }
    368412
    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.
     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.
    373458                for ( Declaration * d : functionDecl->type->parameters ) {
    374459                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    381466        }
    382467
    383         void Resolver::previsit( EnumDecl * ) {
     468        void Resolver_old::previsit( EnumDecl * ) {
    384469                // in case we decide to allow nested enums
    385470                GuardValue( inEnumDecl );
     
    387472        }
    388473
    389         void Resolver::previsit( StaticAssertDecl * assertDecl ) {
     474        void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
    390475                findIntegralExpression( assertDecl->condition, indexer );
    391476        }
    392477
    393         void Resolver::previsit( ExprStmt *exprStmt ) {
     478        void Resolver_old::previsit( ExprStmt * exprStmt ) {
    394479                visit_children = false;
    395480                assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
     
    397482        }
    398483
    399         void Resolver::previsit( AsmExpr *asmExpr ) {
     484        void Resolver_old::previsit( AsmExpr * asmExpr ) {
    400485                visit_children = false;
    401486                findVoidExpression( asmExpr->operand, indexer );
     
    405490        }
    406491
    407         void Resolver::previsit( AsmStmt *asmStmt ) {
     492        void Resolver_old::previsit( AsmStmt * asmStmt ) {
    408493                visit_children = false;
    409494                acceptAll( asmStmt->get_input(), *visitor );
     
    411496        }
    412497
    413         void Resolver::previsit( IfStmt *ifStmt ) {
     498        void Resolver_old::previsit( IfStmt * ifStmt ) {
    414499                findIntegralExpression( ifStmt->condition, indexer );
    415500        }
    416501
    417         void Resolver::previsit( WhileStmt *whileStmt ) {
     502        void Resolver_old::previsit( WhileStmt * whileStmt ) {
    418503                findIntegralExpression( whileStmt->condition, indexer );
    419504        }
    420505
    421         void Resolver::previsit( ForStmt *forStmt ) {
     506        void Resolver_old::previsit( ForStmt * forStmt ) {
    422507                if ( forStmt->condition ) {
    423508                        findIntegralExpression( forStmt->condition, indexer );
     
    429514        }
    430515
    431         void Resolver::previsit( SwitchStmt *switchStmt ) {
     516        void Resolver_old::previsit( SwitchStmt * switchStmt ) {
    432517                GuardValue( currentObject );
    433518                findIntegralExpression( switchStmt->condition, indexer );
     
    436521        }
    437522
    438         void Resolver::previsit( CaseStmt *caseStmt ) {
     523        void Resolver_old::previsit( CaseStmt * caseStmt ) {
    439524                if ( caseStmt->condition ) {
    440525                        std::list< InitAlternative > initAlts = currentObject.getOptions();
     
    455540        }
    456541
    457         void Resolver::previsit( BranchStmt *branchStmt ) {
     542        void Resolver_old::previsit( BranchStmt * branchStmt ) {
    458543                visit_children = false;
    459544                // must resolve the argument for a computed goto
     
    466551        }
    467552
    468         void Resolver::previsit( ReturnStmt *returnStmt ) {
     553        void Resolver_old::previsit( ReturnStmt * returnStmt ) {
    469554                visit_children = false;
    470555                if ( returnStmt->expr ) {
     
    473558        }
    474559
    475         void Resolver::previsit( ThrowStmt *throwStmt ) {
     560        void Resolver_old::previsit( ThrowStmt * throwStmt ) {
    476561                visit_children = false;
    477562                // TODO: Replace *exception type with &exception type.
    478563                if ( throwStmt->get_expr() ) {
    479                         StructDecl * exception_decl =
    480                                 indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
     564                        const StructDecl * exception_decl = indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
    481565                        assert( exception_decl );
    482                         Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) );
     566                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
    483567                        findSingleExpression( throwStmt->expr, exceptType, indexer );
    484568                }
    485569        }
    486570
    487         void Resolver::previsit( CatchStmt *catchStmt ) {
     571        void Resolver_old::previsit( CatchStmt * catchStmt ) {
    488572                if ( catchStmt->cond ) {
    489573                        findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
     
    500584        }
    501585
    502         void Resolver::previsit( WaitForStmt * stmt ) {
     586        void Resolver_old::previsit( WaitForStmt * stmt ) {
    503587                visit_children = false;
    504588
     
    582666
    583667                                                        // Make sure we don't widen any existing bindings
    584                                                         for ( auto & i : resultEnv ) {
    585                                                                 i.allowWidening = false;
    586                                                         }
     668                                                        resultEnv.forbidWidening();
    587669
    588670                                                        // Find any unbound type variables
     
    592674                                                        auto param_end = function->parameters.end();
    593675
    594                                                         int n_mutex_arg = 0;
     676                                                        int n_mutex_param = 0;
    595677
    596678                                                        // For every arguments of its set, check if it matches one of the parameter
     
    602684                                                                        // We ran out of parameters but still have arguments
    603685                                                                        // this function doesn't match
    604                                                                         SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_arg, "\n" ));
     686                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
    605687                                                                }
    606688
    607                                                                 n_mutex_arg++;
     689                                                                n_mutex_param++;
    608690
    609691                                                                // Check if the argument matches the parameter type in the current scope
     
    628710                                                        // Check if parameters are missing
    629711                                                        if( advance_to_mutex( param, param_end ) ) {
     712                                                                do {
     713                                                                        n_mutex_param++;
     714                                                                        param++;
     715                                                                } while( advance_to_mutex( param, param_end ) );
     716
    630717                                                                // We ran out of arguments but still have parameters left
    631718                                                                // this function doesn't match
    632                                                                 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_arg, "\n" ));
     719                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
    633720                                                        }
    634721
     
    646733
    647734                                                }
    648                                                 catch( SemanticErrorException &e ) {
     735                                                catch( SemanticErrorException & e ) {
    649736                                                        errors.append( e );
    650737                                                }
    651738                                        }
    652739                                }
    653                                 catch( SemanticErrorException &e ) {
     740                                catch( SemanticErrorException & e ) {
    654741                                        errors.append( e );
    655742                                }
     
    694781        }
    695782
    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 ) {
     783        bool isCharType( Type * t ) {
    727784                if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
    728785                        return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
     
    732789        }
    733790
    734         void Resolver::previsit( SingleInit *singleInit ) {
     791        void Resolver_old::previsit( SingleInit * singleInit ) {
    735792                visit_children = false;
    736793                // resolve initialization using the possibilities as determined by the currentObject cursor
     
    746803                initExpr->expr = nullptr;
    747804                std::swap( initExpr->env, newExpr->env );
    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.
     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.
    750808                newExpr->spliceInferParams( initExpr );
    751809                delete initExpr;
    752810
    753                 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
     811                // get the actual object's type (may not exactly match what comes back from the resolver
     812                // due to conversions)
    754813                Type * initContext = currentObject.getCurrentType();
    755814
     
    762821                                if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
    763822                                        if ( isCharType( pt->get_base() ) ) {
    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";
     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";
    766826                                                        newExpr = ce->get_arg();
    767827                                                        ce->set_arg( nullptr );
     
    781841        }
    782842
    783         void Resolver::previsit( ListInit * listInit ) {
     843        void Resolver_old::previsit( ListInit * listInit ) {
    784844                visit_children = false;
    785845                // move cursor into brace-enclosed initializer-list
    786846                currentObject.enterListInit();
    787                 // xxx - fix this so that the list isn't copied, iterator should be used to change current element
     847                // xxx - fix this so that the list isn't copied, iterator should be used to change current
     848                // element
    788849                std::list<Designation *> newDesignations;
    789850                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    790                         // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
    791                         // the initializer against that object.
     851                        // iterate designations and initializers in pairs, moving the cursor to the current
     852                        // designated object and resolving the initializer against that object.
    792853                        Designation * des = std::get<0>(p);
    793854                        Initializer * init = std::get<1>(p);
     
    815876
    816877        // ConstructorInit - fall back on C-style initializer
    817         void Resolver::fallbackInit( ConstructorInit * ctorInit ) {
     878        void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
    818879                // could not find valid constructor, or found an intrinsic constructor
    819880                // fall back on C-style initializer
    820881                delete ctorInit->get_ctor();
    821                 ctorInit->set_ctor( NULL );
     882                ctorInit->set_ctor( nullptr );
    822883                delete ctorInit->get_dtor();
    823                 ctorInit->set_dtor( NULL );
     884                ctorInit->set_dtor( nullptr );
    824885                maybeAccept( ctorInit->get_init(), *visitor );
    825886        }
     
    828889        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
    829890                assert( ctorInit );
    830                 PassVisitor<Resolver> resolver( indexer );
     891                PassVisitor<Resolver_old> resolver( indexer );
    831892                ctorInit->accept( resolver );
    832893        }
     
    834895        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
    835896                assert( stmtExpr );
    836                 PassVisitor<Resolver> resolver( indexer );
     897                PassVisitor<Resolver_old> resolver( indexer );
    837898                stmtExpr->accept( resolver );
    838899                stmtExpr->computeResult();
     
    840901        }
    841902
    842         void Resolver::previsit( ConstructorInit *ctorInit ) {
     903        void Resolver_old::previsit( ConstructorInit * ctorInit ) {
    843904                visit_children = false;
    844905                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
     
    864925
    865926                // xxx - todo -- what about arrays?
    866                 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     927                // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    867928                //      // can reduce the constructor down to a SingleInit using the
    868929                //      // second argument from the ctor call, since
    869930                //      delete ctorInit->get_ctor();
    870                 //      ctorInit->set_ctor( NULL );
     931                //      ctorInit->set_ctor( nullptr );
    871932
    872933                //      Expression * arg =
     
    874935                // }
    875936        }
     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
    8761832} // namespace ResolvExpr
    8771833
  • src/ResolvExpr/Resolver.h

    r7951100 rb067d9b  
    1010// Created On       : Sun May 17 12:18:34 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:36:57 2017
    13 // Update Count     : 3
     12// Last Modified On : Mon Feb 18 20:40:38 2019
     13// Update Count     : 4
    1414//
    1515
    1616#pragma once
    1717
    18 #include <list>  // for list
     18#include <list>          // for list
     19
     20#include "AST/Node.hpp"  // for ptr
    1921
    2022class ConstructorInit;
     
    2325class StmtExpr;
    2426namespace SymTab {
    25 class Indexer;
    26 }  // namespace SymTab
     27        class Indexer;
     28} // namespace SymTab
     29
     30namespace 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
    2740
    2841namespace ResolvExpr {
    2942        /// Checks types and binds syntactic constructs to typed representations
    3043        void resolve( std::list< Declaration * > translationUnit );
    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 );
     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 );
    3649        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    3750        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 );
    3874} // namespace ResolvExpr
    3975
  • src/ResolvExpr/TypeEnvironment.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:19:47 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 17 12:23:36 2015
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jun 18 14:27:00 2019
     13// Update Count     : 5
    1414//
    1515
     
    1717#include <algorithm>                   // for copy, set_intersection
    1818#include <iterator>                    // for ostream_iterator, insert_iterator
     19#include <memory>                      // for unique_ptr
    1920#include <utility>                     // for pair, move
    2021
     
    2223#include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
    2324#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
     25#include "Tuples/Tuples.h"             // for isTtype
    2426#include "TypeEnvironment.h"
     27#include "typeops.h"                   // for occurs
     28#include "Unify.h"                     // for unifyInexact
    2529
    2630namespace ResolvExpr {
     
    6569        }
    6670
     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
    6777        EqvClass &EqvClass::operator=( const EqvClass &other ) {
    6878                if ( this == &other ) return *this;
     
    7282        }
    7383
     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
    7497        EqvClass::~EqvClass() {
    7598                delete type;
     99        }
     100
     101        void EqvClass::set_type( Type* ty ) {
     102                if ( ty == type ) return;
     103                delete type;
     104                type = ty;
    76105        }
    77106
     
    91120
    92121        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    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 );
     122                for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {
     123                        if ( i->vars.find( var ) != i->vars.end() ) return &*i;
    101124                } // for
    102125                return nullptr;
     
    109132                        ++next;
    110133                        std::set<std::string> intersection;
    111                         std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(), 
     134                        std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(),
    112135                                std::inserter( intersection, intersection.begin() ) );
    113136                        if ( ! intersection.empty() ) { env.erase( i ); }
    114137                        i = next;
    115138                }
    116         }
    117 
    118         void TypeEnvironment::add( const EqvClass &eqvClass ) {
    119                 filterOverlappingClasses( env, eqvClass );
    120                 env.push_back( eqvClass );
    121139        }
    122140
     
    131149                        newClass.vars.insert( (*i)->get_name() );
    132150                        newClass.data = TypeDecl::Data{ (*i) };
    133                         env.push_back( newClass );
     151                        env.push_back( std::move(newClass) );
    134152                } // for
    135153        }
     
    145163                        // transition to TypeSubstitution
    146164                        newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
    147                         add( newClass );
     165                        add( std::move(newClass) );
    148166                }
    149167        }
    150168
    151169        void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const {
    152                 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
     170                for ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    153171                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    154 ///       std::cerr << "adding " << *theVar;
    155172                                if ( theClass->type ) {
    156 ///         std::cerr << " bound to ";
    157 ///         theClass->type->print( std::cerr );
    158 ///         std::cerr << std::endl;
    159173                                        sub.add( *theVar, theClass->type );
    160174                                } else if ( theVar != theClass->vars.begin() ) {
    161175                                        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;
    163176                                        sub.add( *theVar, newTypeInst );
    164177                                        delete newTypeInst;
     
    166179                        } // for
    167180                } // 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 );
    172181                sub.normalize();
    173182        }
     
    179188        }
    180189
    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
     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;
    186193                } // for
    187194                return env.end();
     
    192199        }
    193200
    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
     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;
    222296        }
    223297
    224298        void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const {
    225                 for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
     299                for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
    226300                        for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {
    227301                                openVars[ *var ] = eqvClass->data;
     
    241315        }
    242316
     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
    243474        std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {
    244475                env.print( out );
  • src/ResolvExpr/TypeEnvironment.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:24:58 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:35:45 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jul 19 17:00:10 2019
     13// Update Count     : 10
    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 <set>                         // for set
     20#include <map>                                             // for map, map<>::value_compare
     21#include <unordered_map>
     22#include <set>                                             // for set
    2223#include <string>                      // for string
     24#include <utility>                     // for move, swap
     25
     26#include "WidenMode.h"                 // for WidenMode
    2327
    2428#include "SynTree/Declaration.h"       // for TypeDecl::Data, DeclarationWit...
     
    3640        // declarations.
    3741        //
    38         // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
     42        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
     43        // comparator.
    3944        //
    4045        // Note: since this compares pointers for position, minor changes in the source file that affect
    4146        // memory layout can alter compilation time in unpredictable ways. For example, the placement
    4247        // of a line directive can reorder type pointers with respect to each other so that assertions
    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.
     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.
    4854        struct AssertCompare {
    49                 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
     55                bool operator()( const DeclarationWithType * d1, const DeclarationWithType * d2 ) const {
    5056                        int cmp = d1->get_name().compare( d2->get_name() );
    5157                        return cmp < 0 ||
     
    5460        };
    5561        struct AssertionSetValue {
    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;
     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) {}
    6166        };
    62         typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet;
    63         typedef std::map< std::string, TypeDecl::Data > OpenVarSet;
     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        }
    6474
    6575        void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 );
     
    6878        struct EqvClass {
    6979                std::set< std::string > vars;
    70                 Type *type;
     80                Type * type;
    7181                bool allowWidening;
    7282                TypeDecl::Data data;
     
    7787                EqvClass( const EqvClass &other );
    7888                EqvClass( const EqvClass &other, const Type *ty );
     89                EqvClass( EqvClass &&other );
    7990                EqvClass &operator=( const EqvClass &other );
     91                EqvClass &operator=( EqvClass &&other );
    8092                ~EqvClass();
    8193                void print( std::ostream &os, Indenter indent = {} ) const;
     94
     95                /// Takes ownership of `ty`, freeing old `type`
     96                void set_type(Type* ty);
    8297        };
    8398
    8499        class TypeEnvironment {
     100                using ClassList = std::list< EqvClass >;
    85101          public:
    86102                const EqvClass* lookup( const std::string &var ) const;
    87                 void add( const EqvClass &eqvClass );
     103          private:
    88104                void add( EqvClass &&eqvClass  );
     105          public:
    89106                void add( const Type::ForallList &tyDecls );
    90107                void add( const TypeSubstitution & sub );
     
    94111                bool isEmpty() const { return env.empty(); }
    95112                void print( std::ostream &os, Indenter indent = {} ) const;
    96                 void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
     113
     114                /// Simply concatenate the second environment onto this one; no safety checks performed
    97115                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
    98129                void extractOpenVars( OpenVarSet &openVars ) const;
    99130                TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
     
    103134                void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
    104135
    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(); }
     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
    111151          private:
    112                 std::list< EqvClass > env;
    113                 std::list< EqvClass >::iterator internal_lookup( const std::string &var );
     152                ClassList env;
     153
     154                ClassList::iterator internal_lookup( const std::string &var );
    114155        };
    115156
  • src/ResolvExpr/Unify.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 16:22:54 2017
    13 // Update Count     : 42
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Sep  4 10:00:00 2019
     13// Update Count     : 44
    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
    3516#include "Unify.h"
    36 #include "typeops.h"              // for flatten, occurs, commonType
     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
     45namespace ast {
     46        class SymbolTable;
     47}
    3748
    3849namespace SymTab {
     
    4455namespace ResolvExpr {
    4556
    46         struct Unify : public WithShortCircuiting {
    47                 Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     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 );
    4859
    4960                bool get_result() const { return result; }
     
    7788                AssertionSet &haveAssertions;
    7889                const OpenVarSet &openVars;
    79                 WidenMode widenMode;
     90                WidenMode widen;
    8091                const SymTab::Indexer &indexer;
    8192        };
     
    8394        /// Attempts an inexact unification of type1 and type2.
    8495        /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
    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 ) {
     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 ) {
    89105                TypeEnvironment newEnv;
    90106                OpenVarSet openVars, closedVars; // added closedVars
    91107                AssertionSet needAssertions, haveAssertions;
    92                 Type *newFirst = first->clone(), *newSecond = second->clone();
     108                Type * newFirst = first->clone(), * newSecond = second->clone();
    93109                env.apply( newFirst );
    94110                env.apply( newSecond );
     
    105121        }
    106122
    107         bool typesCompatibleIgnoreQualifiers( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     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 ) {
    108142                TypeEnvironment newEnv;
    109143                OpenVarSet openVars;
     
    129163        }
    130164
    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;
     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 );
    277180        }
    278181
     
    299202        }
    300203
    301         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     204        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    302205#ifdef DEBUG
    303206                TypeEnvironment debugEnv( env );
     
    320223                bool isopen2 = var2 && ( entry2 != openVars.end() );
    321224
    322                 if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    323                         result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     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                        }
    324233                } else if ( isopen1 ) {
    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 );
     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 );
    328237                } else {
    329                         PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     238                        PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );
    330239                        type1->accept( comparator );
    331240                        result = comparator.pass.get_result();
     
    352261        }
    353262
    354         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ) {
     263        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) {
    355264                Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
    356265                type1->get_qualifiers() = Type::Qualifiers();
     
    364273                std::cerr << std::endl;
    365274#endif
    366                 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) {
     275                if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) {
    367276#ifdef DEBUG
    368277                        std::cerr << "unifyInexact: no exact unification found" << std::endl;
    369278#endif
    370                         if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
    371                                 common->get_qualifiers() = tq1 | tq2;
     279                        if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) {
     280                                common->tq = tq1.unify( tq2 );
    372281#ifdef DEBUG
    373282                                std::cerr << "unifyInexact: common type is ";
     
    384293                } else {
    385294                        if ( tq1 != tq2 ) {
    386                                 if ( ( tq1 > tq2 || widenMode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {
     295                                if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) {
    387296                                        common = type1->clone();
    388                                         common->get_qualifiers() = tq1 | tq2;
     297                                        common->tq = tq1.unify( tq2 );
    389298                                        result = true;
    390299                                } else {
     
    393302                        } else {
    394303                                common = type1->clone();
    395                                 common->get_qualifiers() = tq1 | tq2;
     304                                common->tq = tq1.unify( tq2 );
    396305                                result = true;
    397306                        } // if
     
    402311        }
    403312
    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) {
     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) {
    409318                result = dynamic_cast< VoidType* >( type2 );
    410319        }
    411320
    412         void Unify::postvisit(BasicType *basicType) {
     321        void Unify_old::postvisit(BasicType *basicType) {
    413322                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    414323                        result = basicType->get_kind() == otherBasic->get_kind();
     
    438347        }
    439348
    440         void Unify::postvisit(PointerType *pointerType) {
     349        void Unify_old::postvisit(PointerType *pointerType) {
    441350                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    442351                        result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    446355        }
    447356
    448         void Unify::postvisit(ReferenceType *refType) {
     357        void Unify_old::postvisit(ReferenceType *refType) {
    449358                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    450359                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    454363        }
    455364
    456         void Unify::postvisit(ArrayType *arrayType) {
     365        void Unify_old::postvisit(ArrayType *arrayType) {
    457366                ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    458367                // to unify, array types must both be VLA or both not VLA
     
    534443        /// If this isn't done then argument lists can have wildly different
    535444        /// size and structure, when they should be compatible.
    536         struct TtypeExpander : public WithShortCircuiting {
     445        struct TtypeExpander_old : public WithShortCircuiting {
    537446                TypeEnvironment & tenv;
    538                 TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {}
     447                TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {}
    539448                void premutate( TypeInstType * ) { visit_children = false; }
    540449                Type * postmutate( TypeInstType * typeInst ) {
     
    555464                dst.clear();
    556465                for ( DeclarationWithType * dcl : src ) {
    557                         PassVisitor<TtypeExpander> expander( env );
     466                        PassVisitor<TtypeExpander_old> expander( env );
    558467                        dcl->acceptMutator( expander );
    559468                        std::list< Type * > types;
     
    570479        }
    571480
    572         void Unify::postvisit(FunctionType *functionType) {
     481        void Unify_old::postvisit(FunctionType *functionType) {
    573482                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    574483                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
     
    581490
    582491                        // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    583                         if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
     492                        if (
     493                                        (flatFunc->parameters.size() == flatOther->parameters.size() &&
     494                                                flatFunc->returnVals.size() == flatOther->returnVals.size())
     495                                        || flatFunc->isTtype()
     496                                        || flatOther->isTtype()
     497                        ) {
    584498                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    585499                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     
    597511
    598512        template< typename RefType >
    599         void Unify::handleRefType( RefType *inst, Type *other ) {
     513        void Unify_old::handleRefType( RefType *inst, Type *other ) {
    600514                // check that other type is compatible and named the same
    601515                RefType *otherStruct = dynamic_cast< RefType* >( other );
     
    604518
    605519        template< typename RefType >
    606         void Unify::handleGenericRefType( RefType *inst, Type *other ) {
     520        void Unify_old::handleGenericRefType( RefType *inst, Type *other ) {
    607521                // Check that other type is compatible and named the same
    608522                handleRefType( inst, other );
     
    672586        }
    673587
    674         void Unify::postvisit(StructInstType *structInst) {
     588        void Unify_old::postvisit(StructInstType *structInst) {
    675589                handleGenericRefType( structInst, type2 );
    676590        }
    677591
    678         void Unify::postvisit(UnionInstType *unionInst) {
     592        void Unify_old::postvisit(UnionInstType *unionInst) {
    679593                handleGenericRefType( unionInst, type2 );
    680594        }
    681595
    682         void Unify::postvisit(EnumInstType *enumInst) {
     596        void Unify_old::postvisit(EnumInstType *enumInst) {
    683597                handleRefType( enumInst, type2 );
    684598        }
    685599
    686         void Unify::postvisit(TraitInstType *contextInst) {
     600        void Unify_old::postvisit(TraitInstType *contextInst) {
    687601                handleRefType( contextInst, type2 );
    688602        }
    689603
    690         void Unify::postvisit(TypeInstType *typeInst) {
     604        void Unify_old::postvisit(TypeInstType *typeInst) {
    691605                assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    692606                TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
     
    743657        }
    744658
    745         void Unify::postvisit(TupleType *tupleType) {
     659        void Unify_old::postvisit(TupleType *tupleType) {
    746660                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    747661                        std::unique_ptr<TupleType> flat1( tupleType->clone() );
     
    749663                        std::list<Type *> types1, types2;
    750664
    751                         PassVisitor<TtypeExpander> expander( env );
     665                        PassVisitor<TtypeExpander_old> expander( env );
    752666                        flat1->acceptMutator( expander );
    753667                        flat2->acceptMutator( expander );
     
    760674        }
    761675
    762         void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
     676        void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    763677                result = dynamic_cast< VarArgsType* >( type2 );
    764678        }
    765679
    766         void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
     680        void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    767681                result = dynamic_cast< ZeroType* >( type2 );
    768682        }
    769683
    770         void Unify::postvisit( __attribute__((unused)) OneType *oneType ) {
     684        void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) {
    771685                result = dynamic_cast< OneType* >( type2 );
    772686        }
    773687
    774         // xxx - compute once and store in the FunctionType?
    775688        Type * extractResultType( FunctionType * function ) {
    776689                if ( function->get_returnVals().size() == 0 ) {
     
    786699                }
    787700        }
     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        }
    7881241} // namespace ResolvExpr
    7891242
  • src/ResolvExpr/Unify.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 23:09:34 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    1818#include <list>                   // for list
    1919
     20#include "AST/Node.hpp"             // for ptr
     21#include "AST/TypeEnvironment.hpp"  // for TypeEnvironment, AssertionSet, OpenVarSet
    2022#include "Common/utility.h"       // for deleteAll
    2123#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2224#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
     25#include "WidenMode.h"              // for WidenMode
    2326
    2427class Type;
    2528class TypeInstType;
    2629namespace SymTab {
    27 class Indexer;
    28 }  // namespace SymTab
     30        class Indexer;
     31}
     32
     33namespace ast {
     34        class SymbolTable;
     35        class Type;
     36}
    2937
    3038namespace 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 );
    4339        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    4440        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    4541        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 );
    4643
    4744        template< typename Iterator1, typename Iterator2 >
     
    7269        }
    7370
     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
    7492} // namespace ResolvExpr
    7593
  • src/ResolvExpr/module.mk

    r7951100 rb067d9b  
    1515###############################################################################
    1616
    17 SRC += 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
     17SRC_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
     43SRC += $(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc
     44SRCDEMANGLE += $(SRC_RESOLVEXPR)
  • src/ResolvExpr/typeops.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 07:28:22 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:36:18 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Aug  8 16:36:00 2019
     13// Update Count     : 5
    1414//
    1515
     
    1818#include <vector>
    1919
     20#include "Cost.h"
     21#include "TypeEnvironment.h"
     22#include "WidenMode.h"
     23#include "AST/Fwd.hpp"
     24#include "AST/Node.hpp"
     25#include "AST/SymbolTable.hpp"
     26#include "AST/Type.hpp"
     27#include "AST/TypeEnvironment.hpp"
    2028#include "SynTree/SynTree.h"
    2129#include "SynTree/Type.h"
    22 #include "SymTab/Indexer.h"
    23 #include "Cost.h"
    24 #include "TypeEnvironment.h"
     30
     31namespace SymTab {
     32        class Indexer;
     33}
    2534
    2635namespace ResolvExpr {
     
    5463        // in AdjustExprType.cc
    5564        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
    56         void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     65        void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
    5766
    5867        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
     
    6069
    6170        template< typename ForwardIterator >
    62         void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     71        void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
    6372                while ( begin != end ) {
    6473                        adjustExprType( *begin++, env, indexer );
     
    6675        }
    6776
     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
    6881        // in CastCost.cc
    69         Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     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 );
    7087
    7188        // in ConversionCost.cc
    72         Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     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 );
    7398
    7499        // in PtrsAssignable.cc
    75         int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env );
     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 );
    76103
    77104        // in PtrsCastable.cc
    78         int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     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 );
    79109
    80110        // in Unify.cc
    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 );
    84 
    85         inline bool typesCompatible( Type *t1, Type *t2, const SymTab::Indexer &indexer ) {
     111        bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
     112        bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
     113
     114        inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    86115                TypeEnvironment env;
    87116                return typesCompatible( t1, t2, indexer, env );
    88117        }
    89118
    90         inline bool typesCompatibleIgnoreQualifiers( Type *t1, Type *t2, const SymTab::Indexer &indexer ) {
     119        inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    91120                TypeEnvironment env;
    92121                return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
    93122        }
    94123
     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
    95132        /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
    96133        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 );
    97136
    98137        // in CommonType.cc
    99         Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
     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 );
    100142
    101143        // in PolyCost.cc
    102         int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     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 );
    103151
    104152        // in Occurs.cc
    105         bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
     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        }
    106164
    107165        // in AlternativeFinder.cc
    108166        void referenceToRvalueConversion( Expression *& expr, Cost & cost );
    109 
    110         // flatten tuple type into list of types
     167        // in CandidateFinder.cpp
     168        const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );
     169
     170        /// flatten tuple type into list of types
    111171        template< typename OutputIterator >
    112172        void flatten( Type * type, OutputIterator out ) {
     
    119179                }
    120180        }
     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 );
    121205} // namespace ResolvExpr
     206
     207namespace ast {
     208        // in TypeEnvironment.cpp
     209        bool isFtype( const ast::Type * type );
     210} // namespace ast
    122211
    123212// Local Variables: //
  • src/SymTab/Autogen.cc

    r7951100 rb067d9b  
    2424#include <vector>                  // for vector
    2525
     26#include "AST/Decl.hpp"
    2627#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2728#include "Common/PassVisitor.h"    // for PassVisitor
     
    4142
    4243namespace SymTab {
    43         Type * SizeType = 0;
    44 
    4544        /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
    4645        struct FuncData {
    47                 typedef FunctionType * (*TypeGen)( Type * );
     46                typedef FunctionType * (*TypeGen)( Type *, bool );
    4847                FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
    4948                std::string fname;
     
    211210        }
    212211
     212        bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
     213                return obj && obj->name.empty() && obj->bitfieldWidth;
     214        }
     215
    213216        /// inserts a forward declaration for functionDecl into declsToAdd
    214217        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
     
    231234
    232235        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    233         FunctionType * genDefaultType( Type * paramType ) {
    234                 const auto & typeParams = getGenericParams( paramType );
     236        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
    235237                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    236                 cloneAll( typeParams, ftype->forall );
     238                if ( maybePolymorphic ) {
     239                        // only copy in
     240                        const auto & typeParams = getGenericParams( paramType );
     241                        cloneAll( typeParams, ftype->forall );
     242                }
    237243                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    238244                ftype->parameters.push_back( dstParam );
     
    241247
    242248        /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
    243         FunctionType * genCopyType( Type * paramType ) {
    244                 FunctionType *ftype = genDefaultType( paramType );
     249        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
     250                FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
    245251                ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    246252                ftype->parameters.push_back( srcParam );
     
    249255
    250256        /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
    251         FunctionType * genAssignType( Type * paramType ) {
    252                 FunctionType *ftype = genCopyType( paramType );
     257        FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
     258                FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
    253259                ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    254260                ftype->returnVals.push_back( returnVal );
     
    308314                for ( const FuncData & d : data ) {
    309315                        // generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
    310                         FunctionType * ftype = d.genType( type );
     316                        FunctionType * ftype = d.genType( type, true );
    311317
    312318                        // destructor for concurrent type must be mutex
     
    387393
    388394        void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) {
    389                 InitTweak::InitExpander srcParam( src );
     395                InitTweak::InitExpander_old srcParam( src );
    390396
    391397                // assign to destination
  • src/SymTab/Autogen.h

    r7951100 rb067d9b  
    1717
    1818#include <cassert>                // for assert
     19#include <iterator>               // for back_inserter
    1920#include <string>                 // for string
    2021
     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"
    2128#include "CodeGen/OperatorTable.h"
    2229#include "Common/UniqueName.h"    // for UniqueName
     30#include "Common/utility.h"       // for splice
    2331#include "InitTweak/InitTweak.h"  // for InitExpander
    2432#include "SynTree/Constant.h"     // for Constant
     
    3644        /// returns true if obj's name is the empty string and it has a bitfield width
    3745        bool isUnnamedBitfield( ObjectDecl * obj );
    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 );
     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 };
    5562
    5663        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    5764        template< typename OutputIterator >
    58         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
     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 );
    5972
    6073        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    6174        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    6275        template< typename OutputIterator >
    63         Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
     76        Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
    6477                bool isReferenceCtorDtor = false;
    6578                if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     
    8497                        //   type->get_qualifiers() = Type::Qualifiers();
    8598                        Type * castType = addCast->clone();
    86                         castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     99                        castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    87100                        // castType->set_lvalue( true ); // xxx - might not need this
    88101                        dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
     
    111124        }
    112125
     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
    113183        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    114184        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    115185        template< typename OutputIterator >
    116         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
     186        void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
    117187                static UniqueName indexName( "_index" );
    118188
     
    175245        }
    176246
     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
    177317        template< typename OutputIterator >
    178         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     318        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
    179319                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    180320                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     
    185325        }
    186326
     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
    187344        /// inserts into out a generated call expression to function fname with arguments dstParam
    188345        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     
    190347        /// ImplicitCtorDtorStmt node.
    191348        template< typename OutputIterator >
    192         void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     349        void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    193350                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    194351                assert( obj );
     
    218375                }
    219376        }
     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        }
    220411} // namespace SymTab
    221412
  • src/SymTab/FixFunction.cc

    r7951100 rb067d9b  
    1818#include <list>                   // for list
    1919
    20 #include "Common/utility.h"       // for maybeClone
     20#include "AST/Decl.hpp"
     21#include "AST/Pass.hpp"
     22#include "AST/Type.hpp"
     23#include "Common/utility.h"       // for maybeClone, copy
    2124#include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
    2225#include "SynTree/Expression.h"   // for Expression
     
    2427
    2528namespace SymTab {
    26         FixFunction::FixFunction() : isVoid( false ) {}
     29        class FixFunction_old : public WithShortCircuiting {
     30                typedef Mutator Parent;
     31          public:
     32                FixFunction_old() : isVoid( false ) {}
    2733
     34                void premutate(FunctionDecl *functionDecl);
     35                DeclarationWithType* postmutate(FunctionDecl *functionDecl);
    2836
    29         DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
     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) {
    3057                // can't delete function type because it may contain assertions, so transfer ownership to new object
    3158                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;
    3260                functionDecl->attributes.clear();
    3361                functionDecl->type = nullptr;
     
    4068        // does not cause an error
    4169
    42         Type * FixFunction::postmutate(ArrayType *arrayType) {
     70        Type * FixFunction_old::postmutate(ArrayType *arrayType) {
    4371                // need to recursively mutate the base type in order for multi-dimensional arrays to work.
    4472                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
     73                pointerType->location = arrayType->location;
    4574                arrayType->base = nullptr;
    4675                arrayType->dimension = nullptr;
     
    4978        }
    5079
    51         void FixFunction::premutate(VoidType *) {
     80        void FixFunction_old::premutate(VoidType *) {
    5281                isVoid = true;
    5382        }
    5483
    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; }
     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; }
    6897
    6998        bool fixFunction( DeclarationWithType *& dwt ) {
    70                 PassVisitor<FixFunction> fixer;
     99                PassVisitor<FixFunction_old> fixer;
    71100                dwt = dwt->acceptMutator( fixer );
    72101                return fixer.pass.isVoid;
    73102        }
     103
     104namespace {
     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
     140const 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
    74147} // namespace SymTab
    75148
  • src/SymTab/FixFunction.h

    r7951100 rb067d9b  
    1919#include "SynTree/SynTree.h"    // for Types
    2020
     21namespace ast {
     22        class DeclWithType;
     23}
     24
    2125namespace SymTab {
    22         /// Replaces function and array types by equivalent pointer types.
    23         class FixFunction : public WithShortCircuiting {
    24                 typedef Mutator Parent;
    25           public:
    26                 FixFunction();
     26        /// Replaces function and array types by equivalent pointer types. Returns true if type is
     27        /// void
     28        bool fixFunction( DeclarationWithType *& );
    2729
    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 
    50         bool fixFunction( DeclarationWithType *& );
     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 );
    5133} // namespace SymTab
    5234
  • src/SymTab/Indexer.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:37:33 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 17 16:08:40 2017
    13 // Update Count     : 20
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Mar  8 13:55:00 2019
     13// Update Count     : 21
    1414//
    1515
     
    1717
    1818#include <cassert>                 // for assert, strict_dynamic_cast
    19 #include <iostream>                // for operator<<, basic_ostream, ostream
    2019#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
    2425
    2526#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2627#include "Common/SemanticError.h"  // for SemanticError
    2728#include "Common/utility.h"        // for cloneAll
    28 #include "GenPoly/GenPoly.h"
     29#include "Common/Stats/Counter.h"  // for counters
     30#include "GenPoly/GenPoly.h"       // for getFunctionType
    2931#include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
    3032#include "Mangler.h"               // for Mangler
     
    3840#include "SynTree/Type.h"          // for Type, StructInstType, UnionInstType
    3941
    40 #define debugPrint(x) if ( doDebug ) { std::cerr << x; }
    41 
    4242namespace SymTab {
    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;
     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)
    11471                        };
    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         }
     72                        return ret;
     73                }
     74        }
     75
     76        Indexer::Indexer()
     77        : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(),
     78          prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; }
    19679
    19780        Indexer::~Indexer() {
    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 ) {
     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 ) {
    377191                return GenPoly::getFunctionType( decl->get_type() );
    378192        }
    379193
    380         bool isObject( DeclarationWithType * decl ) {
     194        bool isObject( const DeclarationWithType * decl ) {
    381195                return ! isFunction( decl );
    382196        }
    383197
    384         bool isDefinition( DeclarationWithType * decl ) {
    385                 if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
     198        bool isDefinition( const DeclarationWithType * decl ) {
     199                if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
    386200                        // a function is a definition if it has a body
    387201                        return func->statements;
     
    393207        }
    394208
    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
     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
    397215                assert( (isObject( added ) && isObject( existing.id ) )
    398216                        || ( isFunction( added ) && isFunction( existing.id ) ) );
    399217
    400                 if ( LinkageSpec::isOverridable( existing.id->get_linkage() ) ) {
     218                if ( LinkageSpec::isOverridable( existing.id->linkage ) ) {
    401219                        // new definition shadows the autogenerated one, even at the same scope
    402220                        return false;
    403                 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) {
     221                } else if ( LinkageSpec::isMangled( added->linkage )
     222                                || ResolvExpr::typesCompatible(
     223                                        added->get_type(), existing.id->get_type(), Indexer() ) ) {
    404224
    405225                        // it is a conflict if one declaration is deleted and the other is not
    406226                        if ( deleteStmt && ! existing.deleteStmt ) {
    407                                 return handleConflicts( existing, "deletion of defined identifier " );
     227                                if ( handleConflicts.mode == OnConflict::Error ) {
     228                                        SemanticError( added, "deletion of defined identifier " );
     229                                }
     230                                return true;
    408231                        } else if ( ! deleteStmt && existing.deleteStmt ) {
    409                                 return handleConflicts( existing, "definition of deleted identifier " );
     232                                if ( handleConflicts.mode == OnConflict::Error ) {
     233                                        SemanticError( added, "definition of deleted identifier " );
     234                                }
     235                                return true;
    410236                        }
    411237
    412238                        if ( isDefinition( added ) && isDefinition( existing.id ) ) {
    413                                 if ( isFunction( added ) ) {
    414                                         return handleConflicts( existing, "duplicate function definition for " );
     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;
     246                        } // if
     247                } else {
     248                        if ( handleConflicts.mode == OnConflict::Error ) {
     249                                SemanticError( added, "duplicate definition for " );
     250                        }
     251                        return true;
     252                } // if
     253
     254                return true;
     255        }
     256
     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                                        }
    415356                                } else {
    416                                         return handleConflicts( existing, "duplicate object definition for " );
    417                                 } // if
    418                         } // if
    419                 } else {
    420                         return handleConflicts( existing, "duplicate definition for " );
    421                 } // if
    422 
     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
    423430                return true;
    424431        }
    425432
    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 
     433        void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr,
     434                        const Declaration * deleteStmt ) {
     435                ++* stats().add_calls;
    431436                const std::string &name = decl->name;
     437                if ( name == "" ) return;
     438
    432439                std::string mangleName;
    433440                if ( LinkageSpec::isOverridable( decl->linkage ) ) {
    434                         // mangle the name without including the appropriate suffix, so overridable routines are placed into the
    435                         // same "bucket" as their user defined versions.
     441                        // mangle the name without including the appropriate suffix, so overridable routines
     442                        // are placed into the same "bucket" as their user defined versions.
    436443                        mangleName = Mangler::mangle( decl, false );
    437444                } else {
     
    439446                } // if
    440447
    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 ) ) {
     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 ) ) {
     451                        // Check that a Cforall declaration doesn't override any C declaration
     452                        if ( hasCompatibleCDecl( name, mangleName ) ) {
     453                                SemanticError( decl, "Cforall declaration hides C function " );
     454                        }
     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 ) ) {
    449459                                SemanticError( decl, "conflicting overload of C function " );
    450460                        }
    451                 } else {
    452                         // Check that a Cforall declaration doesn't override any C declaration
    453                         if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
    454                                 SemanticError( decl, "Cforall declaration hides C function " );
    455                         }
    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 ) {
     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 ) {
    468508                // default handling of conflicts is to raise an error
    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 ) {
     509                addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
     510        }
     511
     512        void Indexer::addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt ) {
    473513                // default handling of conflicts is to raise an error
    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 ) {
     514                addId( decl, OnConflict::error(), nullptr, deleteStmt );
     515        }
     516
     517        bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) {
     518                if ( existing->base == nullptr ) {
    479519                        return false;
    480                 } else if ( added->get_base() == 0 ) {
     520                } else if ( added->base == nullptr ) {
    481521                        return true;
    482522                } else {
    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 ) {
     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 ) {
    507554                if ( ! existing->body ) {
    508555                        return false;
     
    513560        }
    514561
    515         void Indexer::addStruct( const std::string &id ) {
    516                 debugPrint( "Adding fwd decl for struct " << id << std::endl );
     562        void Indexer::addStruct( const std::string & id ) {
    517563                addStruct( new StructDecl( id ) );
    518564        }
    519565
    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 );
     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 ) {
    560605                addUnion( new UnionDecl( id ) );
    561606        }
    562607
    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 ) {
     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 ) {
    602647                for ( Declaration * decl : aggr->members ) {
    603648                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    604649                                addId( dwt, handleConflicts, expr );
    605650                                if ( dwt->name == "" ) {
    606                                         Type * t = dwt->get_type()->stripReferences();
    607                                         if ( dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ) ) {
     651                                        const Type * t = dwt->get_type()->stripReferences();
     652                                        if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) {
    608653                                                Expression * base = expr->clone();
    609654                                                ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost?
     
    616661        }
    617662
    618         void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ) {
    619                 for ( Expression * expr : withExprs ) {
     663        void Indexer::addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt ) {
     664                for ( const Expression * expr : withExprs ) {
    620665                        if ( expr->result ) {
    621666                                AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
    622667                                assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
    623668
    624                                 addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) {
    625                                         // on conflict, delete the identifier
    626                                         existing.deleteStmt = withStmt;
    627                                         return true;
    628                                 });
     669                                addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) );
    629670                        }
    630671                }
     
    644685        }
    645686
    646         void Indexer::addFunctionType( FunctionType * ftype ) {
     687        void Indexer::addFunctionType( const FunctionType * ftype ) {
    647688                addTypes( ftype->forall );
    648689                addIds( ftype->returnVals );
    649690                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 
    710691        }
    711692
     
    715696                        Expression * base = baseExpr->clone();
    716697                        ResolvExpr::referenceToRvalueConversion( base, cost );
    717                         ret = new MemberExpr( id, base );
     698                        ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base );
    718699                        // xxx - this introduces hidden environments, for now remove them.
    719700                        // std::swap( base->env, ret->env );
     
    721702                        base->env = nullptr;
    722703                } else {
    723                         ret = new VariableExpr( id );
    724                 }
    725                 if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt );
     704                        ret = new VariableExpr( const_cast<DeclarationWithType *>(id) );
     705                }
     706                if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<Declaration *>(deleteStmt) );
    726707                return ret;
    727708        }
  • src/SymTab/Indexer.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:38:55 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 17 16:09:12 2017
    13 // Update Count     : 8
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Mar  8 13:55:00 2019
     13// Update Count     : 9
    1414//
    1515
    1616#pragma once
    1717
    18 #include <iosfwd>             // for ostream
    19 #include <list>               // for list
    20 #include <string>             // for string
    21 #include <functional>         // for function
     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
    2222
    23 #include "SynTree/Visitor.h"  // for Visitor
    24 #include "SynTree/SynTree.h"  // for AST nodes
     23#include "Common/PersistentMap.h"  // for PersistentMap
     24#include "SynTree/SynTree.h"       // for AST nodes
    2525
    2626namespace ResolvExpr {
    27 class Cost;
     27        class Cost;
    2828}
    2929
    3030namespace SymTab {
    31         class Indexer {
    32           public:
     31        class Indexer : public std::enable_shared_from_this<SymTab::Indexer> {
     32        public:
    3333                explicit Indexer();
     34                virtual ~Indexer();
    3435
    35                 Indexer( const Indexer &that );
    36                 Indexer( Indexer &&that );
    37                 virtual ~Indexer();
    38                 Indexer& operator= ( const Indexer &that );
    39                 Indexer& operator= ( Indexer &&that );
    40 
    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
     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
    4338                void enterScope();
    4439                void leaveScope();
    4540
    4641                struct IdData {
    47                         DeclarationWithType * id = nullptr;
    48                         Expression * baseExpr = nullptr; // WithExpr
     42                        const DeclarationWithType * id = nullptr;
     43                        const Expression * baseExpr = nullptr; // WithExpr
    4944
    5045                        /// non-null if this declaration is deleted
    51                         BaseSyntaxNode * deleteStmt = nullptr;
     46                        const Declaration * deleteStmt = nullptr;
     47                        /// scope of identifier
     48                        unsigned long scope = 0;
    5249
    5350                        // NOTE: shouldn't need either of these constructors, but gcc-4 does not properly support initializer lists with default members.
    5451                        IdData() = default;
    55                         IdData( DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ) {}
     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 ) {}
    5658
    5759                        Expression * combine( ResolvExpr::Cost & cost ) const;
     
    5961
    6062                /// Gets all declarations with the given ID
    61                 void lookupId( const std::string &id, std::list< IdData > &out ) const;
     63                void lookupId( const std::string & id, std::list< IdData > &out ) const;
    6264                /// Gets the top-most type declaration with the given ID
    63                 NamedTypeDecl *lookupType( const std::string &id ) const;
     65                const NamedTypeDecl * lookupType( const std::string & id ) const;
    6466                /// Gets the top-most struct declaration with the given ID
    65                 StructDecl *lookupStruct( const std::string &id ) const;
     67                const StructDecl * lookupStruct( const std::string & id ) const;
    6668                /// Gets the top-most enum declaration with the given ID
    67                 EnumDecl *lookupEnum( const std::string &id ) const;
     69                const EnumDecl * lookupEnum( const std::string & id ) const;
    6870                /// Gets the top-most union declaration with the given ID
    69                 UnionDecl *lookupUnion( const std::string &id ) const;
     71                const UnionDecl * lookupUnion( const std::string & id ) const;
    7072                /// Gets the top-most trait declaration with the given ID
    71                 TraitDecl *lookupTrait( const std::string &id ) const;
     73                const TraitDecl * lookupTrait( const std::string & id ) const;
    7274
    73                 void print( std::ostream &os, int indent = 0 ) const;
     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;
    7483
    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;
     84                void addId( const DeclarationWithType * decl, const Expression * baseExpr = nullptr );
     85                void addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt );
    8886
    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 );
     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 );
    10194
    10295                /// adds all of the IDs from WithStmt exprs
    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 );
     96                void addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt );
    10797
    10898                /// convenience function for adding a list of Ids to the indexer
     
    113103
    114104                /// convenience function for adding all of the declarations in a function type to the indexer
    115                 void addFunctionType( FunctionType * ftype );
     105                void addFunctionType( const FunctionType * ftype );
    116106
    117                 bool doDebug = false; ///< Display debugging trace?
    118107          private:
    119                 struct Impl;
     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
    120113
    121                 Impl *tables;         ///< Copy-on-write instance of table data structure
    122                 unsigned long scope;  ///< Scope index of this pointer
     114                        Scoped(const Decl * d, unsigned long s) : decl(d), scope(s) {}
     115                };
    123116
    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 );
     117                using Ptr = std::shared_ptr<const Indexer>;
    128118
    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;
     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> >;
    133126
    134                 /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
    135                 void makeWritable();
     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 );
    136170
    137171                /// common code for addId, addDeletedId, etc.
    138                 void addId( DeclarationWithType * decl, ConflictFunction, Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr );
     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;
    139182        };
    140183} // namespace SymTab
  • src/SymTab/Mangler.cc

    r7951100 rb067d9b  
    1010// Created On       : Sun May 17 21:40:29 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 15:49:26 2017
    13 // Update Count     : 23
     12// Last Modified On : Tue Jul 30 13:46:10 2019
     13// Update Count     : 26
    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 "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...
     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"
    3235
    3336namespace SymTab {
     
    3538                namespace {
    3639                        /// Mangles names to a unique C identifier
    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 );
     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 );
    6266
    6367                                std::string get_mangleName() { return mangleName.str(); }
     
    7276                                bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
    7377                                bool inFunctionType = false;    ///< Include type qualifiers if false.
    74 
    75                                 void mangleDecl( DeclarationWithType *declaration );
    76                                 void mangleRef( ReferenceToType *refType, std::string prefix );
    77 
    78                                 void printQualifiers( Type *type );
    79                         }; // Mangler
     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
    8090                } // namespace
    8191
    82                 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
    83                         PassVisitor<Mangler> mangler( mangleOverridable, typeMode, mangleGenericParams );
     92                std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
     93                        PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
    8494                        maybeAccept( decl, mangler );
    8595                        return mangler.pass.get_mangleName();
    8696                }
    8797
    88                 std::string mangleType( Type * ty ) {
    89                         PassVisitor<Mangler> mangler( false, true, true );
     98                std::string mangleType( const Type * ty ) {
     99                        PassVisitor<Mangler_old> mangler( false, true, true );
    90100                        maybeAccept( ty, mangler );
    91101                        return mangler.pass.get_mangleName();
    92102                }
    93103
    94                 std::string mangleConcrete( Type * ty ) {
    95                         PassVisitor<Mangler> mangler( false, false, false );
     104                std::string mangleConcrete( const Type * ty ) {
     105                        PassVisitor<Mangler_old> mangler( false, false, false );
    96106                        maybeAccept( ty, mangler );
    97107                        return mangler.pass.get_mangleName();
     
    99109
    100110                namespace {
    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 ) {
     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 ) {
    105123                                bool wasTopLevel = isTopLevel;
    106124                                if ( isTopLevel ) {
     
    109127                                        isTopLevel = false;
    110128                                } // if
    111                                 mangleName << "__";
     129                                mangleName << Encoding::manglePrefix;
    112130                                CodeGen::OperatorInfo opInfo;
    113131                                if ( operatorLookup( declaration->get_name(), opInfo ) ) {
    114                                         mangleName << opInfo.outputName;
     132                                        mangleName << opInfo.outputName.size() << opInfo.outputName;
    115133                                } else {
    116                                         mangleName << declaration->get_name();
    117                                 } // if
    118                                 mangleName << "__";
     134                                        mangleName << declaration->name.size() << declaration->name;
     135                                } // if
    119136                                maybeAccept( declaration->get_type(), *visitor );
    120137                                if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) {
     
    122139                                        // so they need a different name mangling
    123140                                        if ( declaration->get_linkage() == LinkageSpec::AutoGen ) {
    124                                                 mangleName << "autogen__";
     141                                                mangleName << Encoding::autogen;
    125142                                        } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
    126                                                 mangleName << "intrinsic__";
     143                                                mangleName << Encoding::intrinsic;
    127144                                        } else {
    128145                                                // if we add another kind of overridable function, this has to change
     
    133150                        }
    134151
    135                         void Mangler::postvisit( ObjectDecl * declaration ) {
     152                        void Mangler_old::postvisit( const ObjectDecl * declaration ) {
    136153                                mangleDecl( declaration );
    137154                        }
    138155
    139                         void Mangler::postvisit( FunctionDecl * declaration ) {
     156                        void Mangler_old::postvisit( const FunctionDecl * declaration ) {
    140157                                mangleDecl( declaration );
    141158                        }
    142159
    143                         void Mangler::postvisit( VoidType * voidType ) {
     160                        void Mangler_old::postvisit( const VoidType * voidType ) {
    144161                                printQualifiers( voidType );
    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 
     162                                mangleName << Encoding::void_t;
     163                        }
     164
     165                        void Mangler_old::postvisit( const BasicType * basicType ) {
    181166                                printQualifiers( basicType );
    182                                 assert( basicType->get_kind() < sizeof(btLetter)/sizeof(btLetter[0]) );
    183                                 mangleName << btLetter[ basicType->get_kind() ];
    184                         }
    185 
    186                         void Mangler::postvisit( PointerType * pointerType ) {
     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 ) {
    187172                                printQualifiers( pointerType );
    188173                                // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
    189                                 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << "P";
     174                                if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << Encoding::pointer;
    190175                                maybeAccept( pointerType->base, *visitor );
    191176                        }
    192177
    193                         void Mangler::postvisit( ArrayType * arrayType ) {
     178                        void Mangler_old::postvisit( const ArrayType * arrayType ) {
    194179                                // TODO: encode dimension
    195180                                printQualifiers( arrayType );
    196                                 mangleName << "A0";
     181                                mangleName << Encoding::array << "0";
    197182                                maybeAccept( arrayType->base, *visitor );
    198183                        }
    199184
    200                         void Mangler::postvisit( ReferenceType * refType ) {
     185                        void Mangler_old::postvisit( const ReferenceType * refType ) {
    201186                                // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
    202187                                // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
     
    217202                        }
    218203
    219                         void Mangler::postvisit( FunctionType * functionType ) {
     204                        void Mangler_old::postvisit( const FunctionType * functionType ) {
    220205                                printQualifiers( functionType );
    221                                 mangleName << "F";
     206                                mangleName << Encoding::function;
    222207                                // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
    223208                                // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
     
    226211                                inFunctionType = true;
    227212                                std::list< Type* > returnTypes = getTypes( functionType->returnVals );
    228                                 acceptAll( returnTypes, *visitor );
     213                                if (returnTypes.empty()) mangleName << Encoding::void_t;
     214                                else acceptAll( returnTypes, *visitor );
    229215                                mangleName << "_";
    230216                                std::list< Type* > paramTypes = getTypes( functionType->parameters );
     
    233219                        }
    234220
    235                         void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
     221                        void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
    236222                                printQualifiers( refType );
    237223
    238                                 mangleName << ( refType->name.length() + prefix.length() ) << prefix << refType->name;
     224                                mangleName << prefix << refType->name.length() << refType->name;
    239225
    240226                                if ( mangleGenericParams ) {
    241                                         std::list< Expression* >& params = refType->parameters;
     227                                        const std::list< Expression* > & params = refType->parameters;
    242228                                        if ( ! params.empty() ) {
    243229                                                mangleName << "_";
    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));
     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));
    247233                                                        maybeAccept( paramType->type, *visitor );
    248234                                                }
     
    252238                        }
    253239
    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 ) {
     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 ) {
    267253                                VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
    268254                                if ( varNum == varNums.end() ) {
    269                                         mangleRef( typeInst, "t" );
     255                                        mangleRef( typeInst, Encoding::type );
    270256                                } else {
    271257                                        printQualifiers( typeInst );
    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();
    288                                 } // if
    289                         }
    290 
    291                         void Mangler::postvisit( TraitInstType * inst ) {
     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;
     265                                } // if
     266                        }
     267
     268                        void Mangler_old::postvisit( const TraitInstType * inst ) {
    292269                                printQualifiers( inst );
    293                                 mangleName << "_Y" << inst->name << "_";
    294                         }
    295 
    296                         void Mangler::postvisit( TupleType * tupleType ) {
     270                                mangleName << inst->name.size() << inst->name;
     271                        }
     272
     273                        void Mangler_old::postvisit( const TupleType * tupleType ) {
    297274                                printQualifiers( tupleType );
    298                                 mangleName << "T";
     275                                mangleName << Encoding::tuple << tupleType->types.size();
    299276                                acceptAll( tupleType->types, *visitor );
    300                                 mangleName << "_";
    301                         }
    302 
    303                         void Mangler::postvisit( VarArgsType * varArgsType ) {
     277                        }
     278
     279                        void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
    304280                                printQualifiers( varArgsType );
    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;
     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;
    319318                        }
    320319
     
    325324                        }
    326325
    327                         void Mangler::printQualifiers( Type * type ) {
     326                        void Mangler_old::printQualifiers( const Type * type ) {
    328327                                // skip if not including qualifiers
    329328                                if ( typeMode ) return;
    330                                 if ( ! type->get_forall().empty() ) {
     329                                if ( ! type->forall.empty() ) {
    331330                                        std::list< std::string > assertionNames;
    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() ) {
     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 ) {
    336335                                                  case TypeDecl::Dtype:
    337336                                                        dcount++;
     
    346345                                                        assert( false );
    347346                                                } // switch
    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() );
     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++;
    356354                                                } // for
    357355                                        } // for
    358                                         mangleName << tcount << "_" << dcount << "_" << fcount << "_" << vcount << "_";
     356                                        mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
    359357                                        std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
    360358                                        mangleName << "_";
     
    363361                                        // these qualifiers do not distinguish the outermost type of a function parameter
    364362                                        if ( type->get_const() ) {
    365                                                 mangleName << "C";
     363                                                mangleName << Encoding::qualifiers.at(Type::Const);
    366364                                        } // if
    367365                                        if ( type->get_volatile() ) {
    368                                                 mangleName << "V";
     366                                                mangleName << Encoding::qualifiers.at(Type::Volatile);
    369367                                        } // if
    370368                                        // Removed due to restrict not affecting function compatibility in GCC
     
    373371                                        // } // if
    374372                                        if ( type->get_atomic() ) {
    375                                                 mangleName << "A";
     373                                                mangleName << Encoding::qualifiers.at(Type::Atomic);
    376374                                        } // if
    377375                                }
    378376                                if ( type->get_mutex() ) {
    379                                         mangleName << "M";
    380                                 } // 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 
     377                                        mangleName << Encoding::qualifiers.at(Type::Mutex);
     378                                } // if
    386379                                if ( inFunctionType ) {
    387380                                        // turn off inFunctionType so that types can be differentiated for nested qualifiers
     
    394387} // namespace SymTab
    395388
     389namespace 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
     729
    396730// Local Variables: //
    397731// tab-width: 4 //
  • src/SymTab/Mangler.h

    r7951100 rb067d9b  
    2121#include <utility>            // for pair
    2222
     23#include "AST/Bitfield.hpp"
     24#include "AST/Fwd.hpp"
    2325#include "SynTree/SynTree.h"  // for Types
    2426#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
     35namespace ResolvExpr {
     36        class TypeEnvironment;
     37}
    2538
    2639namespace SymTab {
    2740        namespace Mangler {
    2841                /// Mangle syntax tree object; primary interface to clients
    29                 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
     42                std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
    3043
    3144                /// Mangle a type name; secondary interface
    32                 std::string mangleType( Type* ty );
     45                std::string mangleType( const Type * ty );
    3346                /// Mangle ignoring generic type parameters
    34                 std::string mangleConcrete( Type* ty );
     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                };
    3576        } // Mangler
    3677} // SymTab
     78
     79namespace 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
     113extern "C" {
     114        char * cforall_demangle(const char *, int);
     115}
    37116
    38117// Local Variables: //
  • src/SymTab/Validate.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug 28 13:47:23 2017
    13 // Update Count     : 359
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Aug  7 6:42:00 2019
     13// Update Count     : 360
    1414//
    1515
     
    4444#include <list>                        // for list
    4545#include <string>                      // for string
     46#include <unordered_map>               // for unordered_map
    4647#include <utility>                     // for pair
    4748
     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"
    4856#include "CodeGen/CodeGenerator.h"     // for genName
    4957#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5058#include "ControlStruct/Mutate.h"      // for ForExprMutator
     59#include "Common/CodeLocation.h"       // for CodeLocation
     60#include "Common/Stats.h"              // for Stats::Heap
    5161#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
    5262#include "Common/ScopedMap.h"          // for ScopedMap
     
    6171#include "Parser/LinkageSpec.h"        // for C
    6272#include "ResolvExpr/typeops.h"        // for typesCompatible
     73#include "ResolvExpr/Resolver.h"       // for findSingleExpression
     74#include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
    6375#include "SymTab/Autogen.h"            // for SizeType
    6476#include "SynTree/Attribute.h"         // for noAttributes, Attribute
     
    7284#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    7385#include "SynTree/Visitor.h"           // for Visitor
     86#include "Validate/HandleAttributes.h" // for handleAttributes
     87#include "Validate/FindSpecialDecls.h" // for FindSpecialDecls
    7488
    7589class CompoundStmt;
     
    7791class SwitchStmt;
    7892
    79 #define debugPrint( x ) if ( doDebug ) { std::cout << x; }
     93#define debugPrint( x ) if ( doDebug ) x
    8094
    8195namespace 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
    82109        struct HoistStruct final : public WithDeclsToAdd, public WithGuards {
    83110                /// Flattens nested struct types
    84111                static void hoistStruct( std::list< Declaration * > &translationUnit );
    85112
    86                 void previsit( EnumInstType * enumInstType );
    87                 void previsit( StructInstType * structInstType );
    88                 void previsit( UnionInstType * unionInstType );
    89113                void previsit( StructDecl * aggregateDecl );
    90114                void previsit( UnionDecl * aggregateDecl );
    91115                void previsit( StaticAssertDecl * assertDecl );
     116                void previsit( StructInstType * type );
     117                void previsit( UnionInstType * type );
     118                void previsit( EnumInstType * type );
    92119
    93120          private:
    94                 template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
     121                template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl );
    95122
    96123                AggregateDecl * parentAggr = nullptr;
     
    106133
    107134        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
    108         struct EnumAndPointerDecay {
    109                 void previsit( EnumDecl *aggregateDecl );
    110                 void previsit( FunctionType *func );
     135        struct EnumAndPointerDecay_old {
     136                void previsit( EnumDecl * aggregateDecl );
     137                void previsit( FunctionType * func );
    111138        };
    112139
    113140        /// Associates forward declarations of aggregates with their definitions
    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 );
     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 );
    126155                void postvisit( TraitDecl * traitDecl );
    127156
    128                 void previsit( StructDecl *structDecl );
    129                 void previsit( UnionDecl *unionDecl );
     157                void previsit( StructDecl * structDecl );
     158                void previsit( UnionDecl * unionDecl );
    130159
    131160                void renameGenericParams( std::list< TypeDecl * > & params );
    132161
    133162          private:
    134                 const Indexer *local_indexer;
     163                const Indexer * local_indexer;
    135164
    136165                typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType;
     
    145174
    146175        /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
    147         struct ForallPointerDecay final {
     176        struct ForallPointerDecay_old final {
    148177                void previsit( ObjectDecl * object );
    149178                void previsit( FunctionDecl * func );
     
    165194        };
    166195
    167         struct EliminateTypedef final : public WithVisitorRef<EliminateTypedef>, public WithGuards {
    168                 EliminateTypedef() : scopeLevel( 0 ) {}
     196        struct ReplaceTypedef final : public WithVisitorRef<ReplaceTypedef>, public WithGuards, public WithShortCircuiting, public WithDeclsToAdd {
     197                ReplaceTypedef() : scopeLevel( 0 ) {}
    169198                /// Replaces typedefs by forward declarations
    170                 static void eliminateTypedef( std::list< Declaration * > &translationUnit );
    171 
     199                static void replaceTypedef( std::list< Declaration * > &translationUnit );
     200
     201                void premutate( QualifiedType * );
     202                Type * postmutate( QualifiedType * qualType );
    172203                Type * postmutate( TypeInstType * aggregateUseType );
    173204                Declaration * postmutate( TypedefDecl * typeDecl );
     
    180211
    181212                void premutate( CompoundStmt * compoundStmt );
    182                 CompoundStmt * postmutate( CompoundStmt * compoundStmt );
    183213
    184214                void premutate( StructDecl * structDecl );
    185                 Declaration * postmutate( StructDecl * structDecl );
    186215                void premutate( UnionDecl * unionDecl );
    187                 Declaration * postmutate( UnionDecl * unionDecl );
    188216                void premutate( EnumDecl * enumDecl );
    189                 Declaration * postmutate( EnumDecl * enumDecl );
    190                 Declaration * postmutate( TraitDecl * contextDecl );
     217                void premutate( TraitDecl * );
    191218
    192219                void premutate( FunctionType * ftype );
     
    194221          private:
    195222                template<typename AggDecl>
    196                 AggDecl *handleAggregate( AggDecl * aggDecl );
    197 
    198                 template<typename AggDecl>
    199223                void addImplicitTypedef( AggDecl * aggDecl );
     224                template< typename AggDecl >
     225                void handleAggregate( AggDecl * aggr );
    200226
    201227                typedef std::unique_ptr<TypedefDecl> TypedefDeclPtr;
    202228                typedef ScopedMap< std::string, std::pair< TypedefDeclPtr, int > > TypedefMap;
    203                 typedef std::map< std::string, TypeDecl * > TypeDeclMap;
     229                typedef ScopedMap< std::string, TypeDecl * > TypeDeclMap;
    204230                TypedefMap typedefNames;
    205231                TypeDeclMap typedeclNames;
    206232                int scopeLevel;
    207233                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 );
    208246        };
    209247
     
    214252                static void verify( std::list< Declaration * > &translationUnit );
    215253
    216                 void previsit( FunctionDecl *funcDecl );
     254                void previsit( FunctionDecl * funcDecl );
    217255        };
    218256
     
    223261        };
    224262
    225         struct ArrayLength {
     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 {
    226273                /// for array types without an explicit length, compute the length and store it so that it
    227274                /// is known to the rest of the phases. For example,
     
    234281
    235282                void previsit( ObjectDecl * objDecl );
     283                void previsit( ArrayType * arrayType );
    236284        };
    237285
     
    239287                Type::StorageClasses storageClasses;
    240288
    241                 void premutate( ObjectDecl *objectDecl );
    242                 Expression * postmutate( CompoundLiteralExpr *compLitExpr );
     289                void premutate( ObjectDecl * objectDecl );
     290                Expression * postmutate( CompoundLiteralExpr * compLitExpr );
    243291        };
    244292
     
    250298        };
    251299
    252         FunctionDecl * dereferenceOperator = nullptr;
    253         struct FindSpecialDeclarations final {
    254                 void previsit( FunctionDecl * funcDecl );
    255         };
    256 
    257300        void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
    258                 PassVisitor<EnumAndPointerDecay> epc;
    259                 PassVisitor<LinkReferenceToTypes> lrt( nullptr );
    260                 PassVisitor<ForallPointerDecay> fpd;
     301                PassVisitor<EnumAndPointerDecay_old> epc;
     302                PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
     303                PassVisitor<ForallPointerDecay_old> fpd;
    261304                PassVisitor<CompoundLiteral> compoundliteral;
    262305                PassVisitor<ValidateGenericParameters> genericParams;
    263                 PassVisitor<FindSpecialDeclarations> finder;
    264306                PassVisitor<LabelAddressFixer> labelAddrFixer;
    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;
     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;
    291399                type->accept( epc );
    292400                type->accept( lrt );
     
    294402        }
    295403
     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
    296493        void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
    297494                PassVisitor<HoistStruct> hoister;
     
    299496        }
    300497
    301         bool shouldHoist( Declaration *decl ) {
     498        bool shouldHoist( Declaration * decl ) {
    302499                return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl );
    303500        }
    304501
     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
    305516        template< typename AggDecl >
    306         void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
     517        void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) {
    307518                if ( parentAggr ) {
     519                        aggregateDecl->parent = parentAggr;
     520                        aggregateDecl->name = qualifiedName( aggregateDecl );
    308521                        // Add elements in stack order corresponding to nesting structure.
    309522                        declsToAddBefore.push_front( aggregateDecl );
     
    316529        }
    317530
    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 
    336531        void HoistStruct::previsit( StaticAssertDecl * assertDecl ) {
    337532                if ( parentAggr ) {
     
    348543        }
    349544
    350         void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) {
     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 ) {
    351598                // Set the type of each member of the enumeration to be EnumConstant
    352                 for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
    353                         ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
     599                for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) {
     600                        ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i );
    354601                        assert( obj );
    355                         obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->get_name() ) );
     602                        obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) );
    356603                } // for
    357604        }
     
    380627        }
    381628
    382         void EnumAndPointerDecay::previsit( FunctionType *func ) {
     629        void EnumAndPointerDecay_old::previsit( FunctionType * func ) {
    383630                // Fix up parameters and return types
    384631                fixFunctionList( func->parameters, func->isVarArgs, func );
     
    386633        }
    387634
    388         LinkReferenceToTypes::LinkReferenceToTypes( const Indexer *other_indexer ) {
     635        LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) {
    389636                if ( other_indexer ) {
    390637                        local_indexer = other_indexer;
     
    394641        }
    395642
    396         void LinkReferenceToTypes::postvisit( EnumInstType *enumInst ) {
    397                 EnumDecl *st = local_indexer->lookupEnum( enumInst->get_name() );
     643        void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) {
     644                const EnumDecl * st = local_indexer->lookupEnum( enumInst->name );
    398645                // it's not a semantic error if the enum is not found, just an implicit forward declaration
    399646                if ( st ) {
    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() ) {
     647                        enumInst->baseEnum = const_cast<EnumDecl *>(st); // Just linking in the node
     648                } // if
     649                if ( ! st || ! st->body ) {
    404650                        // use of forward declaration
    405                         forwardEnums[ enumInst->get_name() ].push_back( enumInst );
     651                        forwardEnums[ enumInst->name ].push_back( enumInst );
    406652                } // if
    407653        }
     
    415661        }
    416662
    417         void LinkReferenceToTypes::postvisit( StructInstType *structInst ) {
    418                 StructDecl *st = local_indexer->lookupStruct( structInst->get_name() );
     663        void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {
     664                const StructDecl * st = local_indexer->lookupStruct( structInst->name );
    419665                // it's not a semantic error if the struct is not found, just an implicit forward declaration
    420666                if ( st ) {
    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() ) {
     667                        structInst->baseStruct = const_cast<StructDecl *>(st); // Just linking in the node
     668                } // if
     669                if ( ! st || ! st->body ) {
    425670                        // use of forward declaration
    426                         forwardStructs[ structInst->get_name() ].push_back( structInst );
     671                        forwardStructs[ structInst->name ].push_back( structInst );
    427672                } // if
    428673                checkGenericParameters( structInst );
    429674        }
    430675
    431         void LinkReferenceToTypes::postvisit( UnionInstType *unionInst ) {
    432                 UnionDecl *un = local_indexer->lookupUnion( unionInst->get_name() );
     676        void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) {
     677                const UnionDecl * un = local_indexer->lookupUnion( unionInst->name );
    433678                // it's not a semantic error if the union is not found, just an implicit forward declaration
    434679                if ( un ) {
    435                         unionInst->set_baseUnion( un );
    436                 } // if
    437                 if ( ! un || un->get_members().empty() ) {
     680                        unionInst->baseUnion = const_cast<UnionDecl *>(un); // Just linking in the node
     681                } // if
     682                if ( ! un || ! un->body ) {
    438683                        // use of forward declaration
    439                         forwardUnions[ unionInst->get_name() ].push_back( unionInst );
     684                        forwardUnions[ unionInst->name ].push_back( unionInst );
    440685                } // if
    441686                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 );
    442696        }
    443697
     
    450704                        DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
    451705                        if ( dwt1 && dwt2 ) {
    452                                 if ( dwt1->get_name() == dwt2->get_name() && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
     706                                if ( dwt1->name == dwt2->name && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
    453707                                        // std::cerr << "=========== equal:" << std::endl;
    454708                                        // std::cerr << "d1: " << d1 << std::endl;
     
    475729        template< typename Iterator >
    476730        void expandAssertions( TraitInstType * inst, Iterator out ) {
    477                 assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toString( inst ).c_str() );
     731                assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) );
    478732                std::list< DeclarationWithType * > asserts;
    479733                for ( Declaration * decl : inst->baseTrait->members ) {
     
    484738        }
    485739
    486         void LinkReferenceToTypes::postvisit( TraitDecl * traitDecl ) {
     740        void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) {
    487741                if ( traitDecl->name == "sized" ) {
    488742                        // "sized" is a special trait - flick the sized status on for the type variable
     
    506760        }
    507761
    508         void LinkReferenceToTypes::postvisit( TraitInstType * traitInst ) {
     762        void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) {
    509763                // handle other traits
    510                 TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
     764                const TraitDecl * traitDecl = local_indexer->lookupTrait( traitInst->name );
    511765                if ( ! traitDecl ) {
    512766                        SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
    513767                } // if
    514                 if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
     768                if ( traitDecl->parameters.size() != traitInst->parameters.size() ) {
    515769                        SemanticError( traitInst, "incorrect number of trait parameters: " );
    516770                } // if
    517                 traitInst->baseTrait = traitDecl;
     771                traitInst->baseTrait = const_cast<TraitDecl *>(traitDecl); // Just linking in the node
    518772
    519773                // need to carry over the 'sized' status of each decl in the instance
    520                 for ( auto p : group_iterate( traitDecl->get_parameters(), traitInst->get_parameters() ) ) {
     774                for ( auto p : group_iterate( traitDecl->parameters, traitInst->parameters ) ) {
    521775                        TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
    522776                        if ( ! expr ) {
     
    525779                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
    526780                                TypeDecl * formalDecl = std::get<0>(p);
    527                                 TypeDecl * instDecl = inst->get_baseType();
     781                                TypeDecl * instDecl = inst->baseType;
    528782                                if ( formalDecl->get_sized() ) instDecl->set_sized( true );
    529783                        }
     
    532786        }
    533787
    534         void LinkReferenceToTypes::postvisit( EnumDecl *enumDecl ) {
     788        void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) {
    535789                // visit enum members first so that the types of self-referencing members are updated properly
    536                 if ( ! enumDecl->get_members().empty() ) {
    537                         ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->get_name() );
     790                if ( enumDecl->body ) {
     791                        ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->name );
    538792                        if ( fwds != forwardEnums.end() ) {
    539793                                for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    540                                         (*inst )->set_baseEnum( enumDecl );
     794                                        (* inst)->baseEnum = enumDecl;
    541795                                } // for
    542796                                forwardEnums.erase( fwds );
    543797                        } // if
    544                 } // if
    545         }
    546 
    547         void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) {
     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 ) {
    548811                // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
    549812                //   forall(otype T)
     
    563826        }
    564827
    565         void LinkReferenceToTypes::previsit( StructDecl * structDecl ) {
     828        void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) {
    566829                renameGenericParams( structDecl->parameters );
    567830        }
    568831
    569         void LinkReferenceToTypes::previsit( UnionDecl * unionDecl ) {
     832        void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) {
    570833                renameGenericParams( unionDecl->parameters );
    571834        }
    572835
    573         void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) {
     836        void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) {
    574837                // visit struct members first so that the types of self-referencing members are updated properly
    575838                // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults)
    576                 if ( ! structDecl->get_members().empty() ) {
    577                         ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
     839                if ( structDecl->body ) {
     840                        ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->name );
    578841                        if ( fwds != forwardStructs.end() ) {
    579842                                for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    580                                         (*inst )->set_baseStruct( structDecl );
     843                                        (* inst)->baseStruct = structDecl;
    581844                                } // for
    582845                                forwardStructs.erase( fwds );
     
    585848        }
    586849
    587         void LinkReferenceToTypes::postvisit( UnionDecl *unionDecl ) {
    588                 if ( ! unionDecl->get_members().empty() ) {
    589                         ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
     850        void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) {
     851                if ( unionDecl->body ) {
     852                        ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name );
    590853                        if ( fwds != forwardUnions.end() ) {
    591854                                for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    592                                         (*inst )->set_baseUnion( unionDecl );
     855                                        (* inst)->baseUnion = unionDecl;
    593856                                } // for
    594857                                forwardUnions.erase( fwds );
     
    597860        }
    598861
    599         void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) {
     862        void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) {
    600863                // ensure generic parameter instances are renamed like the base type
    601864                if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
    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 );
     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 );
    605868                        } // if
    606869                } // if
     
    614877                        // expand trait instances into their members
    615878                        for ( DeclarationWithType * assertion : asserts ) {
    616                                 if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     879                                if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
    617880                                        // expand trait instance into all of its members
    618881                                        expandAssertions( traitInst, back_inserter( type->assertions ) );
     
    634897        }
    635898
    636         void ForallPointerDecay::previsit( ObjectDecl *object ) {
     899        void ForallPointerDecay_old::previsit( ObjectDecl * object ) {
    637900                // ensure that operator names only apply to functions or function pointers
    638901                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     
    642905        }
    643906
    644         void ForallPointerDecay::previsit( FunctionDecl *func ) {
     907        void ForallPointerDecay_old::previsit( FunctionDecl * func ) {
    645908                func->fixUniqueId();
    646909        }
    647910
    648         void ForallPointerDecay::previsit( FunctionType * ftype ) {
     911        void ForallPointerDecay_old::previsit( FunctionType * ftype ) {
    649912                forallFixer( ftype->forall, ftype );
    650913        }
    651914
    652         void ForallPointerDecay::previsit( StructDecl * aggrDecl ) {
     915        void ForallPointerDecay_old::previsit( StructDecl * aggrDecl ) {
    653916                forallFixer( aggrDecl->parameters, aggrDecl );
    654917        }
    655918
    656         void ForallPointerDecay::previsit( UnionDecl * aggrDecl ) {
     919        void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
    657920                forallFixer( aggrDecl->parameters, aggrDecl );
    658921        }
     
    679942
    680943
    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;
     944        void ReplaceTypedef::replaceTypedef( std::list< Declaration * > &translationUnit ) {
     945                PassVisitor<ReplaceTypedef> eliminator;
    687946                mutateAll( translationUnit, eliminator );
    688947                if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
    689948                        // grab and remember declaration of size_t
    690                         SizeType = eliminator.pass.typedefNames["size_t"].first->get_base()->clone();
     949                        Validate::SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone();
    691950                } else {
    692951                        // xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
    693952                        // eventually should have a warning for this case.
    694                         SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    695                 }
    696                 filter( translationUnit, isTypedef, true );
    697         }
    698 
    699         Type * EliminateTypedef::postmutate( TypeInstType * typeInst ) {
     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 ) {
    700968                // instances of typedef types will come here. If it is an instance
    701969                // of a typdef type, link the instance to its actual type.
    702                 TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
     970                TypedefMap::const_iterator def = typedefNames.find( typeInst->name );
    703971                if ( def != typedefNames.end() ) {
    704                         Type *ret = def->second.first->base->clone();
     972                        Type * ret = def->second.first->base->clone();
     973                        ret->location = typeInst->location;
    705974                        ret->get_qualifiers() |= typeInst->get_qualifiers();
    706975                        // attributes are not carried over from typedef to function parameters/return values
     
    713982                        // place instance parameters on the typedef'd type
    714983                        if ( ! typeInst->parameters.empty() ) {
    715                                 ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret);
     984                                ReferenceToType * rtt = dynamic_cast<ReferenceToType *>(ret);
    716985                                if ( ! rtt ) {
    717986                                        SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
    718987                                }
    719                                 rtt->get_parameters().clear();
     988                                rtt->parameters.clear();
    720989                                cloneAll( typeInst->parameters, rtt->parameters );
    721                                 mutateAll( rtt->parameters, *visitor );  // recursively fix typedefs on parameters
     990                                mutateAll( rtt->parameters, * visitor );  // recursively fix typedefs on parameters
    722991                        } // if
    723992                        delete typeInst;
    724993                        return ret;
    725994                } else {
    726                         TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->get_name() );
    727                         assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst->name.c_str() );
     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                        }
    728999                        typeInst->set_baseType( base->second );
    729                 } // if
    730                 return typeInst;
     1000                        return typeInst;
     1001                } // if
     1002                assert( false );
    7311003        }
    7321004
     
    7451017        }
    7461018
    747         Declaration *EliminateTypedef::postmutate( TypedefDecl * tyDecl ) {
    748                 if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
     1019        Declaration * ReplaceTypedef::postmutate( TypedefDecl * tyDecl ) {
     1020                if ( typedefNames.count( tyDecl->name ) == 1 && typedefNames[ tyDecl->name ].second == scopeLevel ) {
    7491021                        // typedef to the same name from the same scope
    7501022                        // must be from the same type
    7511023
    752                         Type * t1 = tyDecl->get_base();
    753                         Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
     1024                        Type * t1 = tyDecl->base;
     1025                        Type * t2 = typedefNames[ tyDecl->name ].first->base;
    7541026                        if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
    7551027                                SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
     
    7631035                        }
    7641036                } else {
    765                         typedefNames[ tyDecl->get_name() ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
     1037                        typedefNames[ tyDecl->name ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
    7661038                } // if
    7671039
     
    7711043                //    struct screen;
    7721044                // because the expansion of the typedef is:
    773                 //    void rtn( SCREEN *p ) => void rtn( struct screen *p )
     1045                //    void rtn( SCREEN * p ) => void rtn( struct screen * p )
    7741046                // hence the type-name "screen" must be defined.
    7751047                // Note, qualifiers on the typedef are superfluous for the forward declaration.
    7761048
    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() );
     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 );
    7911062                if ( i != typedefNames.end() ) {
    7921063                        typedefNames.erase( i ) ;
    7931064                } // if
    7941065
    795                 typedeclNames[ typeDecl->get_name() ] = typeDecl;
    796         }
    797 
    798         void EliminateTypedef::premutate( FunctionDecl * ) {
     1066                typedeclNames.insert( typeDecl->name, typeDecl );
     1067        }
     1068
     1069        void ReplaceTypedef::premutate( FunctionDecl * ) {
    7991070                GuardScope( typedefNames );
    800         }
    801 
    802         void EliminateTypedef::premutate( ObjectDecl * ) {
     1071                GuardScope( typedeclNames );
     1072        }
     1073
     1074        void ReplaceTypedef::premutate( ObjectDecl * ) {
    8031075                GuardScope( typedefNames );
    804         }
    805 
    806         DeclarationWithType *EliminateTypedef::postmutate( ObjectDecl * objDecl ) {
    807                 if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->get_type() ) ) { // function type?
     1076                GuardScope( typedeclNames );
     1077        }
     1078
     1079        DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) {
     1080                if ( FunctionType * funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type?
    8081081                        // replace the current object declaration with a function declaration
    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();
     1082                        FunctionDecl * newDecl = new FunctionDecl( objDecl->name, objDecl->get_storageClasses(), objDecl->linkage, funtype, 0, objDecl->attributes, objDecl->get_funcSpec() );
     1083                        objDecl->attributes.clear();
    8111084                        objDecl->set_type( nullptr );
    8121085                        delete objDecl;
     
    8161089        }
    8171090
    818         void EliminateTypedef::premutate( CastExpr * ) {
     1091        void ReplaceTypedef::premutate( CastExpr * ) {
    8191092                GuardScope( typedefNames );
    820         }
    821 
    822         void EliminateTypedef::premutate( CompoundStmt * ) {
     1093                GuardScope( typedeclNames );
     1094        }
     1095
     1096        void ReplaceTypedef::premutate( CompoundStmt * ) {
    8231097                GuardScope( typedefNames );
     1098                GuardScope( typedeclNames );
    8241099                scopeLevel += 1;
    8251100                GuardAction( [this](){ scopeLevel -= 1; } );
    8261101        }
    8271102
    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
    8431103        template<typename 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 ) {
     1104        void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
    8511105                if ( typedefNames.count( aggDecl->get_name() ) == 0 ) {
    852                         Type *type = nullptr;
     1106                        Type * type = nullptr;
    8531107                        if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) {
    8541108                                type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() );
     
    8601114                        TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) );
    8611115                        typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel );
    862                 } // if
    863         }
    864 
    865         void EliminateTypedef::premutate( StructDecl * structDecl ) {
     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;
    8661153                addImplicitTypedef( structDecl );
    867         }
    868 
    869 
    870         Declaration *EliminateTypedef::postmutate( StructDecl * structDecl ) {
    871                 return handleAggregate( structDecl );
    872         }
    873 
    874         void EliminateTypedef::premutate( UnionDecl * unionDecl ) {
     1154                handleAggregate( structDecl );
     1155        }
     1156
     1157        void ReplaceTypedef::premutate( UnionDecl * unionDecl ) {
     1158                visit_children = false;
    8751159                addImplicitTypedef( unionDecl );
    876         }
    877 
    878         Declaration *EliminateTypedef::postmutate( UnionDecl * unionDecl ) {
    879                 return handleAggregate( unionDecl );
    880         }
    881 
    882         void EliminateTypedef::premutate( EnumDecl * enumDecl ) {
     1160                handleAggregate( unionDecl );
     1161        }
     1162
     1163        void ReplaceTypedef::premutate( EnumDecl * enumDecl ) {
    8831164                addImplicitTypedef( enumDecl );
    8841165        }
    8851166
    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 * ) {
     1167        void ReplaceTypedef::premutate( FunctionType * ) {
    8951168                GuardValue( inFunctionType );
    8961169                inFunctionType = true;
     1170        }
     1171
     1172        void ReplaceTypedef::premutate( TraitDecl * ) {
     1173                GuardScope( typedefNames );
     1174                GuardScope( typedeclNames);
    8971175        }
    8981176
     
    9391217                        for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) {
    9401218                                if ( i < args.size() ) {
    941                                         TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( *std::next( args.begin(), i ) );
    942                                         sub.add( (*paramIter)->get_name(), expr->get_type()->clone() );
     1219                                        TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) );
     1220                                        sub.add( (* paramIter)->get_name(), expr->get_type()->clone() );
    9431221                                } else if ( i == args.size() ) {
    944                                         Type * defaultType = (*paramIter)->get_init();
     1222                                        Type * defaultType = (* paramIter)->get_init();
    9451223                                        if ( defaultType ) {
    9461224                                                args.push_back( new TypeExpr( defaultType->clone() ) );
    947                                                 sub.add( (*paramIter)->get_name(), defaultType->clone() );
     1225                                                sub.add( (* paramIter)->get_name(), defaultType->clone() );
    9481226                                        }
    9491227                                }
     
    9641242        }
    9651243
    966         void CompoundLiteral::premutate( ObjectDecl *objectDecl ) {
     1244        void CompoundLiteral::premutate( ObjectDecl * objectDecl ) {
    9671245                storageClasses = objectDecl->get_storageClasses();
    9681246        }
    9691247
    970         Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {
     1248        Expression * CompoundLiteral::postmutate( CompoundLiteralExpr * compLitExpr ) {
    9711249                // transform [storage_class] ... (struct S){ 3, ... };
    9721250                // into [storage_class] struct S temp =  { 3, ... };
    9731251                static UniqueName indexName( "_compLit" );
    9741252
    975                 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
     1253                ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
    9761254                compLitExpr->set_result( nullptr );
    9771255                compLitExpr->set_initializer( nullptr );
     
    10111289                        TupleType * tupleType = strict_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
    10121290                        // ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false.
    1013                         ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
     1291                        ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) );
    10141292                        deleteAll( retVals );
    10151293                        retVals.clear();
     
    10181296        }
    10191297
     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
    10201320        void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
    10211321                PassVisitor<ArrayLength> len;
     
    10241324
    10251325        void ArrayLength::previsit( ObjectDecl * objDecl ) {
    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                         }
     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 );
    10311343                }
    10321344        }
     
    10621374        }
    10631375
    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;
     1376namespace {
     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: " );
    10701519                                }
    10711520                        }
    10721521                }
    1073         }
     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
     1830const 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
    10741839} // namespace SymTab
    10751840
  • src/SymTab/Validate.h

    r7951100 rb067d9b  
    1919#include <list>  // for list
    2020
    21 class Declaration;
    22 class Type;
     21struct CodeLocation;
     22class  Declaration;
     23class  Type;
     24
     25namespace ast {
     26        class Type;
     27        class SymbolTable;
     28}
    2329
    2430namespace SymTab {
     
    2834        void validate( std::list< Declaration * > &translationUnit, bool doDebug = false );
    2935        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 );
    3039} // namespace SymTab
    3140
  • src/SymTab/module.mk

    r7951100 rb067d9b  
    1515###############################################################################
    1616
    17 SRC += SymTab/Indexer.cc \
    18        SymTab/Mangler.cc \
    19        SymTab/Validate.cc \
    20        SymTab/FixFunction.cc \
    21        SymTab/Autogen.cc
     17SRC_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
     25SRC += $(SRC_SYMTAB)
     26SRCDEMANGLE += $(SRC_SYMTAB) SymTab/Demangle.cc
  • src/SynTree/AddressExpr.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 23:54:44 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Apr 26 12:35:13 2016
    13 // Update Count     : 6
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Feb 28 13:13:38 2019
     13// Update Count     : 10
    1414//
    1515
     
    4242AddressExpr::AddressExpr( Expression *arg ) : Expression(), arg( arg ) {
    4343        if ( arg->result ) {
    44                 if ( arg->result->get_lvalue() ) {
     44                if ( arg->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                         ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( arg->result );
    50                         set_result( addrType( refType->base ) );
     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
    5154                }
    52                 // result of & is never an lvalue
    53                 get_result()->set_lvalue( false );
    5455        }
    5556}
  • src/SynTree/AggregateDecl.cc

    r7951100 rb067d9b  
    8686std::string TraitDecl::typeString() const { return "trait"; }
    8787
    88 namespace {
    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 
    10388bool EnumDecl::valueOf( Declaration * enumerator, long long int & value ) {
    10489        if ( enumValues.empty() ) {
     
    10893                        if ( field->init ) {
    10994                                SingleInit * init = strict_dynamic_cast< SingleInit * >( field->init );
    110                                 currentValue = getConstValue( init->value );
     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;
    11198                        }
    11299                        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

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Apr 26 12:41:06 2016
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Aug 12 14:28:00 2019
     13// Update Count     : 5
    1414//
    1515
     
    2525#include "Declaration.h"         // for Declaration
    2626#include "Expression.h"          // for ParamEntry, ApplicationExpr, Expression
     27#include "InitTweak/InitTweak.h" // for getFunction
    2728#include "ResolvExpr/typeops.h"  // for extractResultType
    2829#include "Type.h"                // for Type, PointerType, FunctionType
    2930
     31ParamEntry::ParamEntry( UniqueId decl, Declaration * declptr, Type * actualType, Type * formalType, Expression* expr )
     32                : decl( decl ), declptr( declptr ), actualType( actualType ), formalType( formalType ), expr( expr ) {
     33        }
     34
    3035ParamEntry::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 }
    33 
    34 ParamEntry &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;
     36                decl( other.decl ), declptr( maybeClone( other.declptr ) ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) {
    4337}
    4438
    4539ParamEntry::~ParamEntry() {
     40        delete declptr;
    4641        delete actualType;
    4742        delete formalType;
     
    5045
    5146ParamEntry::ParamEntry( ParamEntry && other ) :
    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;
     47                decl( other.decl ), declptr( other.declptr ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr ) {
     48        new (&other) ParamEntry();
    5649}
    5750
    5851ParamEntry & ParamEntry::operator=( ParamEntry && other ) {
    5952        if ( &other == this ) return *this;
    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 );
     53        this->~ParamEntry();
     54        new (this) ParamEntry(other.decl, other.declptr, other.actualType, other.formalType, other.expr);
     55        new (&other) ParamEntry();
     56
    7157        return *this;
    7258}
     
    9177}
    9278
     79bool 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
    9388void ApplicationExpr::print( std::ostream &os, Indenter indent ) const {
    9489        os << "Application of" << std::endl << indent+1;
  • src/SynTree/ArrayType.cc

    r7951100 rb067d9b  
    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 );
    2928}
    3029
  • src/SynTree/Attribute.cc

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

    r7951100 rb067d9b  
    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 ); }
    5253        virtual Attribute * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    5354        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
  • src/SynTree/BaseSyntaxNode.h

    r7951100 rb067d9b  
    99// Author           : Thierry Delisle
    1010// Created On       : Tue Feb 14 07:44:20 2017
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Aug 17 13:44:00
    13 // Update Count     : 1
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jul 10 16:13:49 2019
     13// Update Count     : 4
    1414//
    1515
     
    1818#include "Common/CodeLocation.h"
    1919#include "Common/Indenter.h"
     20#include "Common/Stats.h"
     21
    2022class Visitor;
    2123class Mutator;
     
    2325class BaseSyntaxNode {
    2426  public:
     27        static Stats::Counters::SimpleCounter* new_nodes;
     28
    2529        CodeLocation location;
     30
     31        BaseSyntaxNode() { ++*new_nodes; }
     32        BaseSyntaxNode( const BaseSyntaxNode & o ) : location(o.location) { ++*new_nodes; }
     33        BaseSyntaxNode & operator=( const BaseSyntaxNode & ) = default;
    2634
    2735        virtual ~BaseSyntaxNode() {}
     
    2937        virtual BaseSyntaxNode * clone() const = 0;
    3038        virtual void accept( Visitor & v ) = 0;
     39        virtual void accept( Visitor & v ) const = 0;
    3140        virtual BaseSyntaxNode * acceptMutator( Mutator & m ) = 0;
    32   /// Notes:
    33   /// * each node is responsible for indenting its children.
    34   /// * Expressions should not finish with a newline, since the expression's parent has better information.
     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.
    3544        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   }
    3945};
    4046
  • src/SynTree/BasicType.cc

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 14:14:03 2017
    13 // Update Count     : 11
     12// Last Modified On : Sun Aug  4 21:07:44 2019
     13// Update Count     : 13
    1414//
    1515
     
    3030
    3131bool BasicType::isInteger() const {
    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;
     32        return kind <= UnsignedInt128;
    6533}
    6634
  • src/SynTree/CommaExpr.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Mon May 02 15:19:44 2016
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Arg 12 16:11:00 2016
     13// Update Count     : 2
    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.
    2825        set_result( maybeClone( arg2->get_result() ) );
    29         // get_type->set_isLvalue( false );
    3026}
    3127
     
    3733        delete arg1;
    3834        delete arg2;
     35}
     36
     37bool 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();
    3941}
    4042
  • src/SynTree/Constant.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 14 14:50:00 2017
    13 // Update Count     : 29
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Feb 13 18:11:22 2019
     13// Update Count     : 32
    1414//
    1515
     
    1919
    2020#include "Constant.h"
     21#include "Expression.h" // for ConstantExpr
    2122#include "Type.h"    // for BasicType, Type, Type::Qualifiers, PointerType
    2223
    23 Constant::Constant( Type * type, std::string rep, unsigned long long val ) : type( type ), rep( rep ), val( val ) {}
    24 Constant::Constant( Type * type, std::string rep, double val ) : type( type ), rep( rep ), val( val ) {}
     24Constant::Constant( Type * type, std::string rep, std::optional<unsigned long long> ival ) : type( type ), rep( rep ), ival( ival ) {}
    2525
    26 Constant::Constant( const Constant &other ) : rep( other.rep ), val( other.val ) {
     26Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), ival( other.ival ) {
    2727        type = other.type->clone();
    2828}
     
    3434}
    3535
    36 Constant 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 
    4036Constant Constant::from_int( int i ) {
    4137        return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ), (unsigned long long int)i );
     
    4440Constant Constant::from_ulong( unsigned long i ) {
    4541        return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ), (unsigned long long int)i );
    46 }
    47 
    48 Constant Constant::from_double( double d ) {
    49         return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ), d );
    5042}
    5143
     
    6355unsigned long long Constant::get_ival() const {
    6456        assertf( strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." );
    65         return val.ival;
    66 }
    67 
    68 double Constant::get_dval() const {
    69         assertf( ! strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve dval from integer constant." );
    70         return val.dval;
     57        return ival.value();
    7158}
    7259
    7360void Constant::print( std::ostream &os, Indenter ) const {
    74         os << "(" << rep << " " << val.ival;
     61        os << "(" << rep << " " << (ival ? toString(ival.value()) : "") ;
    7562        if ( type ) {
    7663                os << ": ";
  • src/SynTree/Constant.h

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:54:46 2017
    13 // Update Count     : 17
     12// Last Modified On : Wed Jul 10 15:57:38 2019
     13// Update Count     : 19
    1414//
    1515
     
    1818#include <iosfwd>     // for ostream
    1919#include <string>     // for string
     20#include <optional>   // for optional
    2021
    2122#include "BaseSyntaxNode.h"
     
    2728class Constant : public BaseSyntaxNode {
    2829  public:
    29         Constant( Type * type, std::string rep, unsigned long long val );
    30         Constant( Type * type, std::string rep, double val );
     30        Constant( Type * type, std::string rep, std::optional<unsigned long long> i );
    3131        Constant( const Constant & other );
     32        Constant & operator=( const Constant & ) = default;
    3233        virtual ~Constant();
    3334
    34         virtual Constant * clone() const { return new Constant( *this ); }
     35        virtual Constant * clone() const override { return new Constant( *this ); }
    3536
    3637        Type * get_type() { return type; }
     
    3940        void set_value( std::string newValue ) { rep = newValue; }
    4041        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 );
    4745        /// generates an integer constant of the given int
    4846        static Constant from_int( int i );
    4947        /// generates an integer constant of the given unsigned long int
    5048        static Constant from_ulong( unsigned long i );
    51         /// generates a floating point constant of the given double
    52         static Constant from_double( double d );
    5349
    5450        /// generates a null pointer value for the given type. void * if omitted.
    5551        static Constant null( Type * ptrtype = nullptr );
    5652
    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:
     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
    6158        Type * type;
    6259        std::string rep;
    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;
     60        std::optional<unsigned long long> ival;
    6961};
    7062
  • src/SynTree/DeclReplacer.cc

    r7951100 rb067d9b  
    3030                        bool debug;
    3131                public:
     32                        size_t replaced;
     33
     34                public:
    3235                        DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
    3336
     
    3841                        void previsit( TypeInstType * inst );
    3942                };
     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                };
    4058        }
    4159
    42         void replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
     60        size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
    4361                PassVisitor<DeclReplacer> replacer( declMap, typeMap, debug );
    4462                maybeAccept( node, replacer );
     63                return replacer.pass.replaced;
    4564        }
    4665
    47         void replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug ) {
     66        size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug ) {
    4867                TypeMap typeMap;
    49                 replace( node, declMap, typeMap, debug );
     68                return replace( node, declMap, typeMap, debug );
    5069        }
    5170
    52         void replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug ) {
     71        size_t replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug ) {
    5372                DeclMap declMap;
    54                 replace( node, declMap, typeMap, debug );
     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;
    5580        }
    5681
    5782        namespace {
    58                 DeclReplacer::DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug ) : declMap( declMap ), typeMap( typeMap ) , debug( debug ) {}
     83                DeclReplacer::DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug ) : declMap( declMap ), typeMap( typeMap ) , debug( debug ), replaced( 0 ) {}
    5984
    6085                // replace variable with new node from decl map
     
    6287                        // 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)
    6388                        if ( declMap.count( varExpr->var ) ) {
     89                                replaced++;
    6490                                auto replacement = declMap.at( varExpr->var );
    6591                                if ( debug ) {
     
    7298                void DeclReplacer::previsit( TypeInstType * inst ) {
    7399                        if ( typeMap.count( inst->baseType ) ) {
     100                                replaced++;
    74101                                auto replacement = typeMap.at( inst->baseType );
    75102                                if ( debug ) {
     
    79106                        }
    80107                }
     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                }
    81124        }
    82125} // namespace VarExprReplacer
  • src/SynTree/DeclReplacer.h

    r7951100 rb067d9b  
    2626        typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
    2727        typedef std::map< TypeDecl *, TypeDecl * > TypeMap;
     28        typedef std::map< DeclarationWithType *, Expression * > ExprMap;
    2829
    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 );
     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        }
    3245}
    3346
  • src/SynTree/Declaration.cc

    r7951100 rb067d9b  
    2727
    2828static UniqueId lastUniqueId = 0;
    29 typedef std::map< UniqueId, Declaration* > IdMapType;
    30 static IdMapType idMap;
    3129
    3230Declaration::Declaration( const std::string &name, Type::StorageClasses scs, LinkageSpec::Spec linkage )
    33                 : name( name ), linkage( linkage ), storageClasses( scs ), uniqueId( 0 ) {
     31                : name( name ), linkage( linkage ), uniqueId( 0 ), storageClasses( scs ) {
    3432}
    3533
    3634Declaration::Declaration( const Declaration &other )
    37         : BaseSyntaxNode( other ), name( other.name ), linkage( other.linkage ), extension( other.extension ), storageClasses( other.storageClasses ), uniqueId( other.uniqueId ) {
     35        : BaseSyntaxNode( other ), name( other.name ), linkage( other.linkage ), extension( other.extension ), uniqueId( other.uniqueId ), storageClasses( other.storageClasses ) {
    3836}
    3937
     
    4543        if ( uniqueId ) return;
    4644        uniqueId = ++lastUniqueId;
    47         idMap[ uniqueId ] = this;
    4845}
    49 
    50 Declaration *Declaration::declFromId( UniqueId id ) {
    51         IdMapType::const_iterator i = idMap.find( id );
    52         return i != idMap.end() ? i->second : 0;
    53 }
    54 
    55 void 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 
    6346
    6447AsmDecl::AsmDecl( AsmStmt *stmt ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), stmt( stmt ) {
  • src/SynTree/Declaration.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep  3 19:24:06 2017
    13 // Update Count     : 131
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr May  2 10:47:00 2019
     13// Update Count     : 135
    1414//
    1515
     
    1919#include <iosfwd>                // for ostream
    2020#include <list>                  // for list
     21#include <unordered_map>         // for unordered_map
    2122#include <string>                // for string, operator+, allocator, to_string
    2223
     
    6263        void fixUniqueId( void );
    6364        virtual Declaration *clone() const override = 0;
    64         virtual void accept( Visitor &v ) override = 0;
     65        virtual void accept( Visitor & v ) override = 0;
     66        virtual void accept( Visitor & v ) const override = 0;
    6567        virtual Declaration *acceptMutator( Mutator &m ) override = 0;
    6668        virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
    6769        virtual void printShort( std::ostream &os, Indenter indent = {} ) const = 0;
    6870
    69         static void dumpIds( std::ostream &os );
    70         static Declaration *declFromId( UniqueId id );
    71 
    72   private:
     71        UniqueId uniqueId;
    7372        Type::StorageClasses storageClasses;
    74         UniqueId uniqueId;
     73  private:
    7574};
    7675
     
    141140
    142141        virtual ObjectDecl *clone() const override { return new ObjectDecl( *this ); }
    143         virtual void accept( Visitor &v ) override { v.visit( this ); }
     142        virtual void accept( Visitor & v ) override { v.visit( this ); }
     143        virtual void accept( Visitor & v ) const 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; }
    168169
    169170        static FunctionDecl * newFunction( const std::string & name, FunctionType * type, CompoundStmt * statements );
    170171
    171172        virtual FunctionDecl *clone() const override { return new FunctionDecl( *this ); }
    172         virtual void accept( Visitor &v ) override { v.visit( this ); }
     173        virtual void accept( Visitor & v ) override { v.visit( this ); }
     174        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    173175        virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    174176        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    202204        typedef NamedTypeDecl Parent;
    203205  public:
    204         enum Kind { Dtype, Ftype, Ttype };
     206        enum Kind { Dtype, Ftype, Ttype, NUMBER_OF_KINDS };
    205207
    206208        Type * init;
     
    211213                TypeDecl::Kind kind;
    212214                bool isComplete;
     215
    213216                Data() : kind( (TypeDecl::Kind)-1 ), isComplete( false ) {}
    214217                Data( TypeDecl * typeDecl ) : Data( typeDecl->get_kind(), typeDecl->isComplete() ) {}
    215218                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
    216222                bool operator==(const Data & other) const { return kind == other.kind && isComplete == other.isComplete; }
    217223                bool operator!=(const Data & other) const { return !(*this == other);}
     
    235241
    236242        virtual TypeDecl *clone() const override { return new TypeDecl( *this ); }
    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:
     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
    242248        Kind kind;
    243249};
     
    254260
    255261        virtual TypedefDecl *clone() const override { return new TypedefDecl( *this ); }
    256         virtual void accept( Visitor &v ) override { v.visit( this ); }
     262        virtual void accept( Visitor & v ) override { v.visit( this ); }
     263        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    257264        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    258265  private:
     
    266273        bool body;
    267274        std::list< Attribute * > attributes;
     275        AggregateDecl * parent = nullptr;
    268276
    269277        AggregateDecl( const std::string &name, const std::list< Attribute * > & attributes = std::list< class Attribute * >(), LinkageSpec::Spec linkage = LinkageSpec::Cforall );
     
    280288        AggregateDecl * set_body( bool body ) { AggregateDecl::body = body; return this; }
    281289
    282         virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     290        virtual void print( std::ostream &os, Indenter indent = {} ) const override final;
    283291        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
    284292  protected:
     
    297305
    298306        virtual StructDecl *clone() const override { return new StructDecl( *this ); }
    299         virtual void accept( Visitor &v ) override { v.visit( this ); }
    300         virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    301   private:
     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 ); }
    302310        DeclarationNode::Aggregate kind;
     311  private:
    303312        virtual std::string typeString() const override;
    304313};
     
    311320
    312321        virtual UnionDecl *clone() const override { return new UnionDecl( *this ); }
    313         virtual void accept( Visitor &v ) override { v.visit( this ); }
     322        virtual void accept( Visitor & v ) override { v.visit( this ); }
     323        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    314324        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    315325  private:
     
    326336
    327337        virtual EnumDecl *clone() const override { return new EnumDecl( *this ); }
    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;
     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;
    332343        virtual std::string typeString() const override;
    333344};
     
    342353
    343354        virtual TraitDecl *clone() const override { return new TraitDecl( *this ); }
    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;
     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
     362class WithStmt : public Declaration {
     363public:
     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); }
    348377};
    349378
     
    360389
    361390        virtual AsmDecl *clone() const override { return new AsmDecl( *this ); }
    362         virtual void accept( Visitor &v ) override { v.visit( this ); }
     391        virtual void accept( Visitor & v ) override { v.visit( this ); }
     392        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    363393        virtual AsmDecl *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    364394        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    376406
    377407        virtual StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
    378         virtual void accept( Visitor &v ) override { v.visit( this ); }
     408        virtual void accept( Visitor & v ) override { v.visit( this ); }
     409        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    379410        virtual StaticAssertDecl * acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    380411        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
  • src/SynTree/Expression.cc

    r7951100 rb067d9b  
    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 : Tue Jul 25 14:15:47 2017
    13 // Update Count     : 54
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Aug 15 13:43:00 2019
     13// Update Count     : 64
    1414//
    1515
     
    1919#include <iostream>                  // for ostream, operator<<, basic_ostream
    2020#include <list>                      // for list, _List_iterator, list<>::co...
     21#include <set>                       // for set
    2122
    2223#include "Common/utility.h"          // for maybeClone, cloneAll, deleteAll
     
    3334#include "GenPoly/Lvalue.h"
    3435
    35 void printInferParams( const InferredParams & inferParams, std::ostream &os, Indenter indent, int level ) {
     36void printInferParams( const InferredParams & inferParams, std::ostream & os, Indenter indent, int level ) {
    3637        if ( ! inferParams.empty() ) {
    3738                os << indent << "with inferred parameters " << level << ":" << std::endl;
    3839                for ( InferredParams::const_iterator i = inferParams.begin(); i != inferParams.end(); ++i ) {
    3940                        os << indent+1;
    40                         Declaration::declFromId( i->second.decl )->printShort( os, indent+1 );
     41                        assert(i->second.declptr);
     42                        i->second.declptr->printShort( os, indent+1 );
    4143                        os << std::endl;
    42                         printInferParams( *i->second.inferParams, os, indent+1, level+1 );
     44                        printInferParams( i->second.expr->inferParams, os, indent+1, level+1 );
    4345                } // for
    4446        } // if
     
    4749Expression::Expression() : result( 0 ), env( 0 ) {}
    4850
    49 Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ) {
    50 }
     51Expression::Expression( const Expression & other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ), resnSlots( other.resnSlots ) {}
    5152
    5253void Expression::spliceInferParams( Expression * other ) {
     
    5556                inferParams[p.first] = std::move( p.second );
    5657        }
     58        resnSlots.insert( resnSlots.end(), other->resnSlots.begin(), other->resnSlots.end() );
    5759}
    5860
     
    6264}
    6365
    64 void Expression::print( std::ostream &os, Indenter indent ) const {
     66bool Expression::get_lvalue() const {
     67        return false;
     68}
     69
     70void Expression::print( std::ostream & os, Indenter indent ) const {
    6571        printInferParams( inferParams, os, indent+1, 0 );
    6672
     
    7985}
    8086
    81 ConstantExpr::ConstantExpr( const ConstantExpr &other) : Expression( other ), constant( other.constant ) {
     87ConstantExpr::ConstantExpr( const ConstantExpr & other) : Expression( other ), constant( other.constant ) {
    8288}
    8389
    8490ConstantExpr::~ConstantExpr() {}
    8591
    86 void ConstantExpr::print( std::ostream &os, Indenter indent ) const {
     92void ConstantExpr::print( std::ostream & os, Indenter indent ) const {
    8793        os << "constant expression " ;
    8894        constant.print( os );
     
    103109}
    104110
     111VariableExpr::VariableExpr() : Expression(), var( nullptr ) {}
     112
    105113VariableExpr::VariableExpr( DeclarationWithType *_var ) : Expression(), var( _var ) {
    106114        assert( var );
    107115        assert( var->get_type() );
    108116        Type * type = var->get_type()->clone();
    109         type->set_lvalue( true );
    110117
    111118        // xxx - doesn't quite work yet - get different alternatives with the same cost
     
    117124        //      long long int value;
    118125        //      if ( decl->valueOf( var, value ) ) {
    119         //              type->set_lvalue( false );
     126        //              type->set_lvalue( false ); // Would have to move to get_lvalue.
    120127        //      }
    121128        // }
     
    124131}
    125132
    126 VariableExpr::VariableExpr( const VariableExpr &other ) : Expression( other ), var( other.var ) {
     133VariableExpr::VariableExpr( const VariableExpr & other ) : Expression( other ), var( other.var ) {
    127134}
    128135
    129136VariableExpr::~VariableExpr() {
    130137        // don't delete the declaration, since it points somewhere else in the tree
     138}
     139
     140bool VariableExpr::get_lvalue() const {
     141        // It isn't always an lvalue, but it is never an rvalue.
     142        return true;
    131143}
    132144
     
    137149}
    138150
    139 void VariableExpr::print( std::ostream &os, Indenter indent ) const {
     151void VariableExpr::print( std::ostream & os, Indenter indent ) const {
    140152        os << "Variable Expression: ";
    141153        var->printShort(os, indent);
     
    143155}
    144156
    145 SizeofExpr::SizeofExpr( Expression *expr_ ) :
     157SizeofExpr::SizeofExpr( Expression * expr_ ) :
    146158                Expression(), expr(expr_), type(0), isType(false) {
    147159        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    148160}
    149161
    150 SizeofExpr::SizeofExpr( Type *type_ ) :
     162SizeofExpr::SizeofExpr( Type * type_ ) :
    151163                Expression(), expr(0), type(type_), isType(true) {
    152164        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    153165}
    154166
    155 SizeofExpr::SizeofExpr( const SizeofExpr &other ) :
     167SizeofExpr::SizeofExpr( const SizeofExpr & other ) :
    156168        Expression( other ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
    157169}
     
    162174}
    163175
    164 void SizeofExpr::print( std::ostream &os, Indenter indent) const {
     176void SizeofExpr::print( std::ostream & os, Indenter indent) const {
    165177        os << "Sizeof Expression on: ";
    166178        if (isType) type->print(os, indent+1);
     
    169181}
    170182
    171 AlignofExpr::AlignofExpr( Expression *expr_ ) :
     183AlignofExpr::AlignofExpr( Expression * expr_ ) :
    172184                Expression(), expr(expr_), type(0), isType(false) {
    173185        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    174186}
    175187
    176 AlignofExpr::AlignofExpr( Type *type_ ) :
     188AlignofExpr::AlignofExpr( Type * type_ ) :
    177189                Expression(), expr(0), type(type_), isType(true) {
    178190        set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
    179191}
    180192
    181 AlignofExpr::AlignofExpr( const AlignofExpr &other ) :
     193AlignofExpr::AlignofExpr( const AlignofExpr & other ) :
    182194        Expression( other ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
    183195}
     
    188200}
    189201
    190 void AlignofExpr::print( std::ostream &os, Indenter indent) const {
     202void AlignofExpr::print( std::ostream & os, Indenter indent) const {
    191203        os << "Alignof Expression on: ";
    192204        if (isType) type->print(os, indent+1);
     
    195207}
    196208
    197 UntypedOffsetofExpr::UntypedOffsetofExpr( Type *type, const std::string &member ) :
     209UntypedOffsetofExpr::UntypedOffsetofExpr( Type * type, const std::string & member ) :
    198210                Expression(), type(type), member(member) {
    199211        assert( type );
     
    201213}
    202214
    203 UntypedOffsetofExpr::UntypedOffsetofExpr( const UntypedOffsetofExpr &other ) :
     215UntypedOffsetofExpr::UntypedOffsetofExpr( const UntypedOffsetofExpr & other ) :
    204216        Expression( other ), type( maybeClone( other.type ) ), member( other.member ) {}
    205217
     
    208220}
    209221
    210 void UntypedOffsetofExpr::print( std::ostream &os, Indenter indent) const {
     222void UntypedOffsetofExpr::print( std::ostream & os, Indenter indent) const {
    211223        os << "Untyped Offsetof Expression on member " << member << " of ";
    212224        type->print(os, indent+1);
     
    214226}
    215227
    216 OffsetofExpr::OffsetofExpr( Type *type, DeclarationWithType *member ) :
     228OffsetofExpr::OffsetofExpr( Type * type, DeclarationWithType * member ) :
    217229                Expression(), type(type), member(member) {
    218230        assert( member );
     
    221233}
    222234
    223 OffsetofExpr::OffsetofExpr( const OffsetofExpr &other ) :
     235OffsetofExpr::OffsetofExpr( const OffsetofExpr & other ) :
    224236        Expression( other ), type( maybeClone( other.type ) ), member( other.member ) {}
    225237
     
    228240}
    229241
    230 void OffsetofExpr::print( std::ostream &os, Indenter indent) const {
     242void OffsetofExpr::print( std::ostream & os, Indenter indent) const {
    231243        os << "Offsetof Expression on member " << member->name << " of ";
    232244        type->print(os, indent+1);
     
    234246}
    235247
    236 OffsetPackExpr::OffsetPackExpr( StructInstType *type ) : Expression(), type( type ) {
     248OffsetPackExpr::OffsetPackExpr( StructInstType * type ) : Expression(), type( type ) {
    237249        assert( type );
    238250        set_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) );
    239251}
    240252
    241 OffsetPackExpr::OffsetPackExpr( const OffsetPackExpr &other ) : Expression( other ), type( maybeClone( other.type ) ) {}
     253OffsetPackExpr::OffsetPackExpr( const OffsetPackExpr & other ) : Expression( other ), type( maybeClone( other.type ) ) {}
    242254
    243255OffsetPackExpr::~OffsetPackExpr() { delete type; }
    244256
    245 void OffsetPackExpr::print( std::ostream &os, Indenter indent ) const {
     257void OffsetPackExpr::print( std::ostream & os, Indenter indent ) const {
    246258        os << "Offset pack expression on ";
    247259        type->print(os, indent+1);
     
    249261}
    250262
    251 AttrExpr::AttrExpr( Expression *attr, Expression *expr_ ) :
    252                 Expression(), attr( attr ), expr(expr_), type(0), isType(false) {
    253 }
    254 
    255 AttrExpr::AttrExpr( Expression *attr, Type *type_ ) :
    256                 Expression(), attr( attr ), expr(0), type(type_), isType(true) {
    257 }
    258 
    259 AttrExpr::AttrExpr( const AttrExpr &other ) :
    260                 Expression( other ), attr( maybeClone( other.attr ) ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
    261 }
    262 
    263 AttrExpr::~AttrExpr() {
    264         delete attr;
    265         delete expr;
    266         delete type;
    267 }
    268 
    269 void 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 
    280 CastExpr::CastExpr( Expression *arg, Type *toType, bool isGenerated ) : Expression(), arg(arg), isGenerated( isGenerated ) {
     263CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {
    281264        set_result(toType);
    282265}
    283266
    284 CastExpr::CastExpr( Expression *arg, bool isGenerated ) : Expression(), arg(arg), isGenerated( isGenerated ) {
     267CastExpr::CastExpr( Expression * arg, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {
    285268        set_result( new VoidType( Type::Qualifiers() ) );
    286269}
    287270
    288 CastExpr::CastExpr( const CastExpr &other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ) {
     271CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ) {
    289272}
    290273
     
    293276}
    294277
    295 void CastExpr::print( std::ostream &os, Indenter indent ) const {
    296         os << "Cast of:" << std::endl << indent+1;
     278bool 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
     283void CastExpr::print( std::ostream & os, Indenter indent ) const {
     284        os << (isGenerated ? "Generated " : "Explicit ") << "Cast of:" << std::endl << indent+1;
    297285        arg->print(os, indent+1);
    298286        os << std::endl << indent << "... to:";
     
    306294}
    307295
    308 KeywordCastExpr::KeywordCastExpr( Expression *arg, Target target ) : Expression(), arg(arg), target( target ) {
    309 }
    310 
    311 KeywordCastExpr::KeywordCastExpr( const KeywordCastExpr &other ) : Expression( other ), arg( maybeClone( other.arg ) ), target( other.target ) {
     296KeywordCastExpr::KeywordCastExpr( Expression * arg, Target target ) : Expression(), arg(arg), target( target ) {
     297}
     298
     299KeywordCastExpr::KeywordCastExpr( const KeywordCastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), target( other.target ) {
    312300}
    313301
     
    327315}
    328316
    329 void KeywordCastExpr::print( std::ostream &os, Indenter indent ) const {
     317void KeywordCastExpr::print( std::ostream & os, Indenter indent ) const {
    330318        os << "Keyword Cast of:" << std::endl << indent+1;
    331319        arg->print(os, indent+1);
     
    335323}
    336324
    337 VirtualCastExpr::VirtualCastExpr( Expression *arg_, Type *toType ) : Expression(), arg(arg_) {
     325VirtualCastExpr::VirtualCastExpr( Expression * arg_, Type * toType ) : Expression(), arg(arg_) {
    338326        set_result(toType);
    339327}
    340328
    341 VirtualCastExpr::VirtualCastExpr( const VirtualCastExpr &other ) : Expression( other ), arg( maybeClone( other.arg ) ) {
     329VirtualCastExpr::VirtualCastExpr( const VirtualCastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ) {
    342330}
    343331
     
    346334}
    347335
    348 void VirtualCastExpr::print( std::ostream &os, Indenter indent ) const {
     336void VirtualCastExpr::print( std::ostream & os, Indenter indent ) const {
    349337        os << "Virtual Cast of:" << std::endl << indent+1;
    350338        arg->print(os, indent+1);
     
    359347}
    360348
    361 UntypedMemberExpr::UntypedMemberExpr( Expression * member, Expression *aggregate ) :
     349UntypedMemberExpr::UntypedMemberExpr( Expression * member, Expression * aggregate ) :
    362350                Expression(), member(member), aggregate(aggregate) {
    363351        assert( aggregate );
    364352}
    365353
    366 UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr &other ) :
     354UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr & other ) :
    367355                Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) {
    368356}
     
    373361}
    374362
    375 void UntypedMemberExpr::print( std::ostream &os, Indenter indent ) const {
     363bool UntypedMemberExpr::get_lvalue() const {
     364        return aggregate->get_lvalue();
     365}
     366
     367void UntypedMemberExpr::print( std::ostream & os, Indenter indent ) const {
    376368        os << "Untyped Member Expression, with field: " << std::endl << indent+1;
    377369        member->print(os, indent+1 );
    378         os << indent << "... from aggregate: " << std::endl << indent+1;
     370        os << indent << "... from aggregate:" << std::endl << indent+1;
    379371        aggregate->print(os, indent+1);
    380372        Expression::print( os, indent );
    381373}
    382374
    383 MemberExpr::MemberExpr( DeclarationWithType *member, Expression *aggregate ) :
     375MemberExpr::MemberExpr( DeclarationWithType * member, Expression * aggregate ) :
    384376                Expression(), member(member), aggregate(aggregate) {
    385377        assert( member );
     
    391383        sub.apply( res );
    392384        result = res;
    393         result->set_lvalue( true );
    394385        result->get_qualifiers() |= aggregate->result->get_qualifiers();
    395386}
    396387
    397 MemberExpr::MemberExpr( const MemberExpr &other ) :
     388MemberExpr::MemberExpr( const MemberExpr & other ) :
    398389                Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) {
    399390}
     
    404395}
    405396
    406 void MemberExpr::print( std::ostream &os, Indenter indent ) const {
    407         os << "Member Expression, with field: " << std::endl;
     397bool MemberExpr::get_lvalue() const {
     398        // This is actually wrong by C, but it works with our current set-up.
     399        return true;
     400}
     401
     402void MemberExpr::print( std::ostream & os, Indenter indent ) const {
     403        os << "Member Expression, with field:" << std::endl;
    408404        os << indent+1;
    409405        member->print( os, indent+1 );
    410         os << std::endl << indent << "... from aggregate: " << std::endl << indent+1;
     406        os << std::endl << indent << "... from aggregate:" << std::endl << indent+1;
    411407        aggregate->print(os, indent + 1);
    412408        Expression::print( os, indent );
    413409}
    414410
    415 UntypedExpr::UntypedExpr( Expression *function, const std::list<Expression *> &args ) :
     411UntypedExpr::UntypedExpr( Expression * function, const std::list<Expression *> & args ) :
    416412                Expression(), function(function), args(args) {}
    417413
    418 UntypedExpr::UntypedExpr( const UntypedExpr &other ) :
     414UntypedExpr::UntypedExpr( const UntypedExpr & other ) :
    419415                Expression( other ), function( maybeClone( other.function ) ) {
    420416        cloneAll( other.args, args );
     
    435431                        // if references are still allowed in the AST, dereference returns a reference
    436432                        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 );
    440433                }
    441434        }
     
    454447}
    455448
    456 
    457 void UntypedExpr::print( std::ostream &os, Indenter indent ) const {
    458         os << "Applying untyped: " << std::endl;
     449bool 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
     456void UntypedExpr::print( std::ostream & os, Indenter indent ) const {
     457        os << "Applying untyped:" << std::endl;
    459458        os << indent+1;
    460459        function->print(os, indent+1);
    461         os << std::endl << indent << "...to: " << std::endl;
     460        os << std::endl << indent << "...to:" << std::endl;
    462461        printAll(args, os, indent+1);
    463462        Expression::print( os, indent );
     
    469468}
    470469
    471 NameExpr::NameExpr( const NameExpr &other ) : Expression( other ), name( other.name ) {
     470NameExpr::NameExpr( const NameExpr & other ) : Expression( other ), name( other.name ) {
    472471}
    473472
    474473NameExpr::~NameExpr() {}
    475474
    476 void NameExpr::print( std::ostream &os, Indenter indent ) const {
     475void NameExpr::print( std::ostream & os, Indenter indent ) const {
    477476        os << "Name: " << get_name();
    478477        Expression::print( os, indent );
    479478}
    480479
    481 LogicalExpr::LogicalExpr( Expression *arg1_, Expression *arg2_, bool andp ) :
     480LogicalExpr::LogicalExpr( Expression * arg1_, Expression * arg2_, bool andp ) :
    482481                Expression(), arg1(arg1_), arg2(arg2_), isAnd(andp) {
    483482        set_result( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    484483}
    485484
    486 LogicalExpr::LogicalExpr( const LogicalExpr &other ) :
     485LogicalExpr::LogicalExpr( const LogicalExpr & other ) :
    487486                Expression( other ), arg1( maybeClone( other.arg1 ) ), arg2( maybeClone( other.arg2 ) ), isAnd( other.isAnd ) {
    488487}
     
    493492}
    494493
    495 void LogicalExpr::print( std::ostream &os, Indenter indent )const {
     494void LogicalExpr::print( std::ostream & os, Indenter indent )const {
    496495        os << "Short-circuited operation (" << (isAnd ? "and" : "or") << ") on: ";
    497496        arg1->print(os);
     
    504503                Expression(), arg1(arg1), arg2(arg2), arg3(arg3) {}
    505504
    506 ConditionalExpr::ConditionalExpr( const ConditionalExpr &other ) :
     505ConditionalExpr::ConditionalExpr( const ConditionalExpr & other ) :
    507506                Expression( other ), arg1( maybeClone( other.arg1 ) ), arg2( maybeClone( other.arg2 ) ), arg3( maybeClone( other.arg3 ) ) {
    508507}
     
    514513}
    515514
    516 void ConditionalExpr::print( std::ostream &os, Indenter indent ) const {
     515bool ConditionalExpr::get_lvalue() const {
     516        return false;
     517}
     518
     519void ConditionalExpr::print( std::ostream & os, Indenter indent ) const {
    517520        os << "Conditional expression on: " << std::endl << indent+1;
    518521        arg1->print( os, indent+1 );
     
    527530
    528531
    529 void AsmExpr::print( std::ostream &os, Indenter indent ) const {
     532void AsmExpr::print( std::ostream & os, Indenter indent ) const {
    530533        os << "Asm Expression: " << std::endl;
    531534        if ( inout ) inout->print( os, indent+1 );
     
    538541        assert( callExpr );
    539542        assert( callExpr->result );
    540         set_result( callExpr->get_result()->clone() );
     543        set_result( callExpr->result->clone() );
    541544}
    542545
    543546ImplicitCopyCtorExpr::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         deleteAll( tempDecls );
    553         deleteAll( returnDecls );
    554         deleteAll( dtors );
    555 }
    556 
    557 void ImplicitCopyCtorExpr::print( std::ostream &os, Indenter indent ) const {
     552}
     553
     554void ImplicitCopyCtorExpr::print( std::ostream & os, Indenter indent ) const {
    558555        os <<  "Implicit Copy Constructor Expression: " << std::endl << indent+1;
    559556        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 );
    565557}
    566558
     
    581573}
    582574
    583 void ConstructorExpr::print( std::ostream &os, Indenter indent ) const {
     575bool ConstructorExpr::get_lvalue() const {
     576        return false;
     577}
     578
     579void ConstructorExpr::print( std::ostream & os, Indenter indent ) const {
    584580        os <<  "Constructor Expression: " << std::endl << indent+1;
    585581        callExpr->print( os, indent + 2 );
     
    590586CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : initializer( initializer ) {
    591587        assert( type && initializer );
    592         type->set_lvalue( true );
    593588        set_result( type );
    594589}
    595590
    596 CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr &other ) : Expression( other ), initializer( other.initializer->clone() ) {}
     591CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr & other ) : Expression( other ), initializer( other.initializer->clone() ) {}
    597592
    598593CompoundLiteralExpr::~CompoundLiteralExpr() {
     
    600595}
    601596
    602 void CompoundLiteralExpr::print( std::ostream &os, Indenter indent ) const {
     597bool CompoundLiteralExpr::get_lvalue() const {
     598        return true;
     599}
     600
     601void CompoundLiteralExpr::print( std::ostream & os, Indenter indent ) const {
    603602        os << "Compound Literal Expression: " << std::endl << indent+1;
    604603        result->print( os, indent+1 );
     
    608607}
    609608
    610 RangeExpr::RangeExpr( Expression *low, Expression *high ) : low( low ), high( high ) {}
    611 RangeExpr::RangeExpr( const RangeExpr &other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
    612 void RangeExpr::print( std::ostream &os, Indenter indent ) const {
     609RangeExpr::RangeExpr( Expression * low, Expression * high ) : low( low ), high( high ) {}
     610RangeExpr::RangeExpr( const RangeExpr & other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
     611void RangeExpr::print( std::ostream & os, Indenter indent ) const {
    613612        os << "Range Expression: ";
    614613        low->print( os, indent );
     
    618617}
    619618
    620 StmtExpr::StmtExpr( CompoundStmt *statements ) : statements( statements ) {
     619StmtExpr::StmtExpr( CompoundStmt * statements ) : statements( statements ) {
    621620        computeResult();
    622621}
    623 StmtExpr::StmtExpr( const StmtExpr &other ) : Expression( other ), statements( other.statements->clone() ) {
     622StmtExpr::StmtExpr( const StmtExpr & other ) : Expression( other ), statements( other.statements->clone() ), resultExpr( other.resultExpr ) {
    624623        cloneAll( other.returnDecls, returnDecls );
    625624        cloneAll( other.dtors, dtors );
     
    650649        }
    651650}
    652 void StmtExpr::print( std::ostream &os, Indenter indent ) const {
     651bool StmtExpr::get_lvalue() const {
     652        return false;
     653}
     654void StmtExpr::print( std::ostream & os, Indenter indent ) const {
    653655        os << "Statement Expression: " << std::endl << indent+1;
    654656        statements->print( os, indent+1 );
     
    666668
    667669long long UniqueExpr::count = 0;
    668 UniqueExpr::UniqueExpr( Expression *expr, long long idVal ) : expr( expr ), object( nullptr ), var( nullptr ), id( idVal ) {
     670UniqueExpr::UniqueExpr( Expression * expr, long long idVal ) : expr( expr ), object( nullptr ), var( nullptr ), id( idVal ) {
    669671        assert( expr );
    670672        assert( count != -1 );
     
    674676        }
    675677}
    676 UniqueExpr::UniqueExpr( const UniqueExpr &other ) : Expression( other ), expr( maybeClone( other.expr ) ), object( maybeClone( other.object ) ), var( maybeClone( other.var ) ), id( other.id ) {
     678UniqueExpr::UniqueExpr( const UniqueExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), object( maybeClone( other.object ) ), var( maybeClone( other.var ) ), id( other.id ) {
    677679}
    678680UniqueExpr::~UniqueExpr() {
     
    681683        delete var;
    682684}
    683 void UniqueExpr::print( std::ostream &os, Indenter indent ) const {
     685void UniqueExpr::print( std::ostream & os, Indenter indent ) const {
    684686        os << "Unique Expression with id:" << id << std::endl << indent+1;
    685687        expr->print( os, indent+1 );
     
    732734}
    733735
    734 DeletedExpr::DeletedExpr( Expression * expr, BaseSyntaxNode * deleteStmt ) : expr( expr ), deleteStmt( deleteStmt ) {
     736DeletedExpr::DeletedExpr( Expression * expr, Declaration * deleteStmt ) : expr( expr ), deleteStmt( deleteStmt ) {
    735737        assert( expr->result );
    736738        result = expr->result->clone();
     
    746748        os << std::endl << indent+1 << "... deleted by: ";
    747749        deleteStmt->print( os, indent+1 );
     750}
     751
     752
     753DefaultArgExpr::DefaultArgExpr( Expression * expr ) : expr( expr ) {
     754        assert( expr->result );
     755        result = expr->result->clone();
     756}
     757DefaultArgExpr::DefaultArgExpr( const DefaultArgExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ) {}
     758DefaultArgExpr::~DefaultArgExpr() {
     759        delete expr;
     760}
     761
     762void DefaultArgExpr::print( std::ostream & os, Indenter indent ) const {
     763        os << "Default Argument Expression" << std::endl << indent+1;
     764        expr->print( os, indent+1 );
    748765}
    749766
  • src/SynTree/Expression.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep  3 19:23:46 2017
    13 // Update Count     : 48
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Aug 15 13:46:00 2019
     13// Update Count     : 54
    1414//
    1515
     
    2121#include <memory>                 // for allocator, unique_ptr
    2222#include <string>                 // for string
     23#include <vector>                 // for vector
    2324
    2425#include "BaseSyntaxNode.h"       // for BaseSyntaxNode
     
    3839/// but subject to decay-to-pointer and type parameter renaming
    3940struct ParamEntry {
    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 ) {}
     41        ParamEntry(): decl( 0 ), declptr( nullptr ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
     42        ParamEntry( UniqueId decl, Declaration * declptr, Type * actualType, Type * formalType, Expression* expr );
    4243        ParamEntry( const ParamEntry & other );
    4344        ParamEntry( ParamEntry && other );
    4445        ~ParamEntry();
    45         ParamEntry & operator=( const ParamEntry & other );
    4646        ParamEntry & operator=( ParamEntry && other );
    4747
    48         UniqueId decl;
    49         Type * actualType;
    50         Type * formalType;
     48        UniqueId const decl;
     49        Declaration * const declptr;
     50        Type * const actualType;
     51        Type * const formalType;
    5152        Expression * expr;
    52         std::unique_ptr< InferredParams > inferParams;
    5353};
    5454
     
    5959        TypeSubstitution * env;
    6060        bool extension = false;
    61         InferredParams inferParams;
     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
    6265
    6366        Expression();
     
    6871        const Type * get_result() const { return result; }
    6972        void set_result( Type * newValue ) { result = newValue; }
     73        virtual bool get_lvalue() const;
    7074
    7175        TypeSubstitution * get_env() const { return env; }
     
    7478        Expression * set_extension( bool exten ) { extension = exten; return this; }
    7579
    76         InferredParams & get_inferParams() { return inferParams; }
    77 
    7880        // move other's inferParams to this
    7981        void spliceInferParams( Expression * other );
     
    8183        virtual Expression * clone() const override = 0;
    8284        virtual void accept( Visitor & v ) override = 0;
     85        virtual void accept( Visitor & v ) const override = 0;
    8386        virtual Expression * acceptMutator( Mutator & m ) override = 0;
    8487        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    9699        virtual ~ApplicationExpr();
    97100
     101        bool get_lvalue() const final;
     102
    98103        Expression * get_function() const { return function; }
    99104        void set_function( Expression * newValue ) { function = newValue; }
    100105        std::list<Expression *>& get_args() { return args; }
    101106
    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;
     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;
    106112};
    107113
     
    118124        virtual ~UntypedExpr();
    119125
     126        bool get_lvalue() const final;
     127
    120128        Expression * get_function() const { return function; }
    121129        void set_function( Expression * newValue ) { function = newValue; }
     
    128136        static UntypedExpr * createAssign( Expression * arg1, Expression * arg2 );
    129137
    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;
     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;
    134143};
    135144
     
    146155        void set_name( std::string newValue ) { name = newValue; }
    147156
    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;
     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;
    152162};
    153163
     
    167177        void set_arg(Expression * newValue ) { arg = newValue; }
    168178
    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;
     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;
    173184};
    174185
     
    183194        virtual ~LabelAddressExpr();
    184195
    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;
     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;
    189201};
    190202
     
    193205  public:
    194206        Expression * arg;
    195         bool isGenerated = true; // whether this cast appeared in the source program
     207        bool isGenerated = true; // cast generated implicitly by code generation or explicit in program
    196208
    197209        CastExpr( Expression * arg, bool isGenerated = true );
     
    201213        virtual ~CastExpr();
    202214
     215        bool get_lvalue() const final;
     216
    203217        Expression * get_arg() const { return arg; }
    204218        void set_arg( Expression * newValue ) { arg = newValue; }
    205219
    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;
     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;
    210225};
    211226
     
    224239        const std::string & targetString() const;
    225240
    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;
     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;
    230246};
    231247
     
    242258        void set_arg( Expression * newValue ) { arg = newValue; }
    243259
    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;
     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;
    248265};
    249266
     
    257274        UntypedMemberExpr( const UntypedMemberExpr & other );
    258275        virtual ~UntypedMemberExpr();
     276
     277        bool get_lvalue() const final;
    259278
    260279        Expression * get_member() const { return member; }
     
    263282        void set_aggregate( Expression * newValue ) { aggregate = newValue; }
    264283
    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;
     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;
    269289};
    270290
     
    279299        MemberExpr( const MemberExpr & other );
    280300        virtual ~MemberExpr();
     301
     302        bool get_lvalue() const final;
    281303
    282304        DeclarationWithType * get_member() const { return member; }
     
    285307        void set_aggregate( Expression * newValue ) { aggregate = newValue; }
    286308
    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;
     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;
    291314};
    292315
     
    297320        DeclarationWithType * var;
    298321
     322        VariableExpr();
    299323        VariableExpr( DeclarationWithType * var );
    300324        VariableExpr( const VariableExpr & other );
    301325        virtual ~VariableExpr();
    302326
     327        bool get_lvalue() const final;
     328
    303329        DeclarationWithType * get_var() const { return var; }
    304330        void set_var( DeclarationWithType * newValue ) { var = newValue; }
     
    306332        static VariableExpr * functionPointer( FunctionDecl * decl );
    307333
    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;
     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;
    312339};
    313340
     
    327354        long long int intValue() const;
    328355
    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;
     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;
    333361};
    334362
     
    352380        void set_isType( bool newValue ) { isType = newValue; }
    353381
    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;
     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;
    358387};
    359388
     
    377406        void set_isType( bool newValue ) { isType = newValue; }
    378407
    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;
     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;
    383413};
    384414
     
    398428        void set_type( Type * newValue ) { type = newValue; }
    399429
    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;
     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;
    404435};
    405436
     
    419450        void set_member( DeclarationWithType * newValue ) { member = newValue; }
    420451
    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;
     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;
    425457};
    426458
     
    437469        void set_type( StructInstType * newValue ) { type = newValue; }
    438470
    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)
    446 class 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;
     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;
    471476};
    472477
     
    487492        void set_arg2( Expression * newValue ) { arg2 = newValue; }
    488493
    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;
     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;
    493499
    494500  private:
     
    506512        ConditionalExpr( const ConditionalExpr & other );
    507513        virtual ~ConditionalExpr();
     514
     515        bool get_lvalue() const final;
    508516
    509517        Expression * get_arg1() const { return arg1; }
     
    514522        void set_arg3( Expression * newValue ) { arg3 = newValue; }
    515523
    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;
     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;
    520529};
    521530
     
    529538        CommaExpr( const CommaExpr & other );
    530539        virtual ~CommaExpr();
     540
     541        bool get_lvalue() const final;
    531542
    532543        Expression * get_arg1() const { return arg1; }
     
    535546        void set_arg2( Expression * newValue ) { arg2 = newValue; }
    536547
    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;
     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;
    541553};
    542554
     
    553565        void set_type( Type * newValue ) { type = newValue; }
    554566
    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;
     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;
    559572};
    560573
     
    579592        void set_operand( Expression * newValue ) { operand = newValue; }
    580593
    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;
     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;
    585599
    586600        // https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
     
    591605class ImplicitCopyCtorExpr : public Expression {
    592606public:
    593         ApplicationExpr * callExpr;
    594         std::list< ObjectDecl * > tempDecls;
    595         std::list< ObjectDecl * > returnDecls;
    596         std::list< Expression * > dtors;
     607        ApplicationExpr * callExpr = nullptr;
    597608
    598609        ImplicitCopyCtorExpr( ApplicationExpr * callExpr );
     
    600611        virtual ~ImplicitCopyCtorExpr();
    601612
    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;
     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;
    613618};
    614619
     
    622627        ~ConstructorExpr();
    623628
     629        bool get_lvalue() const final;
     630
    624631        Expression * get_callExpr() const { return callExpr; }
    625632        void set_callExpr( Expression * newValue ) { callExpr = newValue; }
    626633
    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;
     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;
    631639};
    632640
     
    640648        virtual ~CompoundLiteralExpr();
    641649
     650        bool get_lvalue() const final;
     651
    642652        Initializer * get_initializer() const { return initializer; }
    643653        void set_initializer( Initializer * i ) { initializer = i; }
    644654
    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;
     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;
    649660};
    650661
     
    662673        RangeExpr * set_high( Expression * high ) { RangeExpr::high = high; return this; }
    663674
    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;
     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;
    668680};
    669681
     
    679691        std::list<Expression*>& get_exprs() { return exprs; }
    680692
    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;
     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;
    685698};
    686699
     
    694707        virtual ~TupleExpr();
    695708
     709        bool get_lvalue() const final;
     710
    696711        std::list<Expression*>& get_exprs() { return exprs; }
    697712
    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;
     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;
    702718};
    703719
     
    711727        TupleIndexExpr( const TupleIndexExpr & other );
    712728        virtual ~TupleIndexExpr();
     729
     730        bool get_lvalue() const final;
    713731
    714732        Expression * get_tuple() const { return tuple; }
     
    717735        TupleIndexExpr * set_index( unsigned int newValue ) { index = newValue; return this; }
    718736
    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;
     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;
    723742};
    724743
     
    735754        StmtExpr * get_stmtExpr() const { return stmtExpr; }
    736755
    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;
     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 );
    741765};
    742766
     
    748772        std::list< Expression * > dtors; // destructor(s) for return variable(s)
    749773
     774        // readonly
     775        ExprStmt * resultExpr = nullptr;
     776
    750777        StmtExpr( CompoundStmt * statements );
    751778        StmtExpr( const StmtExpr & other );
    752779        virtual ~StmtExpr();
    753780
     781        bool get_lvalue() const final;
     782
    754783        CompoundStmt * get_statements() const { return statements; }
    755784        StmtExpr * set_statements( CompoundStmt * newValue ) { statements = newValue; return this; }
     
    761790        std::list< Expression * > & get_dtors() { return dtors; }
    762791
    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;
     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;
    767797};
    768798
     
    788818        int get_id() const { return id; }
    789819
    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;
     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;
    794825
    795826private:
     
    822853        std::list<InitAlternative> & get_initAlts() { return initAlts; }
    823854
    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;
     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;
    828860};
    829861
     
    843875        InitExpr * set_designation( Designation * newValue ) { designation = newValue; return this; }
    844876
    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;
     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;
    849882};
    850883
     
    853886public:
    854887        Expression * expr;
    855         BaseSyntaxNode * deleteStmt;
    856 
    857         DeletedExpr( Expression * expr, BaseSyntaxNode * deleteStmt );
     888        Declaration * deleteStmt;
     889
     890        DeletedExpr( Expression * expr, Declaration * deleteStmt );
    858891        DeletedExpr( const DeletedExpr & other );
    859892        ~DeletedExpr();
    860893
    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;
     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.
     902class DefaultArgExpr : public Expression {
     903public:
     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;
    865915};
    866916
     
    887937        virtual ~GenericExpr();
    888938
    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;
     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;
    893944};
    894945
  • src/SynTree/FunctionDecl.cc

    r7951100 rb067d9b  
    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

    r7951100 rb067d9b  
    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

    r7951100 rb067d9b  
    3838
    3939        virtual Designation * clone() const override { return new Designation( *this ); };
    40         virtual void accept( Visitor &v ) override { v.visit( this ); }
     40        virtual void accept( Visitor & v ) override { v.visit( this ); }
     41        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    4142        virtual Designation * acceptMutator( Mutator &m ) override { return m.mutate( this ); }
    4243        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    5253        virtual ~Initializer();
    5354
    54         bool get_maybeConstructed() { return maybeConstructed; }
     55        bool get_maybeConstructed() const { return maybeConstructed; }
    5556
    5657        virtual Initializer *clone() const override = 0;
    57         virtual void accept( Visitor &v ) override = 0;
     58        virtual void accept( Visitor & v ) override = 0;
     59        virtual void accept( Visitor & v ) const override = 0;
    5860        virtual Initializer *acceptMutator( Mutator &m ) override = 0;
    5961        virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
     
    7678
    7779        virtual SingleInit *clone() const override { return new SingleInit( *this); }
    78         virtual void accept( Visitor &v ) override { v.visit( this ); }
     80        virtual void accept( Visitor & v ) override { v.visit( this ); }
     81        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    7982        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    8083        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    104107
    105108        virtual ListInit *clone() const override { return new ListInit( *this ); }
    106         virtual void accept( Visitor &v ) override { v.visit( this ); }
     109        virtual void accept( Visitor & v ) override { v.visit( this ); }
     110        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    107111        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    108112        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     
    133137
    134138        ConstructorInit *clone() const override { return new ConstructorInit( *this ); }
    135         virtual void accept( Visitor &v ) override { v.visit( this ); }
     139        virtual void accept( Visitor & v ) override { v.visit( this ); }
     140        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    136141        virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    137142        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
  • src/SynTree/Label.h

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

    r7951100 rb067d9b  
    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 Jul 24 16:31:00 2017
    13 // Update Count     : 16
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:37:46 2019
     13// Update Count     : 17
    1414//
    1515#pragma once
     
    5252        virtual Statement * mutate( FinallyStmt * catchStmt ) = 0;
    5353        virtual Statement * mutate( WaitForStmt * waitforStmt ) = 0;
    54         virtual Statement * mutate( WithStmt * withStmt ) = 0;
     54        virtual Declaration * 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;
    7776        virtual Expression * mutate( LogicalExpr * logicalExpr ) = 0;
    7877        virtual Expression * mutate( ConditionalExpr * conditionalExpr ) = 0;
     
    9392        virtual Expression * mutate( InitExpr  * initExpr ) = 0;
    9493        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;
    102103        virtual Type * mutate( FunctionType * functionType ) = 0;
    103104        virtual Type * mutate( StructInstType * aggregateUseType ) = 0;
     
    112113        virtual Type * mutate( ZeroType * zeroType ) = 0;
    113114        virtual Type * mutate( OneType * oneType ) = 0;
     115        virtual Type * mutate( GlobalScopeType * globalType ) = 0;
    114116
    115117        virtual Designation * mutate( Designation * designation ) = 0 ;
     
    117119        virtual Initializer * mutate( ListInit * listInit ) = 0 ;
    118120        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

    r7951100 rb067d9b  
    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

    r7951100 rb067d9b  
    7676bool StructInstType::isComplete() const { return baseStruct ? baseStruct->has_body() : false; }
    7777
    78 AggregateDecl * StructInstType::getAggr() { return baseStruct; }
     78AggregateDecl * StructInstType::getAggr() const { 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() { return baseUnion; }
     121AggregateDecl * UnionInstType::getAggr() const { 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
     154AggregateDecl * EnumInstType::getAggr() const { return baseEnum; }
     155
    154156void EnumInstType::print( std::ostream &os, Indenter indent ) const {
    155157        using std::endl;
     
    158160        else {
    159161                Type::print( os, indent );
    160                 os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body() << " ";
     162                os << "instance of " << typeString() << " " << name << " with body " << baseEnum->has_body();
    161163        } // if
    162164}
     
    203205
    204206        Type::print( os, indent );
    205         os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type) ";
     207        os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type)";
    206208        if ( ! parameters.empty() ) {
    207209                os << endl << indent << "... with parameters" << endl;
  • src/SynTree/Statement.cc

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

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar  8 14:53:02 2018
    13 // Update Count     : 78
     12// Last Modified On : Tue Mar 12 09:01:53 2019
     13// Update Count     : 83
    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 Statement *acceptMutator( Mutator &m ) override = 0;
    48         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 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;
    4950};
    5051
     
    5556        CompoundStmt();
    5657        CompoundStmt( std::list<Statement *> stmts );
    57         CompoundStmt( const CompoundStmt &other );
     58        CompoundStmt( const CompoundStmt & other );
    5859        virtual ~CompoundStmt();
    5960
     
    6263        void push_front( Statement * stmt ) { kids.push_front( stmt ); }
    6364
    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;
     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;
    6870};
    6971
     
    7274        NullStmt( const std::list<Label> & labels = {} );
    7375
    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;
     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;
    7881};
    7982
    8083class ExprStmt : public Statement {
    8184  public:
    82         Expression *expr;
    83 
    84         ExprStmt( Expression *expr );
    85         ExprStmt( const ExprStmt &other );
     85        Expression * expr;
     86
     87        ExprStmt( Expression * expr );
     88        ExprStmt( const ExprStmt & other );
    8689        virtual ~ExprStmt();
    8790
    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;
     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;
    9599};
    96100
     
    98102  public:
    99103        bool voltile;
    100         Expression *instruction;
     104        Expression * instruction;
    101105        std::list<Expression *> output, input;
    102106        std::list<ConstantExpr *> clobber;
    103107        std::list<Label> gotolabels;
    104108
    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 );
     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 );
    107111        virtual ~AsmStmt();
    108112
     
    114118        void set_output( const std::list<Expression *> & newValue ) { output = newValue; }
    115119        std::list<Expression *> & get_input() { return input; }
    116         void set_input( const std::list<Expression *> &newValue ) { input = newValue; }
     120        void set_input( const std::list<Expression *> & newValue ) { input = newValue; }
    117121        std::list<ConstantExpr *> & get_clobber() { return clobber; }
    118         void set_clobber( const std::list<ConstantExpr *> &newValue ) { clobber = newValue; }
     122        void set_clobber( const std::list<ConstantExpr *> & newValue ) { clobber = newValue; }
    119123        std::list<Label> & get_gotolabels() { return gotolabels; }
    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;
     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;
    126131};
    127132
     
    133138        virtual ~DirectiveStmt(){}
    134139
    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;
     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;
    139145};
    140146
    141147class IfStmt : public Statement {
    142148  public:
    143         Expression *condition;
    144         Statement *thenPart;
    145         Statement *elsePart;
     149        Expression * condition;
     150        Statement * thenPart;
     151        Statement * elsePart;
    146152        std::list<Statement *> initialization;
    147153
    148         IfStmt( Expression *condition, Statement *thenPart, Statement *elsePart,
     154        IfStmt( Expression * condition, Statement * thenPart, Statement * elsePart,
    149155                        std::list<Statement *> initialization = std::list<Statement *>() );
    150         IfStmt( const IfStmt &other );
     156        IfStmt( const IfStmt & other );
    151157        virtual ~IfStmt();
    152158
    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;
     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;
    165172};
    166173
     
    170177        std::list<Statement *> statements;
    171178
    172         SwitchStmt( Expression *condition, const std::list<Statement *> &statements );
    173         SwitchStmt( const SwitchStmt &other );
     179        SwitchStmt( Expression * condition, const std::list<Statement *> & statements );
     180        SwitchStmt( const SwitchStmt & other );
    174181        virtual ~SwitchStmt();
    175182
    176         Expression *get_condition() { return condition; }
    177         void set_condition( Expression *newValue ) { condition = newValue; }
     183        Expression * get_condition() { return condition; }
     184        void set_condition( Expression * newValue ) { condition = newValue; }
    178185
    179186        std::list<Statement *> & get_statements() { return statements; }
    180187
    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;
     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;
    186194
    187195};
     
    192200        std::list<Statement *> stmts;
    193201
    194         CaseStmt( Expression *conditions, const std::list<Statement *> &stmts, bool isdef = false ) throw (SemanticErrorException);
    195         CaseStmt( const CaseStmt &other );
     202        CaseStmt( Expression * conditions, const std::list<Statement *> & stmts, bool isdef = false ) throw (SemanticErrorException);
     203        CaseStmt( const CaseStmt & other );
    196204        virtual ~CaseStmt();
    197205
     
    201209        void set_default(bool b) { _isDefault = b; }
    202210
    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;
     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;
    214223  private:
    215224        bool _isDefault;
     
    218227class WhileStmt : public Statement {
    219228  public:
    220         Expression *condition;
    221         Statement *body;
     229        Expression * condition;
     230        Statement * body;
    222231        std::list<Statement *> initialization;
    223232        bool isDoWhile;
    224233
    225         WhileStmt( Expression *condition,
    226                Statement *body, std::list<Statement *> & initialization, bool isDoWhile = false );
    227         WhileStmt( const WhileStmt &other );
     234        WhileStmt( Expression * condition, Statement * body, std::list<Statement *> & initialization, bool isDoWhile = false );
     235        WhileStmt( const WhileStmt & other );
    228236        virtual ~WhileStmt();
    229237
    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; }
     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; }
    234242        bool get_isDoWhile() { return isDoWhile; }
    235243        void set_isDoWhile( bool newValue ) { isDoWhile = newValue; }
    236244
    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;
     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;
    241250};
    242251
     
    244253  public:
    245254        std::list<Statement *> initialization;
    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 );
     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 );
    253261        virtual ~ForStmt();
    254262
    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;
     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;
    267276};
    268277
     
    274283        const Label originalTarget;
    275284        Label target;
    276         Expression *computedTarget;
     285        Expression * computedTarget;
    277286        Type type;
    278287
    279288        BranchStmt( Label target, Type ) throw (SemanticErrorException);
    280         BranchStmt( Expression *computedTarget, Type ) throw (SemanticErrorException);
     289        BranchStmt( Expression * computedTarget, Type ) throw (SemanticErrorException);
    281290
    282291        Label get_originalTarget() { return originalTarget; }
     
    284293        void set_target( Label newValue ) { target = newValue; }
    285294
    286         Expression *get_computedTarget() { return computedTarget; }
     295        Expression * get_computedTarget() { return computedTarget; }
    287296        void set_target( Expression * newValue ) { computedTarget = newValue; }
    288297
    289298        Type get_type() { return type; }
    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;
     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;
    296306  private:
    297         static const char *brType[];
     307        static const char * brType[];
    298308};
    299309
    300310class ReturnStmt : public Statement {
    301311  public:
    302         Expression *expr;
    303 
    304         ReturnStmt( Expression *expr );
    305         ReturnStmt( const ReturnStmt &other );
     312        Expression * expr;
     313
     314        ReturnStmt( Expression * expr );
     315        ReturnStmt( const ReturnStmt & other );
    306316        virtual ~ReturnStmt();
    307317
    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;
     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;
    315326};
    316327
     
    324335
    325336        ThrowStmt( Kind kind, Expression * expr, Expression * target = nullptr );
    326         ThrowStmt( const ThrowStmt &other );
     337        ThrowStmt( const ThrowStmt & other );
    327338        virtual ~ThrowStmt();
    328339
     
    333344        void set_target( Expression * newTarget ) { target = newTarget; }
    334345
    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;
     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;
    339351};
    340352
     
    345357        FinallyStmt * finallyBlock;
    346358
    347         TryStmt( CompoundStmt *tryBlock, std::list<CatchStmt *> &handlers, FinallyStmt *finallyBlock = 0 );
    348         TryStmt( const TryStmt &other );
     359        TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = 0 );
     360        TryStmt( const TryStmt & other );
    349361        virtual ~TryStmt();
    350362
    351         CompoundStmt *get_block() const { return block; }
    352         void set_block( CompoundStmt *newValue ) { block = newValue; }
     363        CompoundStmt * get_block() const { return block; }
     364        void set_block( CompoundStmt * newValue ) { block = newValue; }
    353365        std::list<CatchStmt *>& get_catchers() { return handlers; }
    354366
    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;
     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;
    362375};
    363376
     
    367380
    368381        const Kind kind;
    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 );
     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 );
    376389        virtual ~CatchStmt();
    377390
    378391        Kind get_kind() { return kind; }
    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;
     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;
    390404};
    391405
    392406class FinallyStmt : public Statement {
    393407  public:
    394         CompoundStmt *block;
    395 
    396         FinallyStmt( CompoundStmt *block );
    397         FinallyStmt( const FinallyStmt &other );
     408        CompoundStmt * block;
     409
     410        FinallyStmt( CompoundStmt * block );
     411        FinallyStmt( const FinallyStmt & other );
    398412        virtual ~FinallyStmt();
    399413
    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;
     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;
    407422};
    408423
     
    438453        } orelse;
    439454
    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 
    447 class WithStmt : public Statement {
    448 public:
    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 ); }
    457         virtual void accept( Visitor & v ) override { v.visit( this ); }
    458         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    459         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    460 };
     455        virtual WaitForStmt * clone() const override { return new WaitForStmt( *this ); }
     456        virtual void accept( Visitor & v ) override { v.visit( this ); }
     457        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     458        virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
     459        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// };
    461478
    462479
     
    464481class DeclStmt : public Statement {
    465482  public:
    466         Declaration *decl;
    467 
    468         DeclStmt( Declaration *decl );
    469         DeclStmt( const DeclStmt &other );
     483        Declaration * decl;
     484
     485        DeclStmt( Declaration * decl );
     486        DeclStmt( const DeclStmt & other );
    470487        virtual ~DeclStmt();
    471488
    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.
     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.
    485502class ImplicitCtorDtorStmt : public Statement {
    486503  public:
     
    492509        virtual ~ImplicitCtorDtorStmt();
    493510
    494         Statement *get_callStmt() const { return callStmt; }
     511        Statement * get_callStmt() const { return callStmt; }
    495512        void set_callStmt( Statement * newValue ) { callStmt = newValue; }
    496513
    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;
     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;
    501519};
    502520
  • src/SynTree/SynTree.h

    r7951100 rb067d9b  
    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 Jul 24 16:54:00 2017
    13 // Update Count     : 11
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:37:45 2019
     13// Update Count     : 12
    1414//
    1515
     
    3434class NamedTypeDecl;
    3535class TypeDecl;
    36 class FtypeDecl;
    37 class DtypeDecl;
    3836class TypedefDecl;
    3937class AsmDecl;
     
    8179class OffsetofExpr;
    8280class OffsetPackExpr;
    83 class AttrExpr;
    8481class LogicalExpr;
    8582class ConditionalExpr;
     
    9087class ConstructorExpr;
    9188class CompoundLiteralExpr;
    92 class UntypedValofExpr;
    9389class RangeExpr;
    9490class UntypedTupleExpr;
     
    10197class InitExpr;
    10298class DeletedExpr;
     99class DefaultArgExpr;
    103100class GenericExpr;
    104101
     
    109106class ArrayType;
    110107class ReferenceType;
     108class QualifiedType;
    111109class FunctionType;
    112110class ReferenceToType;
     
    122120class ZeroType;
    123121class OneType;
     122class GlobalScopeType;
    124123
    125124class Designation;
     
    128127class ListInit;
    129128class ConstructorInit;
    130 
    131 class Subrange;
    132129
    133130//template <class T>    // emulate a union with templates?
  • src/SynTree/TupleExpr.cc

    r7951100 rb067d9b  
    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 : Fri Mar 17 09:42:29 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Aug 14 14:34:00 2019
     13// Update Count     : 5
    1414//
    1515
     
    5757}
    5858
     59bool TupleExpr::get_lvalue() const {
     60        return false;
     61}
     62
    5963void TupleExpr::print( std::ostream &os, Indenter indent ) const {
    6064        os << "Tuple:" << std::endl;
     
    6771        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() );
    6872        set_result( (*std::next( type->get_types().begin(), index ))->clone() );
    69         // like MemberExpr, TupleIndexExpr is always an lvalue
    70         get_result()->set_lvalue( true );
    7173}
    7274
     
    7678TupleIndexExpr::~TupleIndexExpr() {
    7779        delete tuple;
     80}
     81
     82bool TupleIndexExpr::get_lvalue() const {
     83        return tuple->get_lvalue();
    7884}
    7985
     
    105111}
    106112
     113TupleAssignExpr::TupleAssignExpr(
     114        StmtExpr * s )
     115: Expression(), stmtExpr(s) {
     116}
     117
     118
    107119TupleAssignExpr::~TupleAssignExpr() {
    108120        delete stmtExpr;
  • src/SynTree/Type.cc

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 15:16:32 2017
    13 // Update Count     : 38
     12// Last Modified On : Sun Aug  4 21:05:07 2019
     13// Update Count     : 45
    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",
    4839        "__int128",
    4940        "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",
    5057        "__float80",
    51         "__float128"
     58        "_Float128",
     59        "_Float128 _Complex",
     60        "__float128",
     61        "long double",
     62        "long double _Complex",
     63        //"long double _Imaginary",
     64        "_Float128x",
     65        "_Float128x _Complex",
    5266};
    5367static_assert(
    54         sizeof(BasicType::typeNames)/sizeof(BasicType::typeNames[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
     68        sizeof(BasicType::typeNames) / sizeof(BasicType::typeNames[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
    5569        "Each basic type name should have a corresponding kind enum value"
    5670);
     
    6983
    7084// These must remain in the same order as the corresponding bit fields.
    71 const char * Type::FuncSpecifiersNames[] = { "inline", "fortran", "_Noreturn" };
     85const char * Type::FuncSpecifiersNames[] = { "inline", "_Noreturn", "fortran" };
    7286const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "_Thread_local" };
    73 const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic" };
     87const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "mutex", "_Atomic" };
    7488
    7589Type * Type::stripDeclarator() {
     
    86100}
    87101
     102const 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
    88109int Type::referenceDepth() const { return 0; }
    89110
    90111TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
    91112
    92 void Type::print( std::ostream &os, Indenter indent ) const {
     113void Type::print( std::ostream & os, Indenter indent ) const {
    93114        if ( ! forall.empty() ) {
    94115                os << "forall" << std::endl;
     
    105126}
    106127
     128
     129QualifiedType::QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child ) : Type( tq, {} ), parent( parent ), child( child ) {
     130}
     131
     132QualifiedType::QualifiedType( const QualifiedType & other ) : Type( other ), parent( maybeClone( other.parent ) ), child( maybeClone( other.child ) ) {
     133}
     134
     135QualifiedType::~QualifiedType() {
     136        delete parent;
     137        delete child;
     138}
     139
     140void 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
     150GlobalScopeType::GlobalScopeType() : Type( Type::Qualifiers(), {} ) {}
     151
     152void GlobalScopeType::print( std::ostream & os, Indenter ) const {
     153        os << "Global Scope Type" << endl;
     154}
     155
     156
    107157// Empty Variable declarations:
    108158const Type::FuncSpecifiers noFuncSpecifiers;
  • src/SynTree/Type.h

    r7951100 rb067d9b  
    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 : Mon Sep 25 14:14:01 2017
    13 // Update Count     : 154
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Sep  4 09:58:00 2019
     13// Update Count     : 170
    1414//
    1515
     
    102102        }; // StorageClasses
    103103
    104         enum { Const = 1 << 0, Restrict = 1 << 1, Volatile = 1 << 2, Lvalue = 1 << 3, Mutex = 1 << 4, Atomic = 1 << 5, NumTypeQualifier = 6 };
     104        enum { Const = 1 << 0, Restrict = 1 << 1, Volatile = 1 << 2, Mutex = 1 << 3, Atomic = 1 << 4, NumTypeQualifier = 5 };
    105105        static const char * QualifiersNames[];
    106106        union Qualifiers {
    107                 enum { Mask = ~(Restrict | Lvalue) };
     107                enum { Mask = ~Restrict };
    108108                unsigned int val;
    109109                struct {
     
    111111                        bool is_restrict : 1;
    112112                        bool is_volatile : 1;
    113                         bool is_lvalue : 1;
    114113                        bool is_mutex : 1;
    115114                        bool is_atomic : 1;
     
    131130                bool operator>( Qualifiers other ) const { return *this != other && *this >= other; }
    132131                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                }
    133138        }; // Qualifiers
    134139
     
    144149
    145150        Qualifiers & get_qualifiers() { return tq; }
    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; }
     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; }
    152156        void set_const( bool newValue ) { tq.is_const = newValue; }
    153157        void set_volatile( bool newValue ) { tq.is_volatile = newValue; }
    154158        void set_restrict( bool newValue ) { tq.is_restrict = newValue; }
    155         void set_lvalue( bool newValue ) { tq.is_lvalue = newValue; }
    156159        void set_mutex( bool newValue ) { tq.is_mutex = newValue; }
    157160        void set_atomic( bool newValue ) { tq.is_atomic = newValue; }
     
    172175        /// return type without outer references
    173176        Type * stripReferences();
     177        const Type * stripReferences() const;
    174178
    175179        /// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types)
     
    178182        virtual bool isComplete() const { return true; }
    179183
    180         virtual AggregateDecl * getAggr() { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
     184        virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
    181185
    182186        virtual TypeSubstitution genericSubstitution() const;
     
    184188        virtual Type *clone() const = 0;
    185189        virtual void accept( Visitor & v ) = 0;
     190        virtual void accept( Visitor & v ) const = 0;
    186191        virtual Type *acceptMutator( Mutator & m ) = 0;
    187192        virtual void print( std::ostream & os, Indenter indent = {} ) const;
     
    201206        virtual VoidType *clone() const override { return new VoidType( *this ); }
    202207        virtual void accept( Visitor & v ) override { v.visit( this ); }
     208        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    203209        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    204210        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    207213class BasicType : public Type {
    208214  public:
     215        // GENERATED START, DO NOT EDIT
     216        // GENERATED BY BasicTypes-gen.cc
    209217        enum Kind {
    210218                Bool,
     
    220228                LongLongSignedInt,
    221229                LongLongUnsignedInt,
    222                 Float,
    223                 Double,
    224                 LongDouble,
    225                 FloatComplex,
    226                 DoubleComplex,
    227                 LongDoubleComplex,
    228                 FloatImaginary,
    229                 DoubleImaginary,
    230                 LongDoubleImaginary,
    231230                SignedInt128,
    232231                UnsignedInt128,
    233                 Float80,
    234                 Float128,
     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,
    235254                NUMBER_OF_BASIC_TYPES
    236255        } kind;
     256        // GENERATED END
    237257
    238258        static const char *typeNames[];                                         // string names for basic types, MUST MATCH with Kind
     
    240260        BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    241261
    242         Kind get_kind() { return kind; }
     262        Kind get_kind() const { return kind; }
    243263        void set_kind( Kind newValue ) { kind = newValue; }
    244264
    245265        virtual BasicType *clone() const override { return new BasicType( *this ); }
    246266        virtual void accept( Visitor & v ) override { v.visit( this ); }
     267        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    247268        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    248269        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    280301        virtual PointerType *clone() const override { return new PointerType( *this ); }
    281302        virtual void accept( Visitor & v ) override { v.visit( this ); }
     303        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    282304        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    283305        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    311333        virtual ArrayType *clone() const override { return new ArrayType( *this ); }
    312334        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
     340class QualifiedType : public Type {
     341public:
     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 ); }
    313352        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    314353        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    337376        virtual ReferenceType *clone() const override { return new ReferenceType( *this ); }
    338377        virtual void accept( Visitor & v ) override { v.visit( this ); }
     378        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    339379        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    340380        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    366406        virtual FunctionType *clone() const override { return new FunctionType( *this ); }
    367407        virtual void accept( Visitor & v ) override { v.visit( this ); }
     408        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    368409        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    369410        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    416457        virtual bool isComplete() const override;
    417458
    418         virtual AggregateDecl * getAggr() override;
     459        virtual AggregateDecl * getAggr() const override;
    419460
    420461        virtual TypeSubstitution genericSubstitution() const override;
     
    426467        virtual StructInstType *clone() const override { return new StructInstType( *this ); }
    427468        virtual void accept( Visitor & v ) override { v.visit( this ); }
     469        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    428470        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    429471
     
    453495        virtual bool isComplete() const override;
    454496
    455         virtual AggregateDecl * getAggr() override;
     497        virtual AggregateDecl * getAggr() const override;
    456498
    457499        virtual TypeSubstitution genericSubstitution() const override;
     
    463505        virtual UnionInstType *clone() const override { return new UnionInstType( *this ); }
    464506        virtual void accept( Visitor & v ) override { v.visit( this ); }
     507        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    465508        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    466509
     
    486529        virtual bool isComplete() const override;
    487530
     531        virtual AggregateDecl * getAggr() const override;
     532
    488533        virtual EnumInstType *clone() const override { return new EnumInstType( *this ); }
    489534        virtual void accept( Visitor & v ) override { v.visit( this ); }
     535        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    490536        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    491537
     
    511557        virtual TraitInstType *clone() const override { return new TraitInstType( *this ); }
    512558        virtual void accept( Visitor & v ) override { v.visit( this ); }
     559        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    513560        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    514561  private:
     
    538585        virtual TypeInstType *clone() const override { return new TypeInstType( *this ); }
    539586        virtual void accept( Visitor & v ) override { v.visit( this ); }
     587        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    540588        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    541589        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    575623        virtual TupleType *clone() const override { return new TupleType( *this ); }
    576624        virtual void accept( Visitor & v ) override { v.visit( this ); }
     625        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    577626        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    578627        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    581630class TypeofType : public Type {
    582631  public:
    583         Expression *expr;
    584 
    585         TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     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 * >() );
    586638        TypeofType( const TypeofType& );
    587639        virtual ~TypeofType();
     
    594646        virtual TypeofType *clone() const override { return new TypeofType( *this ); }
    595647        virtual void accept( Visitor & v ) override { v.visit( this ); }
     648        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    596649        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    597650        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    623676        virtual AttrType *clone() const override { return new AttrType( *this ); }
    624677        virtual void accept( Visitor & v ) override { v.visit( this ); }
     678        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    625679        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    626680        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    637691        virtual VarArgsType *clone() const override { return new VarArgsType( *this ); }
    638692        virtual void accept( Visitor & v ) override { v.visit( this ); }
     693        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    639694        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    640695        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    649704        virtual ZeroType *clone() const override { return new ZeroType( *this ); }
    650705        virtual void accept( Visitor & v ) override { v.visit( this ); }
     706        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    651707        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    652708        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    661717        virtual OneType *clone() const override { return new OneType( *this ); }
    662718        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
     724class 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 ); }
    663731        virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    664732        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
  • src/SynTree/TypeSubstitution.cc

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

    r7951100 rb067d9b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:52:24 2017
    13 // Update Count     : 3
     12// Last Modified On : Tue Apr 30 22:52:47 2019
     13// Update Count     : 9
    1414//
    1515
     
    1919#include <iosfwd>                  // for ostream
    2020#include <list>                    // for list<>::iterator, _List_iterator
    21 #include <map>                     // for _Rb_tree_iterator, map, map<>::val...
    22 #include <set>                     // for set
     21#include <unordered_map>
     22#include <unordered_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 );
    42         template< typename SynTreeClass > int applyFree( SynTreeClass *&input );
     41        template< typename SynTreeClass > int apply( SynTreeClass *&input ) const;
     42        template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const;
    4343
    4444        void add( std::string formalType, Type *actualType );
     
    4848        bool empty() const;
    4949
     50        void addVar( std::string formalExpr, Expression *actualExpr );
     51
    5052        template< typename FormalIterator, typename ActualIterator >
    5153        void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
     
    5658
    5759        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
    58         static TypeSubstitution * newFromExpr( Expression * expr, TypeSubstitution * env );
     60        static TypeSubstitution * newFromExpr( Expression * expr, const TypeSubstitution * env );
    5961
    6062        void normalize();
     
    7880        friend class PassVisitor;
    7981
    80         typedef std::map< std::string, Type* > TypeEnvType;
    81         typedef std::map< std::string, Expression* > VarEnvType;
     82        typedef std::unordered_map< std::string, Type * > TypeEnvType;
     83        typedef std::unordered_map< std::string, Expression * > VarEnvType;
    8284        TypeEnvType typeEnv;
    8385        VarEnvType varEnv;
     
    8991        auto begin() const -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
    9092        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(); }
    9198};
    9299
     
    98105        ActualIterator actualIt = actualBegin;
    99106        for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) {
    100                 if ( TypeDecl *formal = dynamic_cast< TypeDecl* >( *formalIt ) ) {
    101                         if ( TypeExpr *actual = dynamic_cast< TypeExpr* >( *actualIt ) ) {
     107                if ( TypeDecl *formal = dynamic_cast< TypeDecl * >( *formalIt ) ) {
     108                        if ( TypeExpr *actual = dynamic_cast< TypeExpr * >( *actualIt ) ) {
    102109                                if ( formal->get_name() != "" ) {
    103110                                        TypeEnvType::iterator i = typeEnv.find( formal->get_name() );
     
    130137// definitition must happen after PassVisitor is included so that WithGuards can be used
    131138struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
    132                 Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
     139                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    133140
    134141                Type * postmutate( TypeInstType * aggregateUseType );
     
    143150                void premutate( UnionInstType * aggregateUseType );
    144151
    145                 TypeSubstitution & sub;
     152                const TypeSubstitution & sub;
    146153                int subCount = 0;
    147154                bool freeOnly;
    148                 typedef std::set< std::string > BoundVarsType;
     155                typedef std::unordered_set< std::string > BoundVarsType;
    149156                BoundVarsType boundVars;
    150157};
    151158
    152159template< typename SynTreeClass >
    153 int TypeSubstitution::apply( SynTreeClass *&input ) {
     160int TypeSubstitution::apply( SynTreeClass *&input ) const {
    154161        assert( input );
    155162        PassVisitor<Substituter> sub( *this, false );
     
    163170
    164171template< typename SynTreeClass >
    165 int TypeSubstitution::applyFree( SynTreeClass *&input ) {
     172int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
    166173        assert( input );
    167174        PassVisitor<Substituter> sub( *this, true );
  • src/SynTree/TypeofType.cc

    r7951100 rb067d9b  
    2323class Attribute;
    2424
    25 TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), expr( expr ) {
    26 }
     25TypeofType::TypeofType( const Type::Qualifiers &tq, Expression *expr,
     26        const std::list< Attribute * > & attributes )
     27: Type( tq, attributes ), expr( expr ), is_basetypeof(false) {}
    2728
    28 TypeofType::TypeofType( const TypeofType &other ) : Type( other ), expr( maybeClone( other.expr ) ) {
    29 }
     29TypeofType::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
     33TypeofType::TypeofType( const TypeofType &other )
     34: Type( other ), expr( maybeClone( other.expr ) ), is_basetypeof( other.is_basetypeof ) {}
    3035
    3136TypeofType::~TypeofType() {
     
    3540void TypeofType::print( std::ostream &os, Indenter indent ) const {
    3641        Type::print( os, indent );
     42        if ( is_basetypeof ) { os << "base-"; }
    3743        os << "type-of expression ";
    3844        if ( expr ) {
  • src/SynTree/Visitor.h

    r7951100 rb067d9b  
    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 Jul 24 16:28:00 2017
    13 // Update Count     : 13
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:21:49 2019
     13// Update Count     : 14
    1414//
    1515
     
    2727        // of the given syntax node, but performs no other action.
    2828
    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;
    39 
    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;
    60 
    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;
    98 
    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;
    116 
    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;
    121 
    122         virtual void visit( Subrange * subrange ) = 0;
    123 
    124         virtual void visit( Constant * constant ) = 0;
    125 
    126         virtual void visit( Attribute * attribute ) = 0;
     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;
     49
     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;
     90
     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;
     165
     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;
     204
     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;
     213
     214        virtual void visit( Constant * node ) { visit( const_cast<const Constant *>(node) ); }
     215        virtual void visit( const Constant * constant ) = 0;
     216
     217        virtual void visit( Attribute * node ) { visit( const_cast<const Attribute *>(node) ); }
     218        virtual void visit( const Attribute * attribute ) = 0;
    127219};
    128220
    129221template< typename TreeType, typename VisitorType >
    130 inline void maybeAccept( TreeType *tree, VisitorType &visitor ) {
     222inline void maybeAccept( TreeType * tree, VisitorType & visitor ) {
    131223        if ( tree ) {
    132224                tree->accept( visitor );
     
    134226}
    135227
     228template< typename TreeType, typename VisitorType >
     229inline void maybeAccept( const TreeType * tree, VisitorType & visitor ) {
     230        if ( tree ) {
     231                tree->accept( visitor );
     232        }
     233}
     234
    136235template< typename Container, typename VisitorType >
    137 inline void acceptAll( Container &container, VisitorType &visitor ) {
     236inline void acceptAll( Container & container, VisitorType & visitor ) {
    138237        SemanticErrorException errors;
    139         for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
     238        for ( auto * i : container ) {
    140239                try {
    141                         if ( *i ) {
    142                                 (*i)->accept( visitor );
     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
     252template< typename Container, typename VisitorType >
     253inline 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 );
    143259                        }
    144260                } catch( SemanticErrorException &e ) {
  • src/SynTree/module.mk

    r7951100 rb067d9b  
    1515###############################################################################
    1616
    17 SRC += 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
     17SRC_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
    5152
     53SRC += $(SRC_SYNTREE)
     54SRCDEMANGLE += $(SRC_SYNTREE)
  • src/Tuples/Explode.cc

    r7951100 rb067d9b  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Wed Nov 9 13:20:24 2016
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jun 12 16:40:00 2016
     13// Update Count     : 3
    1414//
    1515
     
    106106                return expr;
    107107        }
     108
     109namespace {
     110
     111// Remove one level of reference from a reference type.
     112const 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
     121struct 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
     179const 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
    108188} // namespace Tuples
    109189
  • src/Tuples/Explode.h

    r7951100 rb067d9b  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:55:16 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 17 14:36:00 2019
     13// Update Count     : 4
    1414//
    1515
     
    1919#include <utility>                      // for forward
    2020
     21#include "AST/Expr.hpp"
    2122#include "ResolvExpr/Alternative.h"     // for Alternative, AltList
     23#include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
    2224#include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
     25#include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
    2326#include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
    2427#include "SynTree/Type.h"               // for TupleType, Type
    2528#include "Tuples.h"                     // for maybeImpure
     29
     30namespace ast {
     31        class SymbolTable;
     32}
    2633
    2734namespace SymTab {
     
    4451        template<typename OutputIterator>
    4552        void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
     53                        const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
    4654                        const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
    47                 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };
     55                *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
    4856        }
    4957
    5058        /// Append alternative to an ExplodedActual
    5159        static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
    52                         const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
     60                        const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
     61                        const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    5362                ea.exprs.emplace_back( expr );
    54                 /// xxx -- merge environment, cost?
     63                /// xxx -- merge environment, openVars, need, cost?
    5564        }
    5665
     
    6877                                        // distribute reference cast over all components
    6978                                        append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
    70                                                 alt.env, alt.cost, alt.cvtCost );
     79                                                alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost );
    7180                                }
    7281                                // 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)
     
    102111                } else {
    103112                        // atomic (non-tuple) type - output a clone of the expression in a new alternative
    104                         append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost );
     113                        append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need,
     114                                alt.cost, alt.cvtCost );
    105115                }
    106116        }
     
    127137                explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
    128138        }
     139
     140const ast::Expr * distributeReference( const ast::Expr * );
     141
     142/// Append candidate to an OutputIterator of Candidates.
     143template<typename OutputIterator>
     144void 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.
     156static 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.
     164static 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
     174template< typename Output >
     175void explodeRecursive(
     176        const ast::CastExpr *, const ResolvExpr::Candidate &,
     177        const ast::SymbolTable &, Output &&
     178) {
     179}
     180
     181/// helper function used by explode
     182template< typename Output >
     183void 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
     232template< typename Output >
     233void 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
     241template< typename Output >
     242void 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
    129251} // namespace Tuples
    130252
  • src/Tuples/TupleAssignment.cc

    r7951100 rb067d9b  
    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"
    2429#include "CodeGen/OperatorTable.h"
    2530#include "Common/PassVisitor.h"
    2631#include "Common/UniqueName.h"             // for UniqueName
    27 #include "Common/utility.h"                // for zipWith
     32#include "Common/utility.h"                // for splice, zipWith
    2833#include "Explode.h"                       // for explode
    2934#include "InitTweak/GenInit.h"             // for genCtorInit
     
    5156
    5257namespace Tuples {
    53         class TupleAssignSpotter {
     58        class TupleAssignSpotter_old {
    5459          public:
    5560                // dispatcher for Tuple (multiple and mass) assignment operations
    56                 TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
     61                TupleAssignSpotter_old( ResolvExpr::AlternativeFinder & );
    5762                void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );
    5863
     
    6267                struct Matcher {
    6368                  public:
    64                         Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
    65                                 ResolvExpr::AltList& rhs );
     69                        Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
     70                                const ResolvExpr::AltList& rhs );
    6671                        virtual ~Matcher() {}
     72
    6773                        virtual void match( std::list< Expression * > &out ) = 0;
    6874                        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
    6986                        ResolvExpr::AltList lhs, rhs;
    70                         TupleAssignSpotter &spotter;
     87                        TupleAssignSpotter_old &spotter;
    7188                        ResolvExpr::Cost baseCost;
    7289                        std::list< ObjectDecl * > tmpDecls;
    7390                        ResolvExpr::TypeEnvironment compositeEnv;
     91                        ResolvExpr::OpenVarSet openVars;
     92                        ResolvExpr::AssertionSet need;
    7493                };
    7594
    7695                struct MassAssignMatcher : public Matcher {
    7796                  public:
    78                         MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     97                        MassAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    7998                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    8099                        virtual void match( std::list< Expression * > &out );
     
    83102                struct MultipleAssignMatcher : public Matcher {
    84103                  public:
    85                         MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     104                        MultipleAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    86105                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    87106                        virtual void match( std::list< Expression * > &out );
     
    122141        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
    123142                                std::vector<ResolvExpr::AlternativeFinder> &args ) {
    124                 TupleAssignSpotter spotter( currentFinder );
     143                TupleAssignSpotter_old spotter( currentFinder );
    125144                spotter.spot( expr, args );
    126145        }
    127146
    128         TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
     147        TupleAssignSpotter_old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f )
    129148                : currentFinder(f) {}
    130149
    131         void TupleAssignSpotter::spot( UntypedExpr * expr,
     150        void TupleAssignSpotter_old::spot( UntypedExpr * expr,
    132151                        std::vector<ResolvExpr::AlternativeFinder> &args ) {
    133152                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
     
    210229        }
    211230
    212         void TupleAssignSpotter::match() {
     231        void TupleAssignSpotter_old::match() {
    213232                assert ( matcher != 0 );
    214233
     
    245264                }
    246265
    247                 // extract expressions from the assignment alternatives to produce a list of assignments that
    248                 // together form a single alternative
     266                // extract expressions from the assignment alternatives to produce a list of assignments
     267                // that together form a single alternative
    249268                std::list< Expression *> solved_assigns;
    250269                for ( ResolvExpr::Alternative & alt : current ) {
    251270                        solved_assigns.push_back( alt.expr->clone() );
    252                 }
    253                 // combine assignment environments into combined expression environment
    254                 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
     271                        matcher->combineState( alt );
     272                }
     273
    255274                // xxx -- was push_front
    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,
     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,
    262283                const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
    263284        : lhs(lhs), rhs(rhs), spotter(spotter),
    264285          baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
    265                 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );
    266                 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv );
     286                combineState( lhs );
     287                combineState( rhs );
    267288        }
    268289
     
    297318        };
    298319
    299         ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) {
     320        ObjectDecl * TupleAssignSpotter_old::Matcher::newObject( UniqueName & namer, Expression * expr ) {
    300321                assert( expr->result && ! expr->get_result()->isVoid() );
    301322                ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) );
     
    313334        }
    314335
    315         void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
     336        void TupleAssignSpotter_old::MassAssignMatcher::match( std::list< Expression * > &out ) {
    316337                static UniqueName lhsNamer( "__massassign_L" );
    317338                static UniqueName rhsNamer( "__massassign_R" );
     
    331352        }
    332353
    333         void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
     354        void TupleAssignSpotter_old::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
    334355                static UniqueName lhsNamer( "__multassign_L" );
    335356                static UniqueName rhsNamer( "__multassign_R" );
     
    361382                }
    362383        }
     384
     385namespace {
     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
     712void 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
    363720} // namespace Tuples
    364721
  • src/Tuples/TupleExpansion.cc

    r7951100 rb067d9b  
    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 : Wed Jun 21 17:35:04 2017
    13 // Update Count     : 19
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jul 19 14:39:00 2019
     13// Update Count     : 22
    1414//
    1515
     
    1717#include <cassert>                // for assert
    1818#include <list>                   // for list
    19 
     19#include <vector>
     20
     21#include "AST/CVQualifiers.hpp"
     22#include "AST/Expr.hpp"
     23#include "AST/Node.hpp"
     24#include "AST/Type.hpp"
    2025#include "Common/PassVisitor.h"   // for PassVisitor, WithDeclsToAdd, WithGu...
    2126#include "Common/ScopedMap.h"     // for ScopedMap
     
    5863                };
    5964
    60                 struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithTypeSubstitution {
     65                struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithConstTypeSubstitution {
    6166                        Type * postmutate( TupleType * tupleType );
    6267
     
    299304                // produce the TupleType which aggregates the types of the exprs
    300305                std::list< Type * > types;
    301                 Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Lvalue | Type::Atomic | Type::Mutex );
     306                Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic | Type::Mutex );
    302307                for ( Expression * expr : exprs ) {
    303308                        assert( expr->get_result() );
     
    314319                return new TupleType( qualifiers, types );
    315320        }
     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        }
    316342
    317343        TypeInstType * isTtype( Type * type ) {
     
    324350        }
    325351
     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
    326370        namespace {
    327371                /// 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
     
    329373                        ImpurityDetector( bool ignoreUnique ) : ignoreUnique( ignoreUnique ) {}
    330374
    331                         void previsit( ApplicationExpr * appExpr ) {
     375                        void previsit( const ApplicationExpr * appExpr ) {
    332376                                visit_children = false;
    333                                 if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
    334                                         if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
    335                                                 if ( function->get_name() == "*?" || function->get_name() == "?[?]" ) {
     377                                if ( const DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
     378                                        if ( function->linkage == LinkageSpec::Intrinsic ) {
     379                                                if ( function->name == "*?" || function->name == "?[?]" ) {
    336380                                                        // intrinsic dereference, subscript are pure, but need to recursively look for impurity
    337381                                                        visit_children = true;
     
    342386                                maybeImpure = true;
    343387                        }
    344                         void previsit( UntypedExpr * ) { maybeImpure = true; visit_children = false; }
    345                         void previsit( UniqueExpr * ) {
     388                        void previsit( const UntypedExpr * ) { maybeImpure = true; visit_children = false; }
     389                        void previsit( const UniqueExpr * ) {
    346390                                if ( ignoreUnique ) {
    347391                                        // bottom out at unique expression.
     
    358402        } // namespace
    359403
    360         bool maybeImpure( Expression * expr ) {
     404        bool maybeImpure( const Expression * expr ) {
    361405                PassVisitor<ImpurityDetector> detector( false );
    362406                expr->accept( detector );
     
    364408        }
    365409
    366         bool maybeImpureIgnoreUnique( Expression * expr ) {
     410        bool maybeImpureIgnoreUnique( const Expression * expr ) {
    367411                PassVisitor<ImpurityDetector> detector( true );
    368412                expr->accept( detector );
  • src/Tuples/Tuples.h

    r7951100 rb067d9b  
    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 : Sat Jul 22 09:55:00 2017
    13 // Update Count     : 16
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Jun 18 09:36:00 2019
     13// Update Count     : 18
    1414//
    1515
     
    1919#include <vector>
    2020
     21#include "AST/Fwd.hpp"
     22#include "AST/Node.hpp"
    2123#include "SynTree/Expression.h"
    2224#include "SynTree/Declaration.h"
     
    2426
    2527#include "ResolvExpr/AlternativeFinder.h"
     28#include "ResolvExpr/CandidateFinder.hpp"
    2629
    2730namespace Tuples {
    2831        // TupleAssignment.cc
    29         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, 
     32        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
    3033                std::vector< ResolvExpr::AlternativeFinder >& args );
    31        
     34        void handleTupleAssignment(
     35                ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
     36                std::vector< ResolvExpr::CandidateFinder > & args );
     37
    3238        // TupleExpansion.cc
    3339        /// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
     
    4248        /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
    4349        Type * makeTupleType( const std::list< Expression * > & exprs );
     50        const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs );
    4451
    4552        /// returns a TypeInstType if `type` is a ttype, nullptr otherwise
    4653        TypeInstType * isTtype( Type * type );
     54        const TypeInstType * isTtype( const Type * type );
     55        const ast::TypeInstType * isTtype( const ast::Type * type );
    4756
    4857        /// returns true if the expression may contain side-effects.
    49         bool maybeImpure( Expression * expr );
     58        bool maybeImpure( const Expression * expr );
     59        bool maybeImpure( const ast::Expr * expr );
    5060
    51         /// returns true if the expression may contain side-effect, ignoring the presence of unique expressions.
    52         bool maybeImpureIgnoreUnique( Expression * expr );
     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 );
    5365} // namespace Tuples
    5466
  • src/Tuples/module.mk

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

    r7951100 rb067d9b  
    147147                                //              )
    148148                                //      ),
    149                         new UntypedExpr( new NameExpr( "__cfa__virtual_cast" ), {
     149                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    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

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

    r7951100 rb067d9b  
    77// main.cc --
    88//
    9 // Author           : Richard C. Bilson
     9// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun  6 15:51:47 2018
    13 // Update Count     : 498
     12// Last Modified On : Fri Aug 23 06:50:08 2019
     13// Update Count     : 607
    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
    2019#include <cassert>                          // for assertf
    2120#include <cstdio>                           // for fopen, FILE, fclose, stdin
    2221#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>
    2627#include <iterator>                         // for back_inserter
    2728#include <list>                             // for list
    2829#include <string>                           // for char_traits, operator<<
    2930
     31#include "CompilationState.h"
    3032#include "../config.h"                      // for CFA_LIBDIR
    3133#include "CodeGen/FixMain.h"                // for FixMain
     
    3335#include "CodeGen/Generate.h"               // for generate
    3436#include "CodeTools/DeclStats.h"            // for printDeclStats
     37#include "CodeTools/ResolvProtoDump.h"      // for dumpAsResolvProto
    3538#include "CodeTools/TrackLoc.h"             // for fillLocations
    3639#include "Common/CompilerError.h"           // for CompilerError
    37 #include "Common/Heap.h"
     40#include "Common/Stats.h"
    3841#include "Common/PassVisitor.h"
    3942#include "Common/SemanticError.h"           // for SemanticError
     
    6164#include "Virtual/ExpandCasts.h"            // for expandCasts
    6265
     66
    6367using namespace std;
    6468
    65 #define PASS(name, pass)                   \
     69static 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 )                  \
    6687        if ( errorp ) { cerr << name << endl; } \
    67         HeapStats::newPass(name);               \
    68         pass;
     88        NewPass(name);                          \
     89        Stats::Time::StartBlock(name);          \
     90        pass;                                   \
     91        Stats::Time::StopBlock();
    6992
    7093LinkageSpec::Spec linkage = LinkageSpec::Cforall;
     
    7295DeclarationNode * parseTree = nullptr;                                  // program parse tree
    7396
    74 extern int yydebug;                                                                             // set for -g flag (Grammar)
    75 bool
    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 
    100 static void parse_cmdline( int argc, char *argv[], const char *& filename );
     97static bool waiting_for_gdb = false;                                    // flag to set cfa-cpp to wait for gdb on start
     98
     99static std::string PreludeDirector = "";
     100
     101static void parse_cmdline( int argc, char *argv[] );
    101102static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false );
    102103static void dump( list< Declaration * > & translationUnit, ostream & out = cout );
     
    152153} // backtrace
    153154
    154 void sigSegvBusHandler( int sig_num ) {
     155static void sigSegvBusHandler( int sig_num ) {
    155156        cerr << "*CFA runtime error* program cfa-cpp terminated with "
    156157                 <<     (sig_num == SIGSEGV ? "segment fault" : "bus error")
     
    158159        backtrace( 2 );                                                                         // skip first 2 stack frames
    159160        //_exit( EXIT_FAILURE );
    160         abort();
     161        abort();                                                                                        // cause core dump for debugging
    161162} // sigSegvBusHandler
    162163
    163 void sigAbortHandler( __attribute__((unused)) int sig_num ) {
     164static void sigAbortHandler( __attribute__((unused)) int sig_num ) {
    164165        backtrace( 6 );                                                                         // skip first 6 stack frames
    165166        signal( SIGABRT, SIG_DFL);                                                      // reset default signal handler
    166     raise( SIGABRT );                                                                   // reraise SIGABRT
     167        raise( SIGABRT );                                                                       // reraise SIGABRT
    167168} // 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;
    173         const char *filename = nullptr;
     172        ostream * output = & cout;
    174173        list< Declaration * > translationUnit;
    175174
     
    183182        // } // for
    184183
    185         parse_cmdline( argc, argv, filename );                          // process command-line arguments
     184        parse_cmdline( argc, argv );                                            // process command-line arguments
    186185        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
    187193
    188194        try {
     
    190196                if ( optind < argc ) {                                                  // any commands after the flags ? => input file name
    191197                        input = fopen( argv[ optind ], "r" );
    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";
     198                        assertf( input, "cannot open %s because %s\n", argv[ optind ], strerror( errno ) );
    197199                        optind += 1;
    198200                } else {                                                                                // no input file name
    199201                        input = stdin;
    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
     202                } // if
     203
     204                Stats::Time::StartGlobal();
     205                NewPass("Parse");
     206                Stats::Time::StartBlock("Parse");
    204207
    205208                // read in the builtins, extras, and the prelude
     
    207210                        // -l is for initial build ONLY and builtins.cf is not in the lib directory so access it here.
    208211
     212                        assertf( !PreludeDirector.empty(), "Can't find prelude without option --prelude-dir must be used." );
     213
    209214                        // Read to gcc builtins, if not generating the cfa library
    210                         FILE * gcc_builtins = fopen( libcfap | treep ? "../prelude/gcc-builtins.cf" : CFA_LIBDIR "/gcc-builtins.cf", "r" );
     215                        FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" );
    211216                        assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" );
    212217                        parse( gcc_builtins, LinkageSpec::Compiler );
    213218
    214219                        // read the extra prelude in, if not generating the cfa library
    215                         FILE * extras = fopen( libcfap | treep ? "../prelude/extras.cf" : CFA_LIBDIR "/extras.cf", "r" );
     220                        FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" );
    216221                        assertf( extras, "cannot open extras.cf\n" );
    217222                        parse( extras, LinkageSpec::BuiltinC );
     
    219224                        if ( ! libcfap ) {
    220225                                // read the prelude in, if not generating the cfa library
    221                                 FILE * prelude = fopen( treep ? "../prelude/prelude.cf" : CFA_LIBDIR "/prelude.cf", "r" );
    222                                 assertf( prelude, "cannot open prelude.cf\n" );
     226                                FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
     227                                assertf( prelude, "cannot open prelude.cfa\n" );
    223228                                parse( prelude, LinkageSpec::Intrinsic );
    224229
    225230                                // Read to cfa builtins, if not generating the cfa library
    226                                 FILE * builtins = fopen( libcfap | treep ? "../prelude/builtins.cf" : CFA_LIBDIR "/builtins.cf", "r" );
     231                                FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" );
    227232                                assertf( builtins, "cannot open builtins.cf\n" );
    228233                                parse( builtins, LinkageSpec::BuiltinCFA );
     
    235240                        parseTree->printList( cout );
    236241                        delete parseTree;
    237                         return 0;
     242                        return EXIT_SUCCESS;
    238243                } // if
    239244
     
    244249                if ( astp ) {
    245250                        dump( translationUnit );
    246                         return 0;
    247                 } // if
     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();
    248259
    249260                // add the assignment statement after the initialization of a type parameter
    250                 PASS( "validate", SymTab::validate( translationUnit, symtabp ) );
     261                PASS( "Validate", SymTab::validate( translationUnit, symtabp ) );
    251262                if ( symtabp ) {
    252263                        deleteAll( translationUnit );
    253                         return 0;
     264                        return EXIT_SUCCESS;
    254265                } // if
    255266
     
    257268                        PassVisitor<ResolvExpr::AlternativePrinter> printer( cout );
    258269                        acceptAll( translationUnit, printer );
    259                         return 0;
     270                        return EXIT_SUCCESS;
    260271                } // if
    261272
    262273                if ( validp ) {
    263274                        dump( 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 ) );
     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 ) );
    271282                if ( libcfap ) {
    272283                        // generate the bodies of cfa library functions
     
    277288                        CodeTools::printDeclStats( translationUnit );
    278289                        deleteAll( translationUnit );
    279                         return 0;
    280                 }
     290                        return EXIT_SUCCESS;
     291                } // if
    281292
    282293                if ( bresolvep ) {
    283294                        dump( translationUnit );
    284                         return 0;
     295                        return EXIT_SUCCESS;
    285296                } // if
    286297
    287298                CodeTools::fillLocations( translationUnit );
    288299
    289                 PASS( "resolve", ResolvExpr::resolve( translationUnit ) );
     300                if ( resolvprotop ) {
     301                        CodeTools::dumpAsResolvProto( translationUnit );
     302                        return EXIT_SUCCESS;
     303                } // if
     304
     305                PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    290306                if ( exprp ) {
    291307                        dump( translationUnit );
    292                         return 0;
     308                        return EXIT_SUCCESS;
    293309                } // if
    294310
    295311                // fix ObjectDecl - replaces ConstructorInit nodes
    296                 PASS( "fixInit", InitTweak::fix( translationUnit, filename, libcfap || treep ) );
     312                PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
    297313                if ( ctorinitp ) {
    298314                        dump ( translationUnit );
    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?
     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?
    311327
    312328                if ( tuplep ) {
    313329                        dump( translationUnit );
    314                         return 0;
    315                 }
    316 
    317                 PASS( "virtual expandCasts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM
    318 
    319                 PASS( "instantiateGenerics", GenPoly::instantiateGeneric( 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 ) );
    320336                if ( genericsp ) {
    321337                        dump( translationUnit );
    322                         return 0;
    323                 }
    324                 PASS( "convertLvalue", GenPoly::convertLvalue( translationUnit ) );
    325 
     338                        return EXIT_SUCCESS;
     339                } // if
     340
     341                PASS( "Convert L-Value", GenPoly::convertLvalue( translationUnit ) );
    326342
    327343                if ( bboxp ) {
    328344                        dump( translationUnit );
    329                         return 0;
    330                 } // if
    331                 PASS( "box", GenPoly::box( translationUnit ) );
     345                        return EXIT_SUCCESS;
     346                } // if
     347                PASS( "Box", GenPoly::box( translationUnit ) );
    332348
    333349                if ( bcodegenp ) {
    334350                        dump( translationUnit );
    335                         return 0;
    336                 }
     351                        return EXIT_SUCCESS;
     352                } // if
    337353
    338354                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     
    341357
    342358                CodeTools::fillLocations( translationUnit );
    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" );
     359                PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );
     360
     361                CodeGen::FixMain::fix( *output, (PreludeDirector + "/bootloader.c").c_str() );
    346362                if ( output != &cout ) {
    347363                        delete output;
     
    357373                        delete output;
    358374                } // if
    359                 return 1;
     375                return EXIT_FAILURE;
    360376        } catch ( UnimplementedError &e ) {
    361377                cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
     
    363379                        delete output;
    364380                } // if
    365                 return 1;
     381                return EXIT_FAILURE;
    366382        } catch ( CompilerError &e ) {
    367383                cerr << "Compiler Error: " << e.get_what() << endl;
     
    370386                        delete output;
    371387                } // if
    372                 return 1;
    373         } catch(...) {
     388                return EXIT_FAILURE;
     389        } catch ( ... ) {
    374390                std::exception_ptr eptr = std::current_exception();
    375391                try {
    376392                        if (eptr) {
    377393                                std::rethrow_exception(eptr);
    378                         }
    379                         else {
    380                                 std::cerr << "Exception Uncaught and Unkown" << std::endl;
    381                         }
     394                        } else {
     395                                std::cerr << "Exception Uncaught and Unknown" << std::endl;
     396                        } // if
    382397                } catch(const std::exception& e) {
    383                         std::cerr << "Unaught Exception \"" << e.what() << "\"\n";
    384                 }
    385                 return 1;
    386         }// try
     398                        std::cerr << "Uncaught Exception \"" << e.what() << "\"\n";
     399                } // try
     400                return EXIT_FAILURE;
     401        } // try
    387402
    388403        deleteAll( translationUnit );
    389         if(!libcfap && !treep) HeapStats::printStats();
    390         return 0;
     404        Stats::print();
     405        return EXIT_SUCCESS;
    391406} // main
    392407
    393 void 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 
     408
     409static const char optstring[] = ":hlLmNnpP:S:twW:D:";
     410
     411enum { PreludeDir = 128 };
     412static 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
     431static 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
     449static_assert( sizeof( long_opts ) / sizeof( long_opts[0] ) - 1 == sizeof( description ) / sizeof( description[0] ), "Long opts and description must match" );
     450
     451static 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};
     478enum { printoptsSize = sizeof( printopts ) / sizeof( printopts[0] ) };
     479
     480static 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
     507static void parse_cmdline( int argc, char * argv[] ) {
    420508        opterr = 0;                                                                                     // (global) prevent getopt from printing error messages
    421509
    422510        bool Wsuppress = false, Werror = false;
    423511        int c;
    424         while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
     512        while ( (c = getopt_long( argc, argv, optstring, long_opts, nullptr )) != -1 ) {
    425513                switch ( c ) {
    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:
     514                  case 'h':                                                                             // help message
     515                        usage( argv );                                                          // no return
     516                        break;
    464517                  case 'l':                                                                             // generate libcfa.c
    465518                        libcfap = true;
    466519                        break;
    467                   case Linemarks:
    468                   case 'L':                                                                             // print lines marks
     520                  case 'L':                                                                             // generate line marks
    469521                        linemarks = true;
    470522                        break;
    471                   case Nopreamble:
    472                   case 'n':                                                                             // do not read preamble
     523                  case 'm':                                                                             // do not replace main
     524                        nomainp = true;
     525                        break;
     526                  case 'N':                                                                             // do not generate line marks
     527                        linemarks = false;
     528                        break;
     529                  case 'n':                                                                             // do not read prelude
    473530                        nopreludep = true;
    474531                        break;
    475                   case Nolinemarks:
    476                   case 'N':                                                                             // suppress line marks
    477                         linemarks = false;
    478                         break;
    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
     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
    500554                        treep = true;
    501555                        break;
    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':
     556                  case 'g':                                                                             // wait for gdb
     557                        waiting_for_gdb = true;
     558                        break;
     559                  case 'w':                                                                             // suppress all warnings, hidden
    510560                        Wsuppress = true;
    511561                        break;
    512                   case 'W':
     562                  case 'W':                                                                             // coordinate gcc -W with CFA, hidden
    513563                        if ( strcmp( optarg, "all" ) == 0 ) {
    514564                                SemanticWarning_EnableAll();
     
    527577                        } // if
    528578                        break;
    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 '?':
     579                  case 'D':                                                                             // ignore -Dxxx, forwarded by cpp, hidden
     580                        break;
     581                  case '?':                                                                             // unknown option
    544582                        if ( optopt ) {                                                         // short option ?
    545                                 assertf( false, "Unknown option: -%c\n", (char)optopt );
     583                                cout << "Unknown option -" << (char)optopt << endl;
    546584                        } else {
    547                                 assertf( false, "Unknown option: %s\n", argv[optind - 1] );
    548                         } // if
    549                         #if defined(__GNUC__) && __GNUC__ >= 7
    550                                 __attribute__((fallthrough));
    551                         #endif
     585                                cout << "Unknown option " << argv[optind - 1] << endl;
     586                        } // 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:
    552596                  default:
    553                         abort();
     597                        usage( argv );                                                          // no return
    554598                } // switch
    555599        } // while
     
    589633        list< Declaration * > decls;
    590634
    591         if ( noprotop ) {
     635        if ( genproto ) {
    592636                filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude );
    593637        } else {
     
    597641        // depending on commandline options, either generate code or dump the AST
    598642        if ( codegenp ) {
    599                 CodeGen::generate( decls, out, ! noprotop, prettycodegenp );
     643                CodeGen::generate( decls, out, ! genproto, prettycodegenp );
    600644        } else {
    601645                printAll( decls, out );
    602         }
     646        } // if
    603647        deleteAll( translationUnit );
    604648} // dump
  • tools/Makefile.am

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

    r7951100 rb067d9b  
    9292build_triplet = @build@
    9393host_triplet = @host@
    94 noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT)
     94noinst_PROGRAMS = busy$(EXEEXT) catchsig$(EXEEXT) repeat$(EXEEXT) \
     95        watchdog$(EXEEXT)
    9596subdir = tools
    9697ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    97 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
     98am__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
    98104am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    99105        $(ACLOCAL_M4)
     
    107113busy_OBJECTS = $(am_busy_OBJECTS)
    108114busy_LDADD = $(LDADD)
    109 busy_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(busy_LDFLAGS) $(LDFLAGS) \
    110         -o $@
     115AM_V_lt = $(am__v_lt_@AM_V@)
     116am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
     117am__v_lt_0 = --silent
     118am__v_lt_1 =
     119busy_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
     120        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
     121        $(busy_LDFLAGS) $(LDFLAGS) -o $@
    111122am_catchsig_OBJECTS = catchsig.$(OBJEXT)
    112123catchsig_OBJECTS = $(am_catchsig_OBJECTS)
     
    115126repeat_OBJECTS = $(am_repeat_OBJECTS)
    116127repeat_LDADD = $(LDADD)
     128am_watchdog_OBJECTS = watchdog.$(OBJEXT)
     129watchdog_OBJECTS = $(am_watchdog_OBJECTS)
     130watchdog_LDADD = $(LDADD)
    117131AM_V_P = $(am__v_P_@AM_V@)
    118132am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    133147COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    134148        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
     149LTCOMPILE = $(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)
    135153AM_V_CC = $(am__v_CC_@AM_V@)
    136154am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
     
    138156am__v_CC_1 =
    139157CCLD = $(CC)
    140 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
     158LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
     159        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
     160        $(AM_LDFLAGS) $(LDFLAGS) -o $@
    141161AM_V_CCLD = $(am__v_CCLD_@AM_V@)
    142162am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
    143163am__v_CCLD_0 = @echo "  CCLD    " $@;
    144164am__v_CCLD_1 =
    145 SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
    146 DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES)
     165SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
     166        $(watchdog_SOURCES)
     167DIST_SOURCES = $(busy_SOURCES) $(catchsig_SOURCES) $(repeat_SOURCES) \
     168        $(watchdog_SOURCES)
    147169am__can_run_installinfo = \
    148170  case $$AM_UPDATE_INFO_DIR in \
     
    172194DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    173195ACLOCAL = @ACLOCAL@
    174 ALLOCA = @ALLOCA@
    175196AMTAR = @AMTAR@
    176197AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
     198AR = @AR@
    177199AUTOCONF = @AUTOCONF@
    178200AUTOHEADER = @AUTOHEADER@
    179201AUTOMAKE = @AUTOMAKE@
    180202AWK = @AWK@
    181 BACKEND_CC = @BACKEND_CC@
    182 CC = @BACKEND_CC@
     203BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
     204CC = @CC@
    183205CCAS = @CCAS@
    184206CCASDEPMODE = @CCASDEPMODE@
    185207CCASFLAGS = @CCASFLAGS@
    186208CCDEPMODE = @CCDEPMODE@
     209CFACC = @CFACC@
     210CFACC_INSTALL = @CFACC_INSTALL@
     211CFACPP = @CFACPP@
    187212CFA_BACKEND_CC = @CFA_BACKEND_CC@
    188213CFA_BINDIR = @CFA_BINDIR@
     
    192217CFA_NAME = @CFA_NAME@
    193218CFA_PREFIX = @CFA_PREFIX@
    194 CFLAGS = -Wall -Wextra -O2 -g
     219CFLAGS = @CFLAGS@
    195220CPP = @CPP@
    196221CPPFLAGS = @CPPFLAGS@
    197222CXX = @CXX@
     223CXXCPP = @CXXCPP@
    198224CXXDEPMODE = @CXXDEPMODE@
    199225CXXFLAGS = @CXXFLAGS@
    200226CYGPATH_W = @CYGPATH_W@
    201227DEFS = @DEFS@
     228DEMANGLER = @DEMANGLER@
    202229DEPDIR = @DEPDIR@
     230DLLTOOL = @DLLTOOL@
     231DRIVER_DIR = @DRIVER_DIR@
     232DSYMUTIL = @DSYMUTIL@
     233DUMPBIN = @DUMPBIN@
    203234ECHO_C = @ECHO_C@
    204235ECHO_N = @ECHO_N@
     
    206237EGREP = @EGREP@
    207238EXEEXT = @EXEEXT@
     239FGREP = @FGREP@
    208240GREP = @GREP@
     241HAS_DISTCC = @HAS_DISTCC@
     242HOST_FLAGS = @HOST_FLAGS@
    209243INSTALL = @INSTALL@
    210244INSTALL_DATA = @INSTALL_DATA@
     
    212246INSTALL_SCRIPT = @INSTALL_SCRIPT@
    213247INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
     248LD = @LD@
    214249LDFLAGS = @LDFLAGS@
    215250LEX = @LEX@
    216251LEXLIB = @LEXLIB@
    217252LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
     253LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
     254LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
     255LIBDEMANGLE = @LIBDEMANGLE@
    218256LIBOBJS = @LIBOBJS@
    219257LIBS = @LIBS@
     258LIBTOOL = @LIBTOOL@
     259LIPO = @LIPO@
     260LN_S = @LN_S@
    220261LTLIBOBJS = @LTLIBOBJS@
    221 MACHINE_TYPE = @MACHINE_TYPE@
    222 MAINT = @MAINT@
     262LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
    223263MAKEINFO = @MAKEINFO@
     264MANIFEST_TOOL = @MANIFEST_TOOL@
    224265MKDIR_P = @MKDIR_P@
     266NM = @NM@
     267NMEDIT = @NMEDIT@
     268OBJDUMP = @OBJDUMP@
    225269OBJEXT = @OBJEXT@
     270OTOOL = @OTOOL@
     271OTOOL64 = @OTOOL64@
    226272PACKAGE = @PACKAGE@
    227273PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    233279PATH_SEPARATOR = @PATH_SEPARATOR@
    234280RANLIB = @RANLIB@
     281SED = @SED@
    235282SET_MAKE = @SET_MAKE@
    236283SHELL = @SHELL@
    237284STRIP = @STRIP@
     285TARGET_HOSTS = @TARGET_HOSTS@
    238286VERSION = @VERSION@
    239287YACC = @YACC@
     
    243291abs_top_builddir = @abs_top_builddir@
    244292abs_top_srcdir = @abs_top_srcdir@
     293ac_ct_AR = @ac_ct_AR@
    245294ac_ct_CC = @ac_ct_CC@
    246295ac_ct_CXX = @ac_ct_CXX@
     296ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    247297am__include = @am__include@
    248298am__leading_dot = @am__leading_dot@
     
    291341top_builddir = @top_builddir@
    292342top_srcdir = @top_srcdir@
     343AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
     344ACLOCAL_AMFLAGS = -I automake
     345AM_CFLAGS = -Wall -Wextra -O2 -g
    293346busy_SOURCES = busy.c
    294347busy_LDFLAGS = -pthread
    295348catchsig_SOURCES = catchsig.c
    296349repeat_SOURCES = repeat.c
     350watchdog_SOURCES = watchdog.c
    297351all: all-am
    298352
    299353.SUFFIXES:
    300 .SUFFIXES: .c .o .obj
    301 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
     354.SUFFIXES: .c .lo .o .obj
     355$(srcdir)/Makefile.in: $(srcdir)/Makefile.am  $(am__configure_deps)
    302356        @for dep in $?; do \
    303357          case '$(am__configure_deps)' in \
     
    323377        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    324378
    325 $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
     379$(top_srcdir)/configure: $(am__configure_deps)
    326380        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    327 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
     381$(ACLOCAL_M4): $(am__aclocal_m4_deps)
    328382        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    329383$(am__aclocal_m4_deps):
    330384
    331385clean-noinstPROGRAMS:
    332         -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
     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
    333393
    334394busy$(EXEEXT): $(busy_OBJECTS) $(busy_DEPENDENCIES) $(EXTRA_busy_DEPENDENCIES)
     
    344404        $(AM_V_CCLD)$(LINK) $(repeat_OBJECTS) $(repeat_LDADD) $(LIBS)
    345405
     406watchdog$(EXEEXT): $(watchdog_OBJECTS) $(watchdog_DEPENDENCIES) $(EXTRA_watchdog_DEPENDENCIES)
     407        @rm -f watchdog$(EXEEXT)
     408        $(AM_V_CCLD)$(LINK) $(watchdog_OBJECTS) $(watchdog_LDADD) $(LIBS)
     409
    346410mostlyclean-compile:
    347411        -rm -f *.$(OBJEXT)
     
    353417@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/catchsig.Po@am__quote@
    354418@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repeat.Po@am__quote@
     419@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watchdog.Po@am__quote@
    355420
    356421.c.o:
     
    369434@AMDEP_TRUE@@am__fastdepCC_FALSE@       DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    370435@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
     445mostlyclean-libtool:
     446        -rm -f *.lo
     447
     448clean-libtool:
     449        -rm -rf .libs _libs
    371450
    372451ID: $(am__tagged_files)
     
    488567clean: clean-am
    489568
    490 clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
     569clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
     570        mostlyclean-am
    491571
    492572distclean: distclean-am
     
    543623mostlyclean: mostlyclean-am
    544624
    545 mostlyclean-am: mostlyclean-compile mostlyclean-generic
     625mostlyclean-am: mostlyclean-compile mostlyclean-generic \
     626        mostlyclean-libtool
    546627
    547628pdf: pdf-am
     
    558639
    559640.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
    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 \
     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 \
    568650        maintainer-clean-generic mostlyclean mostlyclean-compile \
    569         mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
    570         uninstall-am
     651        mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
     652        tags tags-am uninstall uninstall-am
    571653
    572654.PRECIOUS: Makefile
  • tools/cfa.nanorc

    r7951100 rb067d9b  
    22## WIP
    33
    4 syntax "cfa" "\.cfa"
     4syntax "cfa" "\.(c|h)fa"
    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|sizeof|enum|void|auto)\>"
    12 color green "\<(static|const|struct|union|typedef|extern|(un)?signed|inline)\>"
     11color green "\<(float|double|bool|char|int|short|long|enum|void|auto)\>"
     12color green "\<(static|const|extern|(un)?signed|inline)\>" "\<(sizeof)\>"
    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)\>"
     21color brightyellow "\<(disable|enable|waitfor|when|timeout)\>"
    2122color brightyellow "\<(try|catch(Resume)?|finally)\>"
    2223
    2324# Control Flow Statements
    2425color magenta "\<(goto|return|break|continue|fallthr(u|ough)|throw(Resume)?)\>"
     26
     27# Escaped Keywords, now Identifiers.
     28color white "`\w+`"
    2529
    2630# Operator Names
  • tools/prettyprinter/Makefile.am

    r7951100 rb067d9b  
    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
     17AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
     18ACLOCAL_AMFLAGS  = -I automake
    1619
    1720BUILT_SOURCES = parser.hh
  • tools/prettyprinter/Makefile.in

    r7951100 rb067d9b  
    9595subdir = tools/prettyprinter
    9696ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    97 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
     97am__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
    98103am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
    99104        $(ACLOCAL_M4)
     
    112117am__DEPENDENCIES_1 =
    113118pretty_DEPENDENCIES = $(am__DEPENDENCIES_1)
    114 pretty_LINK = $(CXXLD) $(pretty_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
    115         $(LDFLAGS) -o $@
     119AM_V_lt = $(am__v_lt_@AM_V@)
     120am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
     121am__v_lt_0 = --silent
     122am__v_lt_1 =
     123pretty_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
     124        $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(pretty_CXXFLAGS) \
     125        $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    116126AM_V_P = $(am__v_P_@AM_V@)
    117127am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
     
    130140am__depfiles_maybe = depfiles
    131141am__mv = mv -f
    132 AM_V_lt = $(am__v_lt_@AM_V@)
    133 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
    134 am__v_lt_0 = --silent
    135 am__v_lt_1 =
    136142CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
    137143        $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
     144LTCXXCOMPILE = $(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)
    138148AM_V_CXX = $(am__v_CXX_@AM_V@)
    139149am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
     
    141151am__v_CXX_1 =
    142152CXXLD = $(CXX)
    143 CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
    144         -o $@
     153CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
     154        $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
     155        $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
    145156AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
    146157am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
    147158am__v_CXXLD_0 = @echo "  CXXLD   " $@;
    148159am__v_CXXLD_1 =
    149 @MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
    150160LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
     161LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
     162        $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
    151163AM_V_LEX = $(am__v_LEX_@AM_V@)
    152164am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
     
    154166am__v_LEX_1 =
    155167YLWRAP = $(top_srcdir)/automake/ylwrap
    156 @MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
    157168am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
    158169                   -e s/c++$$/h++/ -e s/c$$/h/
    159170YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
     171LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
     172        $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
    160173AM_V_YACC = $(am__v_YACC_@AM_V@)
    161174am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
     
    164177COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    165178        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
     179LTCOMPILE = $(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)
    166183AM_V_CC = $(am__v_CC_@AM_V@)
    167184am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
     
    169186am__v_CC_1 =
    170187CCLD = $(CC)
    171 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
     188LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
     189        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
     190        $(AM_LDFLAGS) $(LDFLAGS) -o $@
    172191AM_V_CCLD = $(am__v_CCLD_@AM_V@)
    173192am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
     
    204223DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
    205224ACLOCAL = @ACLOCAL@
    206 ALLOCA = @ALLOCA@
    207225AMTAR = @AMTAR@
    208226AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
     227AR = @AR@
    209228AUTOCONF = @AUTOCONF@
    210229AUTOHEADER = @AUTOHEADER@
    211230AUTOMAKE = @AUTOMAKE@
    212231AWK = @AWK@
    213 BACKEND_CC = @BACKEND_CC@
     232BUILD_IN_TREE_FLAGS = @BUILD_IN_TREE_FLAGS@
    214233CC = @CC@
    215234CCAS = @CCAS@
     
    217236CCASFLAGS = @CCASFLAGS@
    218237CCDEPMODE = @CCDEPMODE@
     238CFACC = @CFACC@
     239CFACC_INSTALL = @CFACC_INSTALL@
     240CFACPP = @CFACPP@
    219241CFA_BACKEND_CC = @CFA_BACKEND_CC@
    220242CFA_BINDIR = @CFA_BINDIR@
     
    228250CPPFLAGS = @CPPFLAGS@
    229251CXX = @CXX@
     252CXXCPP = @CXXCPP@
    230253CXXDEPMODE = @CXXDEPMODE@
    231254CXXFLAGS = @CXXFLAGS@
    232255CYGPATH_W = @CYGPATH_W@
    233256DEFS = @DEFS@
     257DEMANGLER = @DEMANGLER@
    234258DEPDIR = @DEPDIR@
     259DLLTOOL = @DLLTOOL@
     260DRIVER_DIR = @DRIVER_DIR@
     261DSYMUTIL = @DSYMUTIL@
     262DUMPBIN = @DUMPBIN@
    235263ECHO_C = @ECHO_C@
    236264ECHO_N = @ECHO_N@
     
    238266EGREP = @EGREP@
    239267EXEEXT = @EXEEXT@
     268FGREP = @FGREP@
    240269GREP = @GREP@
     270HAS_DISTCC = @HAS_DISTCC@
     271HOST_FLAGS = @HOST_FLAGS@
    241272INSTALL = @INSTALL@
    242273INSTALL_DATA = @INSTALL_DATA@
     
    244275INSTALL_SCRIPT = @INSTALL_SCRIPT@
    245276INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
     277LD = @LD@
    246278LDFLAGS = @LDFLAGS@
    247279LEX = @LEX@
    248280LEXLIB = @LEXLIB@
    249281LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
     282LIBCFA_TARGET_DIRS = @LIBCFA_TARGET_DIRS@
     283LIBCFA_TARGET_MAKEFILES = @LIBCFA_TARGET_MAKEFILES@
     284LIBDEMANGLE = @LIBDEMANGLE@
    250285LIBOBJS = @LIBOBJS@
    251286LIBS = @LIBS@
     287LIBTOOL = @LIBTOOL@
     288LIPO = @LIPO@
     289LN_S = @LN_S@
    252290LTLIBOBJS = @LTLIBOBJS@
    253 MACHINE_TYPE = @MACHINE_TYPE@
    254 MAINT = @MAINT@
     291LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
    255292MAKEINFO = @MAKEINFO@
     293MANIFEST_TOOL = @MANIFEST_TOOL@
    256294MKDIR_P = @MKDIR_P@
     295NM = @NM@
     296NMEDIT = @NMEDIT@
     297OBJDUMP = @OBJDUMP@
    257298OBJEXT = @OBJEXT@
     299OTOOL = @OTOOL@
     300OTOOL64 = @OTOOL64@
    258301PACKAGE = @PACKAGE@
    259302PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
     
    265308PATH_SEPARATOR = @PATH_SEPARATOR@
    266309RANLIB = @RANLIB@
     310SED = @SED@
    267311SET_MAKE = @SET_MAKE@
    268312SHELL = @SHELL@
    269313STRIP = @STRIP@
     314TARGET_HOSTS = @TARGET_HOSTS@
    270315VERSION = @VERSION@
    271316YACC = @YACC@
     
    275320abs_top_builddir = @abs_top_builddir@
    276321abs_top_srcdir = @abs_top_srcdir@
     322ac_ct_AR = @ac_ct_AR@
    277323ac_ct_CC = @ac_ct_CC@
    278324ac_ct_CXX = @ac_ct_CXX@
     325ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
    279326am__include = @am__include@
    280327am__leading_dot = @am__leading_dot@
     
    323370top_builddir = @top_builddir@
    324371top_srcdir = @top_srcdir@
     372AUTOMAKE_OPTIONS = foreign    # do not require all the GNU file names
     373ACLOCAL_AMFLAGS = -I automake
    325374BUILT_SOURCES = parser.hh
    326375AM_YFLAGS = -d -t -v
     
    340389
    341390.SUFFIXES:
    342 .SUFFIXES: .cc .ll .o .obj .yy
    343 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
     391.SUFFIXES: .cc .ll .lo .o .obj .yy
     392$(srcdir)/Makefile.in: $(srcdir)/Makefile.am  $(am__configure_deps)
    344393        @for dep in $?; do \
    345394          case '$(am__configure_deps)' in \
     
    365414        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    366415
    367 $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
     416$(top_srcdir)/configure: $(am__configure_deps)
    368417        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    369 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
     418$(ACLOCAL_M4): $(am__aclocal_m4_deps)
    370419        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
    371420$(am__aclocal_m4_deps):
     
    380429        sed 's/$(EXEEXT)$$//' | \
    381430        while read p p1; do if test -f $$p \
     431         || test -f $$p1 \
    382432          ; then echo "$$p"; echo "$$p"; else :; fi; \
    383433        done | \
     
    394444            if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
    395445            test -z "$$files" || { \
    396               echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(tools_prettyprinterdir)$$dir'"; \
    397               $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(tools_prettyprinterdir)$$dir" || exit $$?; \
     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 $$?; \
    398448            } \
    399449        ; done
     
    411461
    412462clean-tools_prettyprinterPROGRAMS:
    413         -test -z "$(tools_prettyprinter_PROGRAMS)" || rm -f $(tools_prettyprinter_PROGRAMS)
     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
    414470parser.hh: parser.cc
    415471        @if test ! -f $@; then rm -f parser.cc; else :; fi
     
    448504@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
    449505
     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
    450514pretty-lex.o: lex.cc
    451515@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
     
    523587.yy.cc:
    524588        $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
     589
     590mostlyclean-libtool:
     591        -rm -f *.lo
     592
     593clean-libtool:
     594        -rm -rf .libs _libs
    525595
    526596ID: $(am__tagged_files)
     
    652722clean: clean-am
    653723
    654 clean-am: clean-generic clean-tools_prettyprinterPROGRAMS \
    655         mostlyclean-am
     724clean-am: clean-generic clean-libtool \
     725        clean-tools_prettyprinterPROGRAMS mostlyclean-am
    656726
    657727distclean: distclean-am
     
    708778mostlyclean: mostlyclean-am
    709779
    710 mostlyclean-am: mostlyclean-compile mostlyclean-generic
     780mostlyclean-am: mostlyclean-compile mostlyclean-generic \
     781        mostlyclean-libtool
    711782
    712783pdf: pdf-am
     
    723794
    724795.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
    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 \
     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 \
    733805        installcheck-am installdirs maintainer-clean \
    734806        maintainer-clean-generic mostlyclean mostlyclean-compile \
    735         mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
    736         uninstall-am uninstall-tools_prettyprinterPROGRAMS
     807        mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
     808        tags tags-am uninstall uninstall-am \
     809        uninstall-tools_prettyprinterPROGRAMS
    737810
    738811.PRECIOUS: Makefile
  • tools/stat.py

    r7951100 rb067d9b  
    1111                content = f.readlines()
    1212                content = [x.strip() for x in content]
    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 )
     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 )
    2020
    2121
Note: See TracChangeset for help on using the changeset viewer.