Changeset 02af79b0


Ignore:
Timestamp:
May 9, 2019, 4:47:53 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, cleanup-dtors, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
b038fe4
Parents:
ec28948 (diff), db27767 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Files:
22 added
41 edited

Legend:

Unmodified
Added
Removed
  • Jenkins/FullBuild

    rec28948 r02af79b0  
    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                                         clang_x64: { trigger_build( 'clang',   'x64', false ) },
    24                                         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' ) },
    2525                                )
    2626                        }
     
    5656//===========================================================================================================
    5757
    58 def trigger_build(String cc, String arch, Boolean publish) {
     58def trigger_build(String cc, String arch) {
    5959        def result = build job: 'Cforall/master',               \
    6060                parameters: [                                           \
     
    7676                        [$class: 'BooleanParameterValue',               \
    7777                          name: 'Publish',                              \
    78                           value: publish],                              \
     78                          value: true],                                 \
    7979                        [$class: 'BooleanParameterValue',               \
    8080                          name: 'Silent',                               \
  • Jenkinsfile

    rec28948 r02af79b0  
    170170        build_stage('Publish') {
    171171
    172                 if( !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
     172                if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
    173173
    174174                def groupCompile = new PlotGroup('Compilation', 'seconds', true)
     
    433433}
    434434
    435 def do_plot(boolean silent, String file, PlotGroup group, String title) {
    436 
    437         def series = silent ? [] : [[
     435def do_plot(boolean new_data, String file, PlotGroup group, String title) {
     436
     437        if(new_data) {
     438                echo "Publishing new data"
     439        }
     440
     441        def series = new_data ? [] : [[
    438442                                file: "${file}.csv",
    439443                                exclusionValues: '',
  • doc/papers/concurrency/Paper.tex

    rec28948 r02af79b0  
    241241\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}}
    242242
    243 \fundingInfo{Natural Sciences and Engineering Research Council of Canada}
     243% \fundingInfo{Natural Sciences and Engineering Research Council of Canada}
    244244
    245245\abstract[Summary]{
    246 \CFA is a modern, polymorphic, non-object-oriented, backwards-compatible extension of the C programming language.
    247 This paper discusses some advanced control-flow and concurrency/parallelism features in \CFA, along with the supporting runtime.
    248 These features are created from scratch because they do not exist in ISO C, or are low-level and/or unimplemented, so C programmers continue to rely on library features, like C pthreads.
    249 \CFA introduces language-level control-flow mechanisms, like coroutines, user-level threading, and monitors for mutual exclusion and synchronization.
    250 A unique contribution of this work is allowing multiple monitors to be safely acquired \emph{simultaneously} (deadlock free), while integrating this capability with monitor synchronization mechanisms.
    251 These features also integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers.
     246\CFA is a polymorphic, non-object-oriented, concurrent, backwards-compatible extension of the C programming language.
     247This paper discusses the design philosophy and implementation of its advanced control-flow and concurrent/parallel features, along with the supporting runtime.
     248These 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 C pthreads.
     249\CFA introduces modern language-level control-flow mechanisms, like coroutines, user-level threading, and monitors for mutual exclusion and synchronization.
     250Library extension for executors, futures, and actors are built on these basic mechanisms.
     251The runtime provides significant programmer simplification and safety by eliminating spurious wakeup and reducing monitor barging.
     252The runtime also ensures multiple monitors can be safely acquired \emph{simultaneously} (deadlock free), and this feature is fully integrated with all monitor synchronization mechanisms.
     253All language features integrate with the \CFA polymorphic type-system and exception handling, while respecting the expectations and style of C programmers.
    252254Experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming-languages.
    253255}%
     
    264266\section{Introduction}
    265267
    266 This paper discusses the design of language-level control-flow and concurrency/parallelism extensions in \CFA and its runtime.
     268This paper discusses the design philosophy and implementation of advanced language-level control-flow and concurrent/parallel features in \CFA~\cite{Moss18} and its runtime.
    267269\CFA is a modern, polymorphic, non-object-oriented\footnote{
    268270\CFA has features often associated with object-oriented programming languages, such as constructors, destructors, virtuals and simple inheritance.
    269271However, 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.},
    270 backwards-compatible extension of the C programming language~\cite{Moss18}.
     272backwards-compatible extension of the C programming language.
    271273Within the \CFA framework, new control-flow features are created from scratch.
    272274ISO \Celeven defines only a subset of the \CFA extensions, where the overlapping features are concurrency~\cite[\S~7.26]{C11}.
     
    275277no high-level language concurrency features are defined.
    276278Interestingly, almost a decade after publication of the \Celeven standard, neither gcc-8, clang-8 nor msvc-19 (most recent versions) support the \Celeven include @threads.h@, indicating little interest in the C11 concurrency approach.
    277 Finally, while the \Celeven standard does not state a concurrent threading-model, the historical association with pthreads suggests implementations would adopt kernel-level threading (1:1)~\cite{ThreadModel}.
     279Finally, 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}.
    278280
    279281In contrast, there has been a renewed interest during the past decade in user-level (M:N, green) threading in old and new programming languages.
     
    281283Kernel 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}.
    282284Libraries like pthreads were developed for C, and the Solaris operating-system switched from user (JDK 1.1~\cite{JDK1.1}) to kernel threads.
    283 As a result, languages like Java, Scala~\cite{Scala}, Objective-C~\cite{obj-c-book}, \CCeleven~\cite{C11}, and C\#~\cite{Csharp} adopted the 1:1 kernel-threading model, with a variety of presentation mechanisms.
     285As a result, languages like Java, Scala~\cite{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.
    284286From 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,BoostThreads}, including putting green threads back into Java~\cite{Quasar}.
    285287The main argument for user-level threading is that they are lighter weight than kernel threads (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 smaller work-units to facilitate load balancing by the runtime~\cite{Verch12}.
     
    287289Finally, performant user-threading implementations (both time and space) are largely competitive with direct kernel-threading implementations, while achieving the programming advantages of high concurrency levels and safety.
    288290
    289 A further effort over the past decade is the development of language memory-models to deal with the conflict between certain language features and compiler/hardware optimizations.
    290 This issue can be rephrased as: some language features are pervasive (language and runtime) and cannot be safely added via a library to prevent invalidation by sequential optimizations~\cite{Buhr95a,Boehm05}.
    291 The consequence is that a language must be cognizant of these features and provide sufficient tools to program around any safety issues.
    292 For example, C created the @volatile@ qualifier to provide correct execution for @setjmp@/@logjmp@ (concurrency came later).
    293 The common solution is to provide a handful of complex qualifiers and functions (e.g., @volatile@ and atomics) allowing programmers to write consistent/race-free programs, often in the sequentially-consistent memory-model~\cite{Boehm12}.
    294 
    295 While having a sufficient memory-model allows sound libraries to be constructed, writing these libraries can quickly become awkward and error prone, and using these low-level libraries has the same issues.
    296 Essentially, using low-level explicit locks is the concurrent equivalent of assembler programming.
    297 Just as most assembler programming is replaced with high-level programming, explicit locks can be replaced with high-level concurrency in a programming language.
    298 Then the goal is for the compiler to check for correct usage and follow any complex coding conventions implicitly.
    299 The drawback is that language constructs may preclude certain specialized techniques, therefore introducing inefficiency or inhibiting concurrency.
    300 For most concurrent programs, these drawbacks are insignificant in comparison to the speed of composition, and subsequent reliability and maintainability of the high-level concurrent program.
    301 (The same is true for high-level programming versus assembler programming.)
    302 Only very rarely should it be necessary to drop down to races and/or explicit locks to apply a specialized technique to achieve maximum speed or concurrency.
    303 As stated, this observation applies to non-concurrent forms of complex control-flow, like exception handling and coroutines.
    304 
    305 Adapting the programming language to these features also allows matching the control-flow model with the programming-language style, versus adopting one general (sound) library/paradigm.
     291A 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, i.e., some language features are unsafe in the presence of aggressive sequential optimizations~\cite{Buhr95a,Boehm05}.
     292The 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.
     293One solution is low-level qualifiers and functions (e.g., @volatile@ and atomics) allowing \emph{programmers} to explicitly write safe (race-free~\cite{Boehm12}) programs.
     294A safer solution is high-level language constructs so the \emph{compiler} knows the optimization boundaries, and hence, provides implicit safety.
     295This problem is best know with respect to concurrency, but applies to other complex control-flow, like exceptions\footnote{
     296\CFA exception handling will be presented in a separate paper.
     297The key feature that dovetails with this paper is non-local 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++}
     298} and coroutines.
     299Finally, solutions in the language allows matching constructs with language paradigm, i.e., imperative and functional languages have different presentations of the same concept.
     300
     301Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety for performance when necessary.
     302Two concurrency violations of this philosophy are \emph{spurious wakeup} and \emph{barging}, i.e., random wakeup~\cite[\S~8]{Buhr05a} and signalling-as-hints~\cite[\S~8]{Buhr05a}, where one begats the other.
     303If you believe spurious wakeup is a foundational concurrency property, than unblocking (signalling) a thread is always a hint.
     304If you \emph{do not} believe spurious wakeup is foundational, than signalling-as-hints is a performance decision.
     305Most importantly, removing spurious wakeup and signals-as-hints makes concurrent programming significantly safer because it removes local non-determinism.
     306Clawing back performance where the local non-determinism is unimportant, should be an option not the default.
     307
     308\begin{comment}
    306309For example, it is possible to provide exceptions, coroutines, monitors, and tasks as specialized types in an object-oriented language, integrating these constructs to allow leveraging the type-system (static type-checking) and all other object-oriented capabilities~\cite{uC++}.
    307310It is also possible to leverage call/return for blocking communication via new control structures, versus switching to alternative communication paradigms, like channels or message passing.
     
    321324Hence, rewriting and retraining costs for these languages, even \CC, are prohibitive for companies with a large C software-base.
    322325\CFA with its orthogonal feature-set, its high-performance runtime, and direct access to all existing C libraries circumvents these problems.
    323 
    324 We present comparative examples so the reader can judge if the \CFA control-flow extensions are equivalent or better than those in or proposed for \Celeven, \CC and other concurrent, imperative programming languages, and perform experiments to show the \CFA runtime is competitive with other similar mechanisms.
    325 The detailed contributions of this work are:
     326\end{comment}
     327
     328\CFA embraces user-level threading, language extensions for advanced control-flow, and safety as the default.
     329We present comparative examples so the reader can judge if the \CFA control-flow extensions are better and safer than those in or proposed for \Celeven, \CC and other concurrent, imperative programming languages, and perform experiments to show the \CFA runtime is competitive with other similar mechanisms.
     330The main contributions of this work are:
    326331\begin{itemize}
    327332\item
    328 allowing multiple monitors to be safely acquired \emph{simultaneously} (deadlock free), while seamlessly integrating this capability with all monitor synchronization mechanisms.
     333expressive language-level coroutines and user-level threading, which respect the expectations of C programmers.
    329334\item
    330 all control-flow features respect the expectations of C programmers, with statically type-safe interfaces that integrate with the \CFA polymorphic type-system and other language features.
     335monitor synchronization without barging.
    331336\item
    332 experimental results show comparable performance of the new features with similar mechanisms in other concurrent programming-languages.
     337safely acquiring multiple monitors \emph{simultaneously} (deadlock free), while seamlessly integrating this capability with all monitor synchronization mechanisms.
     338\item
     339providing statically type-safe interfaces that integrate with the \CFA polymorphic type-system and other language features.
     340\item
     341library extensions for executors, futures, and actors built on the basic mechanisms.
     342\item
     343a runtime system with no spurious wakeup.
     344\item
     345experimental results showing comparable performance of the new features with similar mechanisms in other concurrent programming-languages.
    333346\end{itemize}
    334347
  • doc/user/user.tex

    rec28948 r02af79b0  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Apr 14 11:02:34 2019
    14 %% Update Count     : 3443
     13%% Last Modified On : Sun May  5 18:24:50 2019
     14%% Update Count     : 3489
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    193193\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}).
     195
    195196
    196197\subsection{Background}
     
    431432\end{cfa}
    432433which 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}
    433506
    434507
  • libcfa/src/iostream.hfa

    rec28948 r02af79b0  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Apr 20 12:04:07 2019
    13 // Update Count     : 226
     12// Last Modified On : Fri May  3 22:55:04 2019
     13// Update Count     : 230
    1414//
    1515
     
    4848        void close( ostype & os );
    4949        ostype & write( ostype &, const char *, size_t );
    50         int fmt( ostype &, const char format[], ... );
     50        int fmt( ostype &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
    5151}; // ostream
    5252
     
    158158        istype & read( istype &, char *, size_t );
    159159        istype & ungetc( istype &, char );
    160         int fmt( istype &, const char format[], ... );
     160        int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
    161161}; // istream
    162162
  • src/BasicTypes-gen.cc

    rec28948 r02af79b0  
     1#include <algorithm>
    12#include <queue>
    23#include <iostream>
     
    340341        } // for
    341342        code << "\t}; // costMatrix" << endl;
     343
     344        // maximum conversion cost from int
     345        code << "\tstatic const int maxIntCost = " << *max_element(costMatrix[SignedInt], costMatrix[SignedInt] + NUMBER_OF_BASIC_TYPES) << ";" << endl;
    342346        code << "\t";                                                                           // indentation for end marker
    343 
     347       
    344348        if ( (start = str.find( ENDMK, start + 1 )) == string::npos ) Abort( "end", ConversionCost );
    345349        if ( (end = str.find( STARTMK, start + 1 )) == string::npos ) Abort( "start", ConversionCost );
  • src/CodeGen/CodeGenerator.cc

    rec28948 r02af79b0  
    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 : Sat May  5 09:08:32 2018
    13 // Update Count     : 494
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr May  2 10:47:00 2019
     13// Update Count     : 497
    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( CodeGenerator::tabsize ), output( os ), printLabels( *this ), options( pretty, genC, lineMarks, printExprTypes ), endl( *this ) {}
     119        CodeGenerator::CodeGenerator( std::ostream & os, const Options &options ) : indent( 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
     
    164165                previsit( (BaseSyntaxNode *)node );
    165166                GuardAction( [this, node](){
    166                         if ( printExprTypes && node->result ) {
    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                if (objectDecl->get_name().empty() && options.genC ) {
    198201                        // only generate an anonymous name when generating C code, otherwise it clutters the output too much
    199202                        static UniqueName name = { "__anonymous_object" };
    200203                        objectDecl->set_name( name.newName() );
     204            // Stops unused parameter warnings.
     205            if ( options.anonymousUnused ) {
     206                objectDecl->attributes.push_back( new Attribute( "unused" ) );
     207            }
    201208                }
    202209
     
    205212
    206213                handleStorageClass( objectDecl );
    207                 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty, genC );
     214                output << genType( objectDecl->get_type(), mangleName( objectDecl ), options.pretty, options.genC );
    208215
    209216                asmName( objectDecl );
     
    224231
    225232        void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) {
    226                 if( ! aggDecl->parameters.empty() && ! genC ) {
     233                if( ! aggDecl->parameters.empty() && ! options.genC ) {
    227234                        // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    228235                        output << "forall(";
     
    294301
    295302        void CodeGenerator::postvisit( TraitDecl * traitDecl ) {
    296                 assertf( ! genC, "TraitDecls should not reach code generation." );
     303                assertf( ! options.genC, "TraitDecls should not reach code generation." );
    297304                extension( traitDecl );
    298305                handleAggregate( traitDecl, "trait " );
     
    300307
    301308        void CodeGenerator::postvisit( TypedefDecl * typeDecl ) {
    302                 assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );
     309                assertf( ! options.genC, "Typedefs are removed and substituted in earlier passes." );
    303310                output << "typedef ";
    304                 output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl;
     311                output << genType( typeDecl->get_base(), typeDecl->get_name(), options ) << endl;
    305312        }
    306313
    307314        void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
    308                 assertf( ! genC, "TypeDecls should not reach code generation." );
     315                assertf( ! options.genC, "TypeDecls should not reach code generation." );
    309316                output << typeDecl->genTypeString() << " " << typeDecl->name;
    310317                if ( typeDecl->sized ) {
     
    371378
    372379        void CodeGenerator::postvisit( ConstructorInit * init ){
    373                 assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
     380                assertf( ! options.genC, "ConstructorInit nodes should not reach code generation." );
    374381                // pseudo-output for constructor/destructor pairs
    375382                output << "<ctorinit>{" << endl << ++indent << "ctor: ";
     
    507514                                        } else {
    508515                                                // no constructors with 0 or more than 2 parameters
    509                                                 assertf( ! genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
     516                                                assertf( ! options.genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
    510517                                                output << "(";
    511518                                                (*arg++)->accept( *visitor );
     
    604611                        // an lvalue cast, this has been taken out.
    605612                        output << "(";
    606                         output << genType( castExpr->get_result(), "", pretty, genC );
     613                        output << genType( castExpr->get_result(), "", options );
    607614                        output << ")";
    608615                } // if
     
    612619
    613620        void CodeGenerator::postvisit( KeywordCastExpr * castExpr ) {
    614                 assertf( ! genC, "KeywordCast should not reach code generation." );
     621                assertf( ! options.genC, "KeywordCast should not reach code generation." );
    615622                extension( castExpr );
    616623                output << "((" << castExpr->targetString() << " &)";
     
    620627
    621628        void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
    622                 assertf( ! genC, "VirtualCastExpr should not reach code generation." );
     629                assertf( ! options.genC, "VirtualCastExpr should not reach code generation." );
    623630                extension( castExpr );
    624631                output << "(virtual ";
     
    628635
    629636        void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
    630                 assertf( ! genC, "UntypedMemberExpr should not reach code generation." );
     637                assertf( ! options.genC, "UntypedMemberExpr should not reach code generation." );
    631638                extension( memberExpr );
    632639                memberExpr->get_aggregate()->accept( *visitor );
     
    661668                output << "sizeof(";
    662669                if ( sizeofExpr->get_isType() ) {
    663                         output << genType( sizeofExpr->get_type(), "", pretty, genC );
     670                        output << genType( sizeofExpr->get_type(), "", options );
    664671                } else {
    665672                        sizeofExpr->get_expr()->accept( *visitor );
     
    673680                output << "__alignof__(";
    674681                if ( alignofExpr->get_isType() ) {
    675                         output << genType( alignofExpr->get_type(), "", pretty, genC );
     682                        output << genType( alignofExpr->get_type(), "", options );
    676683                } else {
    677684                        alignofExpr->get_expr()->accept( *visitor );
     
    681688
    682689        void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
    683                 assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );
     690                assertf( ! options.genC, "UntypedOffsetofExpr should not reach code generation." );
    684691                output << "offsetof(";
    685                 output << genType( offsetofExpr->get_type(), "", pretty, genC );
     692                output << genType( offsetofExpr->get_type(), "", options );
    686693                output << ", " << offsetofExpr->get_member();
    687694                output << ")";
     
    691698                // use GCC builtin
    692699                output << "__builtin_offsetof(";
    693                 output << genType( offsetofExpr->get_type(), "", pretty, genC );
     700                output << genType( offsetofExpr->get_type(), "", options );
    694701                output << ", " << mangleName( offsetofExpr->get_member() );
    695702                output << ")";
     
    697704
    698705        void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
    699                 assertf( ! genC, "OffsetPackExpr should not reach code generation." );
    700                 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")";
     706                assertf( ! options.genC, "OffsetPackExpr should not reach code generation." );
     707                output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", options ) << ")";
    701708        }
    702709
     
    728735                extension( commaExpr );
    729736                output << "(";
    730                 if ( genC ) {
     737                if ( options.genC ) {
    731738                        // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
    732739                        commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
     
    739746
    740747        void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
    741                 assertf( ! genC, "TupleAssignExpr should not reach code generation." );
     748                assertf( ! options.genC, "TupleAssignExpr should not reach code generation." );
    742749                tupleExpr->stmtExpr->accept( *visitor );
    743750        }
    744751
    745752        void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
    746                 assertf( ! genC, "UntypedTupleExpr should not reach code generation." );
     753                assertf( ! options.genC, "UntypedTupleExpr should not reach code generation." );
    747754                extension( tupleExpr );
    748755                output << "[";
     
    752759
    753760        void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
    754                 assertf( ! genC, "TupleExpr should not reach code generation." );
     761                assertf( ! options.genC, "TupleExpr should not reach code generation." );
    755762                extension( tupleExpr );
    756763                output << "[";
     
    760767
    761768        void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
    762                 assertf( ! genC, "TupleIndexExpr should not reach code generation." );
     769                assertf( ! options.genC, "TupleIndexExpr should not reach code generation." );
    763770                extension( tupleExpr );
    764771                tupleExpr->get_tuple()->accept( *visitor );
     
    767774
    768775        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 );
     776                // if ( options.genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
     777                // assertf( ! options.genC, "TypeExpr should not reach code generation." );
     778                if ( ! options.genC ) {
     779                        output << genType( typeExpr->get_type(), "", options );
    773780                }
    774781        }
     
    788795        void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
    789796                assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
    790                 output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
     797                output << "(" << genType( compLitExpr->get_result(), "", options ) << ")";
    791798                compLitExpr->get_initializer()->accept( *visitor );
    792799        }
    793800
    794801        void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
    795                 assertf( ! genC, "Unique expressions should not reach code generation." );
     802                assertf( ! options.genC, "Unique expressions should not reach code generation." );
    796803                output << "unq<" << unqExpr->get_id() << ">{ ";
    797804                unqExpr->get_expr()->accept( *visitor );
     
    829836
    830837        void CodeGenerator::postvisit( ConstructorExpr * expr ) {
    831                 assertf( ! genC, "Unique expressions should not reach code generation." );
     838                assertf( ! options.genC, "Unique expressions should not reach code generation." );
    832839                expr->callExpr->accept( *visitor );
    833840        }
    834841
    835842        void CodeGenerator::postvisit( DeletedExpr * expr ) {
    836                 assertf( ! genC, "Deleted expressions should not reach code generation." );
     843                assertf( ! options.genC, "Deleted expressions should not reach code generation." );
    837844                expr->expr->accept( *visitor );
    838845        }
    839846
    840847        void CodeGenerator::postvisit( DefaultArgExpr * arg ) {
    841                 assertf( ! genC, "Default argument expressions should not reach code generation." );
     848                assertf( ! options.genC, "Default argument expressions should not reach code generation." );
    842849                arg->expr->accept( *visitor );
    843850        }
    844851
    845852        void CodeGenerator::postvisit( GenericExpr * expr ) {
    846                 assertf( ! genC, "C11 _Generic expressions should not reach code generation." );
     853                assertf( ! options.genC, "C11 _Generic expressions should not reach code generation." );
    847854                output << "_Generic(";
    848855                expr->control->accept( *visitor );
     
    854861                                output << "default: ";
    855862                        } else {
    856                                 output << genType( assoc.type, "", pretty, genC ) << ": ";
     863                                output << genType( assoc.type, "", options ) << ": ";
    857864                        }
    858865                        assoc.expr->accept( *visitor );
     
    889896        void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
    890897                assert( exprStmt );
    891                 if ( genC ) {
     898                if ( options.genC ) {
    892899                        // cast the top-level expression to void to reduce gcc warnings.
    893900                        exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
     
    9991006                  case BranchStmt::FallThrough:
    10001007                  case BranchStmt::FallThroughDefault:
    1001                         assertf( ! genC, "fallthru should not reach code generation." );
     1008                        assertf( ! options.genC, "fallthru should not reach code generation." );
    10021009                  output << "fallthru";
    10031010                        break;
    10041011                } // switch
    10051012                // print branch target for labelled break/continue/fallthru in debug mode
    1006                 if ( ! genC && branchStmt->get_type() != BranchStmt::Goto ) {
     1013                if ( ! options.genC && branchStmt->get_type() != BranchStmt::Goto ) {
    10071014                        if ( ! branchStmt->get_target().empty() ) {
    10081015                                output << " " << branchStmt->get_target();
     
    10211028
    10221029        void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
    1023                 assertf( ! genC, "Throw statements should not reach code generation." );
     1030                assertf( ! options.genC, "Throw statements should not reach code generation." );
    10241031
    10251032                output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ?
     
    10361043        }
    10371044        void CodeGenerator::postvisit( CatchStmt * stmt ) {
    1038                 assertf( ! genC, "Catch statements should not reach code generation." );
     1045                assertf( ! options.genC, "Catch statements should not reach code generation." );
    10391046
    10401047                output << ((stmt->get_kind() == CatchStmt::Terminate) ?
     
    10531060
    10541061        void CodeGenerator::postvisit( WaitForStmt * stmt ) {
    1055                 assertf( ! genC, "Waitfor statements should not reach code generation." );
     1062                assertf( ! options.genC, "Waitfor statements should not reach code generation." );
    10561063
    10571064                bool first = true;
     
    10991106
    11001107        void CodeGenerator::postvisit( WithStmt * with ) {
    1101                 if ( ! genC ) {
     1108                if ( ! options.genC ) {
    11021109                        output << "with ( ";
    11031110                        genCommaList( with->exprs.begin(), with->exprs.end() );
     
    11651172
    11661173        void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
    1167                 assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );
     1174                assertf( ! options.genC, "ImplicitCtorDtorStmts should not reach code generation." );
    11681175                stmt->callStmt->accept( *visitor );
    11691176        }
  • src/CodeGen/CodeGenerator.h

    rec28948 r02af79b0  
    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
     
    144146                std::ostream & output;
    145147                LabelPrinter printLabels;
    146                 bool pretty = false;  // pretty print
    147                 bool genC = false;    // true if output has to be C code
    148                 bool lineMarks = false;
    149                 bool printExprTypes = false;
     148                Options options;
    150149        public:
    151150                LineEnder endl;
  • src/CodeGen/GenType.cc

    rec28948 r02af79b0  
    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"
     
    2828        struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
    2929                std::string typeString;
    30                 GenType( const std::string &typeString, bool pretty, bool genC, bool lineMarks );
     30                GenType( const std::string &typeString, const Options &options );
    3131
    3232                void previsit( BaseSyntaxNode * );
     
    5757                void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
    5858
    59                 bool pretty = false;    // pretty print
    60                 bool genC = false;      // generating C code?
    61                 bool lineMarks = false; // lineMarks on for CodeGenerator?
     59                Options options;
    6260        };
    6361
    64         std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
    65                 PassVisitor<GenType> gt( baseString, pretty, genC, lineMarks );
     62        std::string genType( Type *type, const std::string &baseString, const Options &options ) {
     63                PassVisitor<GenType> gt( baseString, options );
    6664                std::ostringstream os;
    6765
    6866                if ( ! type->get_attributes().empty() ) {
    69                         PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     67                        PassVisitor<CodeGenerator> cg( os, options );
    7068                        cg.pass.genAttributes( type->get_attributes() );
    7169                } // if
     
    7573        }
    7674
    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 ) {}
     75        std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
     76                return genType( type, baseString, Options(pretty, genC, lineMarks, false ) );
     77        }
     78
     79        std::string genPrettyType( Type * type, const std::string & baseString ) {
     80                return genType( type, baseString, true, false );
     81        }
     82
     83        GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {}
    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
    293295        void GenType::postvisit( GlobalScopeType * globalType ) {
    294                 assertf( ! genC, "Global scope type should not reach code generation." );
     296                assertf( ! options.genC, "Global scope type should not reach code generation." );
    295297                handleQualifiers( globalType );
    296298        }
    297299
    298300        void GenType::postvisit( TraitInstType * inst ) {
    299                 assertf( ! genC, "Trait types should not reach code generation." );
     301                assertf( ! options.genC, "Trait types should not reach code generation." );
    300302                typeString = inst->name + " " + typeString;
    301303                handleQualifiers( inst );
     
    304306        void GenType::postvisit( TypeofType * typeof ) {
    305307                std::ostringstream os;
    306                 PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
     308                PassVisitor<CodeGenerator> cg( os, options );
    307309                os << "typeof(";
    308310                typeof->expr->accept( cg );
     
    313315
    314316        void GenType::postvisit( QualifiedType * qualType ) {
    315                 assertf( ! genC, "Qualified types should not reach code generation." );
    316                 std::ostringstream os;
    317                 os << genType( qualType->parent, "", pretty, genC, lineMarks ) << "." << genType( qualType->child, "", pretty, genC, lineMarks ) << typeString;
     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;
    318320                typeString = os.str();
    319321                handleQualifiers( qualType );
     
    333335                        typeString = "_Atomic " + typeString;
    334336                } // if
    335                 if ( type->get_lvalue() && ! genC ) {
     337                if ( type->get_lvalue() && ! options.genC ) {
    336338                        // when not generating C code, print lvalue for debugging.
    337339                        typeString = "lvalue " + typeString;
  • src/CodeGen/GenType.h

    rec28948 r02af79b0  
    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/Common/Assert.cc

    rec28948 r02af79b0  
    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/PassVisitor.h

    rec28948 r02af79b0  
    44
    55#include <stack>
     6#include <type_traits>
    67
    78#include "Common/Stats.h"
     
    301302
    302303
    303         TypeSubstitution **             get_env_ptr    () { return env_impl             ( pass, 0); }
     304        auto                                    get_env_ptr    () -> decltype(env_impl( pass, 0)) { return env_impl( pass, 0); }
    304305        std::list< Statement* > *       get_beforeStmts() { return stmtsToAddBefore_impl( pass, 0); }
    305306        std::list< Statement* > *       get_afterStmts () { return stmtsToAddAfter_impl ( pass, 0); }
     
    348349};
    349350
     351class WithConstTypeSubstitution {
     352protected:
     353        WithConstTypeSubstitution() = default;
     354        ~WithConstTypeSubstitution() = default;
     355
     356public:
     357        const TypeSubstitution * env = nullptr;
     358};
     359
    350360class WithStmtsToAdd {
    351361protected:
  • src/Common/PassVisitor.impl.h

    rec28948 r02af79b0  
    2020
    2121#define MUTATE_END( type, node )                \
    22         return call_postmutate< type * >( node ); \
     22        auto __return = call_postmutate< type * >( node ); \
     23        assert( __return ); \
     24        return __return;
    2325
    2426
     
    253255
    254256        // don't want statements from outer CompoundStmts to be added to this CompoundStmt
    255         ValueGuardPtr< TypeSubstitution * >  oldEnv        ( get_env_ptr    () );
     257        ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    256258        ValueGuardPtr< DeclList_t >          oldBeforeDecls( get_beforeDecls() );
    257259        ValueGuardPtr< DeclList_t >          oldAfterDecls ( get_afterDecls () );
     
    19951997
    19961998        // don't want statements from outer CompoundStmts to be added to this StmtExpr
    1997         ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
     1999        ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    19982000        ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
    19992001        ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
     
    20122014
    20132015        // don't want statements from outer CompoundStmts to be added to this StmtExpr
    2014         ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
     2016        ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
    20152017        ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
    20162018        ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
  • src/Common/PassVisitor.proto.h

    rec28948 r02af79b0  
    165165static inline type * name##_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) { return nullptr;}    \
    166166
    167 FIELD_PTR( TypeSubstitution *, env )
     167FIELD_PTR( const TypeSubstitution *, env )
    168168FIELD_PTR( std::list< Statement* >, stmtsToAddBefore )
    169169FIELD_PTR( std::list< Statement* >, stmtsToAddAfter  )
     
    174174FIELD_PTR( PassVisitor<pass_type> * const, visitor )
    175175
     176#undef FIELD_PTR
     177
    176178//---------------------------------------------------------
    177179// Indexer
  • src/CompilationState.cc

    rec28948 r02af79b0  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon Ju1 30 10:47:01 2018
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Mon Ju1 30 10:46:25 2018
    13 // Update Count     : 2
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri May  3 13:45:23 2019
     13// Update Count     : 4
    1414//
    1515
    16 bool
     16int
    1717        astp = false,
    1818        bresolvep = false,
     
    2626        libcfap = false,
    2727        nopreludep = false,
    28         noprotop = false,
     28        genproto = false,
    2929        nomainp = false,
    3030        parsep = false,
  • src/CompilationState.h

    rec28948 r02af79b0  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon Ju1 30 10:47:01 2018
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Mon Ju1 30 10:46:25 2018
    13 // Update Count     : 2
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri May  3 13:43:21 2019
     13// Update Count     : 4
    1414//
    1515
    1616extern int yydebug;                   // set for -g flag (Grammar)
    17 extern bool
     17extern int
    1818        astp,
    1919        bresolvep,
     
    2727        libcfap,
    2828        nopreludep,
    29         noprotop,
     29        genproto,
    3030        nomainp,
    3131        parsep,
  • src/ControlStruct/ExceptTranslate.cc

    rec28948 r02af79b0  
    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/GenPoly/Box.cc

    rec28948 r02af79b0  
    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();
     
    17641764
    17651765                Expression *PolyGenericCalculator::postmutate( SizeofExpr *sizeofExpr ) {
    1766                         Type *ty = sizeofExpr->get_isType() ? 
     1766                        Type *ty = sizeofExpr->get_isType() ?
    17671767                                sizeofExpr->get_type() : sizeofExpr->get_expr()->get_result();
    1768                        
     1768
    17691769                        Expression * gen = genSizeof( ty );
    17701770                        if ( gen ) {
  • src/GenPoly/GenPoly.cc

    rec28948 r02af79b0  
    440440        }
    441441
    442         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env ) {
     442        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
    443443                // is parameter is not polymorphic, don't need to box
    444444                if ( ! isPolyType( param, exprTyVars ) ) return false;
     
    450450        }
    451451
    452         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env ) {
     452        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
    453453                FunctionType * function = getFunctionType( appExpr->function->result );
    454454                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
  • src/GenPoly/GenPoly.h

    rec28948 r02af79b0  
    8181
    8282        /// true if arg requires boxing given exprTyVars
    83         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env );
     83        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );
    8484
    8585        /// true if arg requires boxing in the call to appExpr
    86         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env );
     86        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );
    8787
    8888        /// Adds the type variable `tyVar` to `tyVarMap`
  • src/GenPoly/InstantiateGeneric.cc

    rec28948 r02af79b0  
    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/Specialize.cc

    rec28948 r02af79b0  
    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        }
  • src/InitTweak/FixInit.cc

    rec28948 r02af79b0  
    7272                };
    7373
    74                 struct InsertImplicitCalls : public WithTypeSubstitution {
     74                struct InsertImplicitCalls : public WithConstTypeSubstitution {
    7575                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
    7676                        /// function calls need their parameters to be copy constructed
     
    187187                };
    188188
    189                 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution {
     189                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithConstTypeSubstitution {
    190190                  public:
    191191                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
  • src/ResolvExpr/ConversionCost.cc

    rec28948 r02af79b0  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 26 16:33:04 2019
    13 // Update Count     : 24
     12// Last Modified On : Mon May  6 14:18:22 2019
     13// Update Count     : 25
    1414//
    1515
     
    249249                /*_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, },
    250250        }; // costMatrix
     251        static const int maxIntCost = 15;
    251252        // GENERATED END
    252253        static_assert(
     
    461462                        } // if
    462463                } else if ( dynamic_cast< PointerType* >( dest ) ) {
    463                         cost = Cost::safe;
     464                        cost = Cost::zero;
     465                        cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
    464466                } // if
    465467        }
  • src/ResolvExpr/RenameVars.cc

    rec28948 r02af79b0  
    1010// Created On       : Sun May 17 12:05:18 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  2 17:36:32 2016
    13 // Update Count     : 5
     12// Last Modified On : Tue Apr 30 17:07:57 2019
     13// Update Count     : 7
    1414//
    1515
     
    3939                  private:
    4040                        int level, resetCount;
    41                         std::list< std::map< std::string, std::string > > mapStack;
     41                        std::list< std::unordered_map< std::string, std::string > > mapStack;
    4242                };
    4343
     
    5555        namespace {
    5656                RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) {
    57                         mapStack.push_front( std::map< std::string, std::string >() );
     57                        mapStack.push_front( std::unordered_map< std::string, std::string >() );
    5858                }
    5959
     
    6565                void RenameVars::previsit( TypeInstType * instType ) {
    6666                        previsit( (Type *)instType );
    67                         std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name );
     67                        std::unordered_map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name );
    6868                        if ( i != mapStack.front().end() ) {
    6969                                instType->name = i->second;
  • src/ResolvExpr/TypeEnvironment.h

    rec28948 r02af79b0  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:24:58 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Apr 30 23:04:10 2019
     13// Update Count     : 9
    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
    2324#include <utility>                     // for move, swap
     
    6465                AssertionSetValue() : isUsed(false), resnSlot(0) {}
    6566        };
    66         typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet;
    67         typedef std::map< std::string, TypeDecl::Data > OpenVarSet;
     67        typedef std::map< DeclarationWithType *, AssertionSetValue, AssertCompare > AssertionSet;
     68        typedef std::unordered_map< std::string, TypeDecl::Data > OpenVarSet;
    6869
    6970        /// merges one set of open vars into another
  • src/SynTree/Declaration.h

    rec28948 r02af79b0  
    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
     
    166167        CompoundStmt *get_statements() const { return statements; }
    167168        void set_statements( CompoundStmt *newValue ) { statements = newValue; }
     169        bool has_body() const { return NULL != statements; }
    168170
    169171        static FunctionDecl * newFunction( const std::string & name, FunctionType * type, CompoundStmt * statements );
     
    334336        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    335337  private:
    336         std::map< std::string, long long int > enumValues;
     338        std::unordered_map< std::string, long long int > enumValues;
    337339        virtual std::string typeString() const override;
    338340};
  • src/SynTree/TypeSubstitution.cc

    rec28948 r02af79b0  
    108108namespace {
    109109        struct EnvTrimmer {
    110                 TypeSubstitution * env, * newEnv;
    111                 EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
     110                const TypeSubstitution * env;
     111                TypeSubstitution * newEnv;
     112                EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
    112113                void previsit( TypeDecl * tyDecl ) {
    113114                        // transfer known bindings for seen type variables
     
    120121
    121122/// reduce environment to just the parts that are referenced in a given expression
    122 TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, TypeSubstitution * env ) {
     123TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, const TypeSubstitution * env ) {
    123124        if ( env ) {
    124125                TypeSubstitution * newEnv = new TypeSubstitution();
  • src/SynTree/TypeSubstitution.h

    rec28948 r02af79b0  
    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 );
     
    5656
    5757        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
    58         static TypeSubstitution * newFromExpr( Expression * expr, TypeSubstitution * env );
     58        static TypeSubstitution * newFromExpr( Expression * expr, const TypeSubstitution * env );
    5959
    6060        void normalize();
     
    7878        friend class PassVisitor;
    7979
    80         typedef std::map< std::string, Type* > TypeEnvType;
    81         typedef std::map< std::string, Expression* > VarEnvType;
     80        typedef std::unordered_map< std::string, Type * > TypeEnvType;
     81        typedef std::unordered_map< std::string, Expression * > VarEnvType;
    8282        TypeEnvType typeEnv;
    8383        VarEnvType varEnv;
     
    9898        ActualIterator actualIt = actualBegin;
    9999        for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) {
    100                 if ( TypeDecl *formal = dynamic_cast< TypeDecl* >( *formalIt ) ) {
    101                         if ( TypeExpr *actual = dynamic_cast< TypeExpr* >( *actualIt ) ) {
     100                if ( TypeDecl *formal = dynamic_cast< TypeDecl * >( *formalIt ) ) {
     101                        if ( TypeExpr *actual = dynamic_cast< TypeExpr * >( *actualIt ) ) {
    102102                                if ( formal->get_name() != "" ) {
    103103                                        TypeEnvType::iterator i = typeEnv.find( formal->get_name() );
     
    130130// definitition must happen after PassVisitor is included so that WithGuards can be used
    131131struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
    132                 Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
     132                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    133133
    134134                Type * postmutate( TypeInstType * aggregateUseType );
     
    143143                void premutate( UnionInstType * aggregateUseType );
    144144
    145                 TypeSubstitution & sub;
     145                const TypeSubstitution & sub;
    146146                int subCount = 0;
    147147                bool freeOnly;
    148                 typedef std::set< std::string > BoundVarsType;
     148                typedef std::unordered_set< std::string > BoundVarsType;
    149149                BoundVarsType boundVars;
    150150};
    151151
    152152template< typename SynTreeClass >
    153 int TypeSubstitution::apply( SynTreeClass *&input ) {
     153int TypeSubstitution::apply( SynTreeClass *&input ) const {
    154154        assert( input );
    155155        PassVisitor<Substituter> sub( *this, false );
     
    163163
    164164template< typename SynTreeClass >
    165 int TypeSubstitution::applyFree( SynTreeClass *&input ) {
     165int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
    166166        assert( input );
    167167        PassVisitor<Substituter> sub( *this, true );
  • src/Tuples/TupleExpansion.cc

    rec28948 r02af79b0  
    5858                };
    5959
    60                 struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithTypeSubstitution {
     60                struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithConstTypeSubstitution {
    6161                        Type * postmutate( TupleType * tupleType );
    6262
  • src/include/cassert

    rec28948 r02af79b0  
    4545}
    4646
     47extern void abort(const char *fmt, ...  ) noexcept __attribute__((noreturn, format(printf, 1, 2)));
    4748// Local Variables: //
    4849// tab-width: 4 //
  • src/main.cc

    rec28948 r02af79b0  
    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 : Sat Feb 16 09:14:04 2019
    13 // Update Count     : 500
     12// Last Modified On : Fri May  3 16:10:52 2019
     13// Update Count     : 599
    1414//
    1515
     
    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
     
    3940#include "Common/Stats.h"
    4041#include "Common/PassVisitor.h"
     42// #include "AST/Pass.hpp"
    4143#include "Common/SemanticError.h"           // for SemanticError
    4244#include "Common/UnimplementedError.h"      // for UnimplementedError
     
    6567using namespace std;
    6668
    67 void NewPass(const char * const name) {
    68         Stats::Heap::newPass(name);
     69static void NewPass( const char * const name ) {
     70        Stats::Heap::newPass( name );
    6971        using namespace Stats::Counters;
    70        
    7172        {
    72                 static auto group = build<CounterGroup>("Pass Visitor");
    73                 auto pass = build<CounterGroup>(name, group);
     73                static auto group = build<CounterGroup>( "Pass Visitor" );
     74                auto pass = build<CounterGroup>( name, group );
    7475                pass_visitor_stats.depth = 0;
    75                 pass_visitor_stats.avg = build<AverageCounter<double>>("Average Depth", pass);
    76                 pass_visitor_stats.max = build<MaxCounter<double>>("Max Depth", pass);
     76                pass_visitor_stats.avg = build<AverageCounter<double>>( "Average Depth", pass );
     77                pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass );
    7778        }
    78 
    7979        {
    80                 static auto group = build<CounterGroup>("Syntax Node");
    81                 auto pass = build<CounterGroup>(name, group);
    82                 BaseSyntaxNode::new_nodes = build<SimpleCounter>("Allocs", pass);
     80                static auto group = build<CounterGroup>( "Syntax Node" );
     81                auto pass = build<CounterGroup>( name, group );
     82                BaseSyntaxNode::new_nodes = build<SimpleCounter>( "Allocs", pass );
    8383        }
    8484}
    8585
    86 #define PASS(name, pass)                  \
     86#define PASS( name, pass )                  \
    8787        if ( errorp ) { cerr << name << endl; } \
    8888        NewPass(name);                          \
     
    9595DeclarationNode * parseTree = nullptr;                                  // program parse tree
    9696
    97 std::string PreludeDirector = "";
     97static std::string PreludeDirector = "";
    9898
    9999static void parse_cmdline( int argc, char *argv[], const char *& filename );
     
    151151} // backtrace
    152152
    153 void sigSegvBusHandler( int sig_num ) {
     153static void sigSegvBusHandler( int sig_num ) {
    154154        cerr << "*CFA runtime error* program cfa-cpp terminated with "
    155155                 <<     (sig_num == SIGSEGV ? "segment fault" : "bus error")
     
    157157        backtrace( 2 );                                                                         // skip first 2 stack frames
    158158        //_exit( EXIT_FAILURE );
    159         abort();
     159        abort();                                                                                        // cause core dump for debugging
    160160} // sigSegvBusHandler
    161161
    162 void sigAbortHandler( __attribute__((unused)) int sig_num ) {
     162static void sigAbortHandler( __attribute__((unused)) int sig_num ) {
    163163        backtrace( 6 );                                                                         // skip first 6 stack frames
    164164        signal( SIGABRT, SIG_DFL);                                                      // reset default signal handler
     
    240240                        parseTree->printList( cout );
    241241                        delete parseTree;
    242                         return 0;
     242                        return EXIT_SUCCESS;
    243243                } // if
    244244
     
    249249                if ( astp ) {
    250250                        dump( translationUnit );
    251                         return 0;
     251                        return EXIT_SUCCESS;
    252252                } // if
    253253
     
    262262                if ( symtabp ) {
    263263                        deleteAll( translationUnit );
    264                         return 0;
     264                        return EXIT_SUCCESS;
    265265                } // if
    266266
     
    268268                        PassVisitor<ResolvExpr::AlternativePrinter> printer( cout );
    269269                        acceptAll( translationUnit, printer );
    270                         return 0;
     270                        return EXIT_SUCCESS;
    271271                } // if
    272272
    273273                if ( validp ) {
    274274                        dump( translationUnit );
    275                         return 0;
     275                        return EXIT_SUCCESS;
    276276                } // if
    277277
     
    288288                        CodeTools::printDeclStats( translationUnit );
    289289                        deleteAll( translationUnit );
    290                         return 0;
    291                 }
     290                        return EXIT_SUCCESS;
     291                } // if
    292292
    293293                if ( bresolvep ) {
    294294                        dump( translationUnit );
    295                         return 0;
     295                        return EXIT_SUCCESS;
    296296                } // if
    297297
     
    300300                if ( resolvprotop ) {
    301301                        CodeTools::dumpAsResolvProto( translationUnit );
    302                         return 0;
    303                 }
     302                        return EXIT_SUCCESS;
     303                } // if
    304304
    305305                PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    306306                if ( exprp ) {
    307307                        dump( translationUnit );
    308                         return 0;
     308                        return EXIT_SUCCESS;
    309309                } // if
    310310
     
    313313                if ( ctorinitp ) {
    314314                        dump ( translationUnit );
    315                         return 0;
     315                        return EXIT_SUCCESS;
    316316                } // if
    317317
     
    328328                if ( tuplep ) {
    329329                        dump( translationUnit );
    330                         return 0;
    331                 }
     330                        return EXIT_SUCCESS;
     331                } // if
    332332
    333333                PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM
     
    336336                if ( genericsp ) {
    337337                        dump( translationUnit );
    338                         return 0;
    339                 }
     338                        return EXIT_SUCCESS;
     339                } // if
    340340                PASS( "Convert L-Value", GenPoly::convertLvalue( translationUnit ) );
    341341
     
    343343                if ( bboxp ) {
    344344                        dump( translationUnit );
    345                         return 0;
     345                        return EXIT_SUCCESS;
    346346                } // if
    347347                PASS( "Box", GenPoly::box( translationUnit ) );
     
    349349                if ( bcodegenp ) {
    350350                        dump( translationUnit );
    351                         return 0;
    352                 }
     351                        return EXIT_SUCCESS;
     352                } // if
    353353
    354354                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     
    357357
    358358                CodeTools::fillLocations( translationUnit );
    359                 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp, true, linemarks ) );
     359                PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );
    360360
    361361                CodeGen::FixMain::fix( *output, (PreludeDirector + "/bootloader.c").c_str() );
     
    373373                        delete output;
    374374                } // if
    375                 return 1;
     375                return EXIT_FAILURE;
    376376        } catch ( UnimplementedError &e ) {
    377377                cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
     
    379379                        delete output;
    380380                } // if
    381                 return 1;
     381                return EXIT_FAILURE;
    382382        } catch ( CompilerError &e ) {
    383383                cerr << "Compiler Error: " << e.get_what() << endl;
     
    386386                        delete output;
    387387                } // if
    388                 return 1;
    389         } catch(...) {
     388                return EXIT_FAILURE;
     389        } catch ( ... ) {
    390390                std::exception_ptr eptr = std::current_exception();
    391391                try {
    392392                        if (eptr) {
    393393                                std::rethrow_exception(eptr);
    394                         }
    395                         else {
    396                                 std::cerr << "Exception Uncaught and Unkown" << std::endl;
    397                         }
     394                        } else {
     395                                std::cerr << "Exception Uncaught and Unknown" << std::endl;
     396                        } // if
    398397                } catch(const std::exception& e) {
    399398                        std::cerr << "Uncaught Exception \"" << e.what() << "\"\n";
    400                 }
    401                 return 1;
    402         }// try
     399                } // try
     400                return EXIT_FAILURE;
     401        } // try
    403402
    404403        deleteAll( translationUnit );
    405404        Stats::print();
    406 
    407         return 0;
     405        return EXIT_SUCCESS;
    408406} // main
    409407
    410 void parse_cmdline( int argc, char * argv[], const char *& filename ) {
    411         enum { Ast, Bbox, Bresolver, CtorInitFix, DeclStats, Expr, ExprAlt, Grammar, LibCFA, Linemarks, Nolinemarks, Nopreamble, Parse, PreludeDir, Prototypes, Resolver, ResolvProto, Stats, Symbol, Tree, TupleExpansion, Validate};
    412 
    413         static struct option long_opts[] = {
    414                 { "ast", no_argument, 0, Ast },
    415                 { "before-box", no_argument, 0, Bbox },
    416                 { "before-resolver", no_argument, 0, Bresolver },
    417                 { "ctorinitfix", no_argument, 0, CtorInitFix },
    418                 { "decl-stats", no_argument, 0, DeclStats },
    419                 { "expr", no_argument, 0, Expr },
    420                 { "expralt", no_argument, 0, ExprAlt },
    421                 { "grammar", no_argument, 0, Grammar },
    422                 { "libcfa", no_argument, 0, LibCFA },
    423                 { "line-marks", no_argument, 0, Linemarks },
    424                 { "no-line-marks", no_argument, 0, Nolinemarks },
    425                 { "no-preamble", no_argument, 0, Nopreamble },
    426                 { "parse", no_argument, 0, Parse },
    427                 { "prelude-dir", required_argument, 0, PreludeDir },
    428                 { "no-prototypes", no_argument, 0, Prototypes },
    429                 { "resolver", no_argument, 0, Resolver },
    430                 { "resolv-proto", no_argument, 0, ResolvProto },
    431                 { "stats", required_argument, 0, Stats },
    432                 { "symbol", no_argument, 0, Symbol },
    433                 { "tree", no_argument, 0, Tree },
    434                 { "tuple-expansion", no_argument, 0, TupleExpansion },
    435                 { "validate", no_argument, 0, Validate },
    436                 { 0, 0, 0, 0 }
    437         }; // long_opts
    438         int long_index;
    439 
     408
     409static const char optstring[] = ":hlLmNn:pP:S:twW:D:F:";
     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        { "", no_argument, nullptr, 0 },                                        // -w
     425        { "", no_argument, nullptr, 0 },                                        // -W
     426        { "", no_argument, nullptr, 0 },                                        // -D
     427        { "", no_argument, nullptr, 0 },                                        // -F
     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        "build in tree",                                                                        // -t
     443        "",                                                                                                     // -w
     444        "",                                                                                                     // -W
     445        "",                                                                                                     // -D
     446        "",                                                                                                     // -F
     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        { "altexpr", expraltp, true, "alternatives for expressions" },
     458        { "ascodegen", codegenp, true, "as codegen rather than AST" },
     459        { "ast", astp, true, "AST after parsing" },
     460        { "astdecl", validp, true, "AST after declaration validation pass" },
     461        { "asterr", errorp, true, "AST on error" },
     462        { "astexpr", exprp, true, "AST after expression analysis" },
     463        { "astgen", genericsp, true, "AST after instantiate generics" },
     464        { "box", bboxp, true, "before box step" },
     465        { "ctordtor", ctorinitp, true, "after ctor/dtor are replaced" },
     466        { "codegen", bcodegenp, true, "before code generation" },
     467        { "declstats", declstatsp, true, "code property statistics" },
     468        { "parse", yydebug, true, "yacc (parsing) debug information" },
     469        { "pretty", prettycodegenp, true, "prettyprint for ascodegen flag" },
     470        { "resolver", bresolvep, true, "before resolver step" },
     471        { "rproto", resolvprotop, true, "resolver-proto instance" },
     472        { "rsteps", resolvep, true, "resolver steps" },
     473        { "symevt", symtabp, true, "symbol table events" },
     474        { "tree", parsep, true, "parse tree" },
     475        { "tuple", tuplep, true, "after tuple expansion" },
     476};
     477enum { printoptsSize = sizeof( printopts ) / sizeof( printopts[0] ) };
     478
     479static void usage( char *argv[] ) {
     480    cout << "Usage: " << argv[0] << " options are:" << endl;
     481        int i = 0, j = 1;                                                                       // j skips starting colon
     482        for ( ; long_opts[i].name != 0 && optstring[j] != '\0'; i += 1, j += 1 ) {
     483                if ( long_opts[i].name[0] != '\0' ) {                   // hidden option, internal usage only
     484                        if ( strcmp( long_opts[i].name, "prelude-dir" ) != 0 ) { // flag
     485                                cout << "  -" << optstring[j] << ",";
     486                        } else {                                                                        // no flag
     487                                j -= 1;                                                                 // compensate
     488                                cout << "     ";
     489                        } // if
     490                        cout << " --" << left << setw(12) << long_opts[i].name << "  ";
     491                        if ( strcmp( long_opts[i].name, "print" ) == 0 ) {
     492                                cout << "one of: " << endl;
     493                                for ( int i = 0; i < printoptsSize; i += 1 ) {
     494                                        cout << setw(10) << " " << left << setw(10) << printopts[i].name << "  " << printopts[i].descript << endl;
     495                                } // for
     496                        } else {
     497                                cout << description[i] << endl;
     498                        } // if
     499                } // if
     500                if ( optstring[j + 1] == ':' ) j += 1;
     501        } // for
     502        if ( long_opts[i].name != 0 || optstring[j] != '\0' ) assertf( false, "internal error, mismatch of option flags and names\n" );
     503    exit( EXIT_FAILURE );
     504} // usage
     505
     506static void parse_cmdline( int argc, char * argv[], const char *& filename ) {
    440507        opterr = 0;                                                                                     // (global) prevent getopt from printing error messages
    441508
    442509        bool Wsuppress = false, Werror = false;
    443510        int c;
    444         while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrRstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
     511        while ( (c = getopt_long( argc, argv, optstring, long_opts, nullptr )) != -1 ) {
    445512                switch ( c ) {
    446                         case Ast:
    447                         case 'a':                                                                               // dump AST
    448                         astp = true;
    449                         break;
    450                         case Bresolver:
    451                         case 'b':                                                                               // print before resolver steps
    452                         bresolvep = true;
    453                         break;
    454                         case 'B':                                                                               // print before box steps
    455                         bboxp = true;
    456                         break;
    457                         case CtorInitFix:
    458                         case 'c':                                                                               // print after constructors and destructors are replaced
    459                         ctorinitp = true;
    460                         break;
    461                         case 'C':                                                                               // print before code generation
    462                         bcodegenp = true;
    463                         break;
    464                         case DeclStats:
    465                         case 'd':
    466                                 declstatsp = true;
    467                         break;
    468                         case Expr:
    469                         case 'e':                                                                               // dump AST after expression analysis
    470                         exprp = true;
    471                         break;
    472                         case ExprAlt:
    473                         case 'f':                                                                               // print alternatives for expressions
    474                         expraltp = true;
    475                         break;
    476                         case Grammar:
    477                         case 'g':                                                                               // bison debugging info (grammar rules)
    478                         yydebug = true;
    479                         break;
    480                         case 'G':                                                                               // dump AST after instantiate generics
    481                         genericsp = true;
    482                         break;
    483                         case LibCFA:
    484                         case 'l':                                                                               // generate libcfa.c
     513                  case 'h':                                                                             // help message
     514                        usage( argv );                                                          // no return
     515                        break;
     516                  case 'l':                                                                             // generate libcfa.c
    485517                        libcfap = true;
    486518                        break;
    487                         case Linemarks:
    488                         case 'L':                                                                               // print lines marks
     519                  case 'L':                                                                             // generate line marks
    489520                        linemarks = true;
    490521                        break;
    491                         case Nopreamble:
    492                         case 'n':                                                                               // do not read preamble
     522                  case 'm':                                                                             // do not replace main
     523                        nomainp = true;
     524                        break;
     525                  case 'N':                                                                             // do not generate line marks
     526                        linemarks = false;
     527                        break;
     528                  case 'n':                                                                             // do not read prelude
    493529                        nopreludep = true;
    494530                        break;
    495                         case Nolinemarks:
    496                         case 'N':                                                                               // suppress line marks
    497                         linemarks = false;
    498                         break;
    499                         case Prototypes:
    500                         case 'p':                                                                               // generate prototypes for preamble functions
    501                         noprotop = true;
    502                         break;
    503                         case PreludeDir:
    504                                 PreludeDirector = optarg;
    505                         break;
    506                         case 'm':                                                                               // don't replace the main
    507                                 nomainp = true;
    508                         break;
    509                         case Parse:
    510                         case 'q':                                                                               // dump parse tree
    511                         parsep = true;
    512                         break;
    513                         case Resolver:
    514                         case 'r':                                                                               // print resolver steps
    515                         resolvep = true;
    516                         break;
    517                         case 'R':                                                                               // dump resolv-proto instance
    518                         resolvprotop = true;
    519                         break;
    520                         case Stats:
    521                                 Stats::parse_params(optarg);
    522                         break;
    523                         case Symbol:
    524                         case 's':                                                                               // print symbol table events
    525                         symtabp = true;
    526                         break;
    527                         case Tree:
    528                         case 't':                                                                               // build in tree
     531                  case 'p':                                                                             // generate prototypes for prelude functions
     532                        genproto = true;
     533                        break;
     534                  case 'P':                                                                             // print options
     535                        for ( int i = 0;; i += 1 ) {
     536                                if ( i == printoptsSize ) {
     537                                        cout << "Unknown --print option " << optarg << endl;
     538                                        goto Default;
     539                                } // if
     540                                if ( strcmp( optarg, printopts[i].name ) == 0 ) {
     541                                        printopts[i].flag = printopts[i].val;
     542                                        break;
     543                                } // if
     544                        } // for
     545                        break;
     546                  case PreludeDir:                                                              // prelude directory for debug/nodebug, hidden
     547                        PreludeDirector = optarg;
     548                        break;
     549                  case 'S':                                                                             // enable profiling information, argument comma separated list of names
     550                        Stats::parse_params( optarg );
     551                        break;
     552                  case 't':                                                                             // build in tree
    529553                        treep = true;
    530554                        break;
    531                         case TupleExpansion:
    532                         case 'T':                                                                               // print after tuple expansion
    533                         tuplep = true;
    534                         break;
    535                         case 'v':                                                                               // dump AST after decl validation pass
    536                         validp = true;
    537                         break;
    538                         case 'w':
     555                  case 'w':                                                                             // suppress all warnings, hidden
    539556                        Wsuppress = true;
    540557                        break;
    541                         case 'W':
     558                  case 'W':                                                                             // coordinate gcc -W with CFA, hidden
    542559                        if ( strcmp( optarg, "all" ) == 0 ) {
    543560                                SemanticWarning_EnableAll();
     
    556573                        } // if
    557574                        break;
    558                         case 'y':                                                                               // dump AST on error
    559                         errorp = true;
    560                         break;
    561                         case 'z':                                                                               // dump as codegen rather than AST
    562                         codegenp = true;
    563                         break;
    564                         case 'Z':                                                                       // prettyprint during codegen (i.e. print unmangled names, etc.)
    565                         prettycodegenp = true;
    566                         break;
    567                         case 'D':                                                                               // ignore -Dxxx
    568                         break;
    569                         case 'F':                                                                               // source file-name without suffix
     575                  case 'D':                                                                             // ignore -Dxxx, forwarded by cpp, hidden
     576                        break;
     577                  case 'F':                                                                             // source file-name without suffix, hidden
    570578                        filename = optarg;
    571579                        break;
    572                         case '?':
     580                  case '?':                                                                             // unknown option
    573581                        if ( optopt ) {                                                         // short option ?
    574                                 assertf( false, "Unknown option: -%c\n", (char)optopt );
     582                                cout << "Unknown option -" << (char)optopt << endl;
    575583                        } else {
    576                                 assertf( false, "Unknown option: %s\n", argv[optind - 1] );
    577                         } // if
    578                         #if defined(__GNUC__) && __GNUC__ >= 7
    579                                 __attribute__((fallthrough));
    580                         #endif
    581                         default:
    582                         abort();
     584                                cout << "Unknown option " << argv[optind - 1] << endl;
     585                        } // if
     586                        goto Default;
     587                  case ':':                                                                             // missing option
     588                        if ( optopt ) {                                                         // short option ?
     589                                cout << "Missing option for -" << (char)optopt << endl;
     590                        } else {
     591                                cout << "Missing option for " << argv[optind - 1] << endl;
     592                        } // if
     593                        goto Default;
     594                  Default:
     595                  default:
     596                        usage( argv );                                                          // no return
    583597                } // switch
    584598        } // while
     
    618632        list< Declaration * > decls;
    619633
    620         if ( noprotop ) {
     634        if ( genproto ) {
    621635                filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), notPrelude );
    622636        } else {
     
    626640        // depending on commandline options, either generate code or dump the AST
    627641        if ( codegenp ) {
    628                 CodeGen::generate( decls, out, ! noprotop, prettycodegenp );
     642                CodeGen::generate( decls, out, ! genproto, prettycodegenp );
    629643        } else {
    630644                printAll( decls, out );
    631         }
     645        } // if
    632646        deleteAll( translationUnit );
    633647} // dump
  • tests/.expect/KRfunctions.x64.txt

    rec28948 r02af79b0  
    4444    __attribute__ ((unused)) signed int _X10_retval_f5i_1;
    4545}
    46 signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))(signed int __anonymous_object0){
     46signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))(__attribute__ ((unused)) signed int __anonymous_object0){
    4747    __attribute__ ((unused)) signed int (*_X10_retval_f6Fi_i__1)(signed int __anonymous_object1);
    4848}
  • tests/.expect/KRfunctions.x86.txt

    rec28948 r02af79b0  
    4444    __attribute__ ((unused)) signed int _X10_retval_f5i_1;
    4545}
    46 signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))(signed int __anonymous_object0){
     46signed int (*_X2f6FFi_i__iPiPi__1(signed int _X1ai_1, signed int *_X1bPi_1, signed int *_X1cPi_1))(__attribute__ ((unused)) signed int __anonymous_object0){
    4747    __attribute__ ((unused)) signed int (*_X10_retval_f6Fi_i__1)(signed int __anonymous_object1);
    4848}
  • tests/.expect/attributes.x64.txt

    rec28948 r02af79b0  
    271271}
    272272__attribute__ ((unused,used,unused)) signed int (*_X2f4FFi_i____1())(signed int __anonymous_object1);
    273 __attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())(signed int __anonymous_object2){
     273__attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())(__attribute__ ((unused)) signed int __anonymous_object2){
    274274    __attribute__ ((unused)) signed int (*_X10_retval_f4Fi_i__1)(signed int __anonymous_object3);
    275275}
  • tests/.expect/attributes.x86.txt

    rec28948 r02af79b0  
    271271}
    272272__attribute__ ((unused,used,unused)) signed int (*_X2f4FFi_i____1())(signed int __anonymous_object1);
    273 __attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())(signed int __anonymous_object2){
     273__attribute__ ((unused,unused)) signed int (*_X2f4FFi_i____1())(__attribute__ ((unused)) signed int __anonymous_object2){
    274274    __attribute__ ((unused)) signed int (*_X10_retval_f4Fi_i__1)(signed int __anonymous_object3);
    275275}
  • tests/.expect/declarationSpecifier.x64.txt

    rec28948 r02af79b0  
    691691    ((void)(_X12_retval_maini_1=0) /* ?{} */);
    692692    return _X12_retval_maini_1;
    693     ((void)(_X12_retval_maini_1=0) /* ?{} */);
    694     return _X12_retval_maini_1;
    695693}
    696694static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return _X4mainFi_iPPKc__1((signed int )argc, (const char **)argv); }
  • tests/.expect/declarationSpecifier.x86.txt

    rec28948 r02af79b0  
    691691    ((void)(_X12_retval_maini_1=0) /* ?{} */);
    692692    return _X12_retval_maini_1;
    693     ((void)(_X12_retval_maini_1=0) /* ?{} */);
    694     return _X12_retval_maini_1;
    695693}
    696694static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return _X4mainFi_iPPKc__1((signed int )argc, (const char **)argv); }
  • tests/.expect/functions.x64.txt

    rec28948 r02af79b0  
    11void _X1hFv___1(void){
    22}
    3 signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1(signed int (*__anonymous_object0)(void), signed int (*__anonymous_object1)(signed int __anonymous_object2), signed int (*__anonymous_object3)(void), signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){
     3signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1(__attribute__ ((unused)) signed int (*__anonymous_object0)(void), __attribute__ ((unused)) signed int (*__anonymous_object1)(signed int __anonymous_object2), __attribute__ ((unused)) signed int (*__anonymous_object3)(void), __attribute__ ((unused)) signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){
    44    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    55    ((void)(*_X1gFv___1)());
     
    9090    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    9191}
    92 signed int _X1fFi_i__1(signed int __anonymous_object7){
     92signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object7){
    9393    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    9494}
     
    121121    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    122122}
    123 struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object9, signed int _X1xi_1){
     123struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object9, signed int _X1xi_1){
    124124    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    125125}
     
    158158    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    159159}
    160 struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object12, signed int _X1xi_1, signed int __anonymous_object13){
     160struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object12, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object13){
    161161    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    162162}
     
    171171    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    172172}
    173 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){
     173struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){
    174174    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    175175}
     
    181181const double _X3fooFd___1(void);
    182182const double _X3fooFd_i__1(signed int __anonymous_object19);
    183 const double _X3fooFd_d__1(double __anonymous_object20){
     183const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object20){
    184184    __attribute__ ((unused)) const double _X11_retval_fooKd_1;
    185185    ((void)((*((double *)(&_X11_retval_fooKd_1)))=3.0) /* ?{} */);
     
    212212    ((void)((*_X4_dstS1S_1)._X1ii_1=_X1ii_1) /* ?{} */);
    213213}
    214 struct S _X3rtnFS1S_i__1(signed int __anonymous_object21){
     214struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object21){
    215215    __attribute__ ((unused)) struct S _X11_retval_rtnS1S_1;
    216216}
    217 signed int _X1fFi_Fi_ii_Fi_i___1(signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1), signed int (*__anonymous_object24)(signed int __anonymous_object25)){
     217signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1), __attribute__ ((unused)) signed int (*__anonymous_object24)(signed int __anonymous_object25)){
    218218    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    219219    signed int (*(*_X2pcPA0A0PA0A0i_2)[][((unsigned long int )10)])[][((unsigned long int )3)];
     
    241241}
    242242signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object27)(), signed int *(*__anonymous_object28)(), signed int **(*__anonymous_object29)(), signed int *const *(*__anonymous_object30)(), signed int *const *const (*__anonymous_object31)(), signed int *__anonymous_object32, signed int __anonymous_object33[((unsigned long int )10)], signed int **__anonymous_object34, signed int *__anonymous_object35[((unsigned long int )10)], signed int ***__anonymous_object36, signed int **__anonymous_object37[((unsigned long int )10)], signed int *const **__anonymous_object38, signed int *const *__anonymous_object39[((unsigned long int )10)], signed int *const *const *__anonymous_object40, signed int *const *const __anonymous_object41[((unsigned long int )10)]);
    243 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object42)(), signed int *(*__anonymous_object43)(), signed int **(*__anonymous_object44)(), signed int *const *(*__anonymous_object45)(), signed int *const *const (*__anonymous_object46)(), signed int *__anonymous_object47, signed int __anonymous_object48[((unsigned long int )10)], signed int **__anonymous_object49, signed int *__anonymous_object50[((unsigned long int )10)], signed int ***__anonymous_object51, signed int **__anonymous_object52[((unsigned long int )10)], signed int *const **__anonymous_object53, signed int *const *__anonymous_object54[((unsigned long int )10)], signed int *const *const *__anonymous_object55, signed int *const *const __anonymous_object56[((unsigned long int )10)]){
     243signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object42)(), __attribute__ ((unused)) signed int *(*__anonymous_object43)(), __attribute__ ((unused)) signed int **(*__anonymous_object44)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object45)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object46)(), __attribute__ ((unused)) signed int *__anonymous_object47, __attribute__ ((unused)) signed int __anonymous_object48[((unsigned long int )10)], __attribute__ ((unused)) signed int **__anonymous_object49, __attribute__ ((unused)) signed int *__anonymous_object50[((unsigned long int )10)], __attribute__ ((unused)) signed int ***__anonymous_object51, __attribute__ ((unused)) signed int **__anonymous_object52[((unsigned long int )10)], __attribute__ ((unused)) signed int *const **__anonymous_object53, __attribute__ ((unused)) signed int *const *__anonymous_object54[((unsigned long int )10)], __attribute__ ((unused)) signed int *const *const *__anonymous_object55, __attribute__ ((unused)) signed int *const *const __anonymous_object56[((unsigned long int )10)]){
    244244    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    245245}
  • tests/.expect/functions.x86.txt

    rec28948 r02af79b0  
    11void _X1hFv___1(void){
    22}
    3 signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1(signed int (*__anonymous_object0)(void), signed int (*__anonymous_object1)(signed int __anonymous_object2), signed int (*__anonymous_object3)(void), signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){
     3signed int _X1fFi_Fi__Fi_i_Fi__Fi_i_Fv____1(__attribute__ ((unused)) signed int (*__anonymous_object0)(void), __attribute__ ((unused)) signed int (*__anonymous_object1)(signed int __anonymous_object2), __attribute__ ((unused)) signed int (*__anonymous_object3)(void), __attribute__ ((unused)) signed int (*__anonymous_object4)(signed int __anonymous_object5), void (*_X1gFv___1)(void)){
    44    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    55    ((void)(*_X1gFv___1)());
     
    9090    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    9191}
    92 signed int _X1fFi_i__1(signed int __anonymous_object7){
     92signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object7){
    9393    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    9494}
     
    121121    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    122122}
    123 struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object9, signed int _X1xi_1){
     123struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object9, signed int _X1xi_1){
    124124    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    125125}
     
    158158    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    159159}
    160 struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object12, signed int _X1xi_1, signed int __anonymous_object13){
     160struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object12, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object13){
    161161    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    162162}
     
    171171    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    172172}
    173 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){
     173struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object15, signed int _X1xi_1, signed int *_X1yPi_1){
    174174    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    175175}
     
    181181const double _X3fooFd___1(void);
    182182const double _X3fooFd_i__1(signed int __anonymous_object19);
    183 const double _X3fooFd_d__1(double __anonymous_object20){
     183const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object20){
    184184    __attribute__ ((unused)) const double _X11_retval_fooKd_1;
    185185    ((void)((*((double *)(&_X11_retval_fooKd_1)))=3.0) /* ?{} */);
     
    212212    ((void)((*_X4_dstS1S_1)._X1ii_1=_X1ii_1) /* ?{} */);
    213213}
    214 struct S _X3rtnFS1S_i__1(signed int __anonymous_object21){
     214struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object21){
    215215    __attribute__ ((unused)) struct S _X11_retval_rtnS1S_1;
    216216}
    217 signed int _X1fFi_Fi_ii_Fi_i___1(signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1), signed int (*__anonymous_object24)(signed int __anonymous_object25)){
     217signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object22)(signed int __anonymous_object23, signed int _X1pi_1), __attribute__ ((unused)) signed int (*__anonymous_object24)(signed int __anonymous_object25)){
    218218    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    219219    signed int (*(*_X2pcPA0A0PA0A0i_2)[][((unsigned int )10)])[][((unsigned int )3)];
     
    241241}
    242242signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object27)(), signed int *(*__anonymous_object28)(), signed int **(*__anonymous_object29)(), signed int *const *(*__anonymous_object30)(), signed int *const *const (*__anonymous_object31)(), signed int *__anonymous_object32, signed int __anonymous_object33[((unsigned int )10)], signed int **__anonymous_object34, signed int *__anonymous_object35[((unsigned int )10)], signed int ***__anonymous_object36, signed int **__anonymous_object37[((unsigned int )10)], signed int *const **__anonymous_object38, signed int *const *__anonymous_object39[((unsigned int )10)], signed int *const *const *__anonymous_object40, signed int *const *const __anonymous_object41[((unsigned int )10)]);
    243 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object42)(), signed int *(*__anonymous_object43)(), signed int **(*__anonymous_object44)(), signed int *const *(*__anonymous_object45)(), signed int *const *const (*__anonymous_object46)(), signed int *__anonymous_object47, signed int __anonymous_object48[((unsigned int )10)], signed int **__anonymous_object49, signed int *__anonymous_object50[((unsigned int )10)], signed int ***__anonymous_object51, signed int **__anonymous_object52[((unsigned int )10)], signed int *const **__anonymous_object53, signed int *const *__anonymous_object54[((unsigned int )10)], signed int *const *const *__anonymous_object55, signed int *const *const __anonymous_object56[((unsigned int )10)]){
     243signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object42)(), __attribute__ ((unused)) signed int *(*__anonymous_object43)(), __attribute__ ((unused)) signed int **(*__anonymous_object44)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object45)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object46)(), __attribute__ ((unused)) signed int *__anonymous_object47, __attribute__ ((unused)) signed int __anonymous_object48[((unsigned int )10)], __attribute__ ((unused)) signed int **__anonymous_object49, __attribute__ ((unused)) signed int *__anonymous_object50[((unsigned int )10)], __attribute__ ((unused)) signed int ***__anonymous_object51, __attribute__ ((unused)) signed int **__anonymous_object52[((unsigned int )10)], __attribute__ ((unused)) signed int *const **__anonymous_object53, __attribute__ ((unused)) signed int *const *__anonymous_object54[((unsigned int )10)], __attribute__ ((unused)) signed int *const *const *__anonymous_object55, __attribute__ ((unused)) signed int *const *const __anonymous_object56[((unsigned int )10)]){
    244244    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    245245}
  • tests/declarationSpecifier.cfa

    rec28948 r02af79b0  
    1010// Created On       : Wed Aug 17 08:21:04 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 17:52:59 2018
    13 // Update Count     : 3
     12// Last Modified On : Tue Apr 30 18:20:36 2019
     13// Update Count     : 4
    1414//
    1515
     
    8989
    9090//Dummy main
    91 int main(int argc, char const *argv[])
    92 {
    93         return 0;
    94 }
     91int main( int argc, char const * argv[] ) {}
    9592
    9693// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.