Changeset 6943a987
- Timestamp:
- Aug 29, 2016, 10:33:05 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 5e644d3e
- Parents:
- 79841be (diff), 413ad05 (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. - Files:
-
- 6 added
- 6 deleted
- 83 edited
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
r79841be r6943a987 34 34 # generated by bison and lex from cfa.yy and lex.ll, respectively 35 35 src/Parser/parser.output 36 37 # generated by xfig for user manual 38 doc/user/Cdecl.tex 39 doc/user/pointer1.tex 40 doc/user/pointer2.tex -
doc/LaTeXmacros/common.tex
r79841be r6943a987 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Tue Aug 2 17:02:02201614 %% Update Count : 2 2813 %% Last Modified On : Sun Aug 14 08:27:29 2016 14 %% Update Count : 231 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 154 154 }% 155 155 \newcommand{\etal}{% 156 \@ifnextchar{.}{\abbrevFont{et 156 \@ifnextchar{.}{\abbrevFont{et~al}}% 157 157 {\abbrevFont{et al}.\xspace}% 158 158 }% … … 255 255 literate={-}{\raisebox{-0.15ex}{\texttt{-}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1 256 256 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {_}{\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1 257 {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {...}{$\dots$}2,257 {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2, 258 258 }% 259 259 -
doc/aaron_comp_II/comp_II.tex
r79841be r6943a987 91 91 \CFA\footnote{Pronounced ``C-for-all'', and written \CFA or \CFL.} is an evolutionary modernization of the C programming language currently being designed and built at the University of Waterloo by a team led by Peter Buhr. 92 92 \CFA both fixes existing design problems and adds multiple new features to C, including name overloading, user-defined operators, parametric-polymorphic routines, and type constructors and destructors, among others. 93 The new features make \CFA significantly more powerful and expressive than C, but impose a significant compile-time cost, particularly in the expression resolver, which must evaluate the typing rules of a muchmore complex type-system.93 The new features make \CFA more powerful and expressive than C, but impose a compile-time cost, particularly in the expression resolver, which must evaluate the typing rules of a significantly more complex type-system. 94 94 95 95 The primary goal of this research project is to develop a sufficiently performant expression resolution algorithm, experimentally validate its performance, and integrate it into CFA, the \CFA reference compiler. … … 104 104 105 105 It is important to note that \CFA is not an object-oriented language. 106 \CFA does have a system of (possibly implicit) type conversions derived from C's type conversions; while these conversions may be thought of as something like an inheritance hierarchy the underlying semantics are significantly different and such an analogy is loose at best.106 \CFA does have a system of (possibly implicit) type conversions derived from C's type conversions; while these conversions may be thought of as something like an inheritance hierarchy, the underlying semantics are significantly different and such an analogy is loose at best. 107 107 Particularly, \CFA has no concept of ``subclass'', and thus no need to integrate an inheritance-based form of polymorphism with its parametric and overloading-based polymorphism. 108 108 The graph structure of the \CFA type conversions is also markedly different than an inheritance graph; it has neither a top nor a bottom type, and does not satisfy the lattice properties typical of inheritance graphs. … … 120 120 \end{lstlisting} 121 121 The ©identity© function above can be applied to any complete object type (or ``©otype©''). 122 The type variable ©T© is transformed into a set of additional implicit parameters to ©identity© which encode sufficient information about ©T© to create and return a variable of that type.122 The type variable ©T© is transformed into a set of additional implicit parameters to ©identity©, which encode sufficient information about ©T© to create and return a variable of that type. 123 123 The current \CFA implementation passes the size and alignment of the type represented by an ©otype© parameter, as well as an assignment operator, constructor, copy constructor and destructor. 124 124 Here, the runtime cost of polymorphism is spread over each polymorphic call, due to passing more arguments to polymorphic functions; preliminary experiments have shown this overhead to be similar to \CC virtual function calls. 125 125 Determining if packaging all polymorphic arguments to a function into a virtual function table would reduce the runtime overhead of polymorphic calls is an open research question. 126 126 127 Since bare polymorphic types do not provide a great range of available operations, \CFA alsoprovides a \emph{type assertion} mechanism to provide further information about a type:127 Since bare polymorphic types do not provide a great range of available operations, \CFA provides a \emph{type assertion} mechanism to provide further information about a type: 128 128 \begin{lstlisting} 129 129 forall(otype T ®| { T twice(T); }®) … … 137 137 \end{lstlisting} 138 138 These type assertions may be either variable or function declarations that depend on a polymorphic type variable. 139 ©four_times© can only be called with an argument for which there exists a function named ©twice© that can take that argument and return another value of the same type; a pointer to the appropriate ©twice© function is passed as an additional implicit parameter to the call to©four_times©.139 ©four_times© can only be called with an argument for which there exists a function named ©twice© that can take that argument and return another value of the same type; a pointer to the appropriate ©twice© function is passed as an additional implicit parameter to the call of ©four_times©. 140 140 141 141 Monomorphic specializations of polymorphic functions can themselves be used to satisfy type assertions. … … 148 148 The compiler accomplishes this by creating a wrapper function calling ©twice // (2)© with ©S© bound to ©double©, then providing this wrapper function to ©four_times©\footnote{©twice // (2)© could also have had a type parameter named ©T©; \CFA specifies renaming of the type parameters, which would avoid the name conflict with the type variable ©T© of ©four_times©.}. 149 149 150 Finding appropriate functions to satisfy type assertions is essentially a recursive case of expression resolution, as it takes a name (that of the type assertion) and attempts to match it to a suitable declaration in the current scope.150 Finding appropriate functions to satisfy type assertions is essentially a recursive case of expression resolution, as it takes a name (that of the type assertion) and attempts to match it to a suitable declaration \emph{in the current scope}. 151 151 If a polymorphic function can be used to satisfy one of its own type assertions, this recursion may not terminate, as it is possible that function is examined as a candidate for its own type assertion unboundedly repeatedly. 152 152 To avoid infinite loops, the current CFA compiler imposes a fixed limit on the possible depth of recursion, similar to that employed by most \CC compilers for template expansion; this restriction means that there are some semantically well-typed expressions that cannot be resolved by CFA. … … 170 170 forall(otype M | has_magnitude(M)) 171 171 M max_magnitude( M a, M b ) { 172 M aa = abs(a), ab = abs(b); 173 return aa < ab ? b : a; 172 return abs(a) < abs(b) ? b : a; 174 173 } 175 174 \end{lstlisting} 176 175 177 176 Semantically, traits are simply a named lists of type assertions, but they may be used for many of the same purposes that interfaces in Java or abstract base classes in \CC are used for. 178 Unlike Java interfaces or \CC base classes, \CFA types do not explicitly state any inheritance relationship to traits they satisfy; this can be considered a form of structural inheritance, similar to i nterface implementationin Go, as opposed to the nominal inheritance model of Java and \CC.177 Unlike Java interfaces or \CC base classes, \CFA types do not explicitly state any inheritance relationship to traits they satisfy; this can be considered a form of structural inheritance, similar to implementation of an interface in Go, as opposed to the nominal inheritance model of Java and \CC. 179 178 Nominal inheritance can be simulated with traits using marker variables or functions: 180 179 \begin{lstlisting} … … 190 189 \end{lstlisting} 191 190 192 Traits, however, are significantly more powerful than nominal-inheritance interfaces; firstly, due to the scoping rules of the declarations whichsatisfy a trait's type assertions, a type may not satisfy a trait everywhere that the type is declared, as with ©char© and the ©nominal© trait above.193 Secondly, traits may be used to declare a relationship between multiple types, a property whichmay be difficult or impossible to represent in nominal-inheritance type systems:191 Traits, however, are significantly more powerful than nominal-inheritance interfaces; firstly, due to the scoping rules of the declarations that satisfy a trait's type assertions, a type may not satisfy a trait everywhere that the type is declared, as with ©char© and the ©nominal© trait above. 192 Secondly, traits may be used to declare a relationship among multiple types, a property that may be difficult or impossible to represent in nominal-inheritance type systems: 194 193 \begin{lstlisting} 195 194 trait pointer_like(®otype Ptr, otype El®) { … … 202 201 }; 203 202 204 typedef list *list_iterator;203 typedef list *list_iterator; 205 204 206 205 lvalue int *?( list_iterator it ) { … … 209 208 \end{lstlisting} 210 209 211 In the example above, ©(list_iterator, int)© satisfies ©pointer_like© by the given function, and ©(list_iterator, list)© also satisfies ©pointer_like© by the built-in pointer dereference operator. 210 In the example above, ©(list_iterator, int)© satisfies ©pointer_like© by the user-defined dereference function, and ©(list_iterator, list)© also satisfies ©pointer_like© by the built-in dereference operator for pointers. 211 Given a declaration ©list_iterator it©, ©*it© can be either an ©int© or a ©list©, with the meaning disambiguated by context (\eg ©int x = *it;© interprets ©*it© as an ©int©, while ©(*it).value = 42;© interprets ©*it© as a ©list©). 212 212 While a nominal-inheritance system with associated types could model one of those two relationships by making ©El© an associated type of ©Ptr© in the ©pointer_like© implementation, few such systems could model both relationships simultaneously. 213 213 214 The flexibility of \CFA's implicit trait 215 The ability of types to begin to or cease to satisfy traits when declarations go into or out of scope makes caching of trait satisfaction judgements difficult, and the ability of traits to take multiple type parameters c ouldlead to a combinatorial explosion of work in any attempt to pre-compute trait satisfaction relationships.214 The flexibility of \CFA's implicit trait-satisfaction mechanism provides programmers with a great deal of power, but also blocks some optimization approaches for expression resolution. 215 The ability of types to begin to or cease to satisfy traits when declarations go into or out of scope makes caching of trait satisfaction judgements difficult, and the ability of traits to take multiple type parameters can lead to a combinatorial explosion of work in any attempt to pre-compute trait satisfaction relationships. 216 216 On the other hand, the addition of a nominal inheritance mechanism to \CFA's type system or replacement of \CFA's trait satisfaction system with a more object-oriented inheritance model and investigation of possible expression resolution optimizations for such a system may be an interesting avenue of further research. 217 217 218 218 \subsection{Name Overloading} 219 219 In C, no more than one variable or function in the same scope may share the same name\footnote{Technically, C has multiple separated namespaces, one holding ©struct©, ©union©, and ©enum© tags, one holding labels, one holding typedef names, variable, function, and enumerator identifiers, and one for each ©struct© or ©union© type holding the field names.}, and variable or function declarations in inner scopes with the same name as a declaration in an outer scope hide the outer declaration. 220 This makes finding the proper declaration to match to a variable expression or function application a simple matter of symboltable lookup, which can be easily and efficiently implemented.220 This restriction makes finding the proper declaration to match to a variable expression or function application a simple matter of symbol-table lookup, which can be easily and efficiently implemented. 221 221 \CFA, on the other hand, allows overloading of variable and function names, so long as the overloaded declarations do not have the same type, avoiding the multiplication of variable and function names for different types common in the C standard library, as in the following example: 222 222 \begin{lstlisting} … … 229 229 double max = DBL_MAX; // (4) 230 230 231 max(7, -max); // uses (1) and (3), by matching int type of 7232 max(max, 3.14); // uses (2) and (4), by matching double type of 3.14231 max(7, -max); // uses (1) and (3), by matching int type of the constant 7 232 max(max, 3.14); // uses (2) and (4), by matching double type of the constant 3.14 233 233 234 234 max(max, -max); // ERROR: ambiguous 235 int m = max(max, -max); // uses (1) and (3) twice, byreturn type235 int m = max(max, -max); // uses (1) once and (3) twice, by matching return type 236 236 \end{lstlisting} 237 237 … … 239 239 240 240 \subsection{Implicit Conversions} 241 In addition to the multiple interpretations of an expression produced by name overloading, \CFA also supports all of the implicit conversions present in C, producing further candidate interpretations for expressions.242 C does not have a traditionally-definedinheritance hierarchy of types, but the C standard's rules for the ``usual arithmetic conversions'' define which of the built-in types are implicitly convertable to which other types, and the relative cost of any pair of such conversions from a single source type.243 \CFA adds to the usual arithmetic conversions rules for determining the cost of binding a polymorphic type variable in a function call; such bindings are cheaper than any \emph{unsafe} (narrowing) conversion, \eg ©int© to ©char©, but more expensive than any \emph{safe} (widening) conversion, \eg ©int© to ©double©.244 245 The expression resolution problem, then, is to find the unique minimal-cost interpretation of each expression in the program, where all identifiers must be matched to a declaration and implicit conversions or polymorphic bindings of the result of an expression may increase the cost of the expression.241 In addition to the multiple interpretations of an expression produced by name overloading, \CFA must support all of the implicit conversions present in C for backward compatibility, producing further candidate interpretations for expressions. 242 C does not have a inheritance hierarchy of types, but the C standard's rules for the ``usual arithmetic conversions'' define which of the built-in types are implicitly convertable to which other types, and the relative cost of any pair of such conversions from a single source type. 243 \CFA adds to the usual arithmetic conversions rules defining the cost of binding a polymorphic type variable in a function call; such bindings are cheaper than any \emph{unsafe} (narrowing) conversion, \eg ©int© to ©char©, but more expensive than any \emph{safe} (widening) conversion, \eg ©int© to ©double©. 244 245 The expression resolution problem, then, is to find the unique minimal-cost interpretation of each expression in the program, where all identifiers must be matched to a declaration, and implicit conversions or polymorphic bindings of the result of an expression may increase the cost of the expression. 246 246 Note that which subexpression interpretation is minimal-cost may require contextual information to disambiguate. 247 For instance, in the example in the previous subsection, ©max(max, -max)© cannot be unambiguously resolved, but ©int m = max(max, -max) ;© has a single minimal-cost resolution.248 ©int m = (int)max((double)max, -(double)max)© is also be a valid interpretation, but is not minimal-cost due to the unsafe cast from the ©double© result of ©max© to ©int© (the two ©double© casts function as type ascriptions selecting ©double max© rather than casts from ©int max© to ©double©, and as such are zero-cost).247 For instance, in the example in the previous subsection, ©max(max, -max)© cannot be unambiguously resolved, but ©int m = max(max, -max)© has a single minimal-cost resolution. 248 While the interpretation ©int m = (int)max((double)max, -(double)max)© is also a valid interpretation, it is not minimal-cost due to the unsafe cast from the ©double© result of ©max© to ©int© (the two ©double© casts function as type ascriptions selecting ©double max© rather than casts from ©int max© to ©double©, and as such are zero-cost). 249 249 250 250 \subsubsection{User-generated Implicit Conversions} … … 252 252 Such a conversion system should be simple for programmers to utilize, and fit naturally with the existing design of implicit conversions in C; ideally it would also be sufficiently powerful to encode C's usual arithmetic conversions itself, so that \CFA only has one set of rules for conversions. 253 253 254 Ditchfield~\cite{Ditchfield:conversions} haslaid out a framework for using polymorphic-conversion-constructor functions to create a directed acyclic graph (DAG) of conversions.254 Ditchfield~\cite{Ditchfield:conversions} laid out a framework for using polymorphic-conversion-constructor functions to create a directed acyclic graph (DAG) of conversions. 255 255 A monomorphic variant of these functions can be used to mark a conversion arc in the DAG as only usable as the final step in a conversion. 256 With these two types of conversion arcs, separate DAGs can be created for the safe and the unsafe conversions, and conversion cost can be represented as path length through the DAG.256 With these two types of conversion arcs, separate DAGs can be created for the safe and the unsafe conversions, and conversion cost can be represented the length of the shortest path through the DAG from one type to another. 257 257 \begin{figure}[h] 258 258 \centering 259 259 \includegraphics{conversion_dag} 260 \caption{A portion of the implicit conversion DAG for built-in types.} 260 \caption{A portion of the implicit conversion DAG for built-in types.}\label{fig:conv_dag} 261 261 \end{figure} 262 As can be seen in the example DAG above, there are either safe or unsafe paths between each of the arithmetic types listed; the ``final'' arcs are important both to avoid creating cycles in the signed-unsigned conversions, and to disambiguate potential diamond conversions (\eg, if the ©int© to ©unsigned int© conversion was not marked final there would be two length-two paths from ©int© to ©unsigned long©, and it would beimpossible to choose which one; however, since the ©unsigned int© to ©unsigned long© arc can not be traversed after the final ©int© to ©unsigned int© arc, there is a single unambiguous conversion path from ©int© to ©unsigned long©).262 As can be seen in Figure~\ref{fig:conv_dag}, there are either safe or unsafe paths between each of the arithmetic types listed; the ``final'' arcs are important both to avoid creating cycles in the signed-unsigned conversions, and to disambiguate potential diamond conversions (\eg, if the ©int© to ©unsigned int© conversion was not marked final there would be two length-two paths from ©int© to ©unsigned long©, making it impossible to choose which one; however, since the ©unsigned int© to ©unsigned long© arc can not be traversed after the final ©int© to ©unsigned int© arc, there is a single unambiguous conversion path from ©int© to ©unsigned long©). 263 263 264 264 Open research questions on this topic include: 265 265 \begin{itemize} 266 266 \item Can a conversion graph be generated that represents each allowable conversion in C with a unique minimal-length path such that the path lengths accurately represent the relative costs of the conversions? 267 \item Can such a graph representation canbe usefully augmented to include user-defined types as well as built-in types?268 \item Can the graph canbe efficiently represented and used in the expression resolver?267 \item Can such a graph representation be usefully augmented to include user-defined types as well as built-in types? 268 \item Can the graph be efficiently represented and used in the expression resolver? 269 269 \end{itemize} 270 270 271 271 \subsection{Constructors and Destructors} 272 272 Rob Shluntz, a current member of the \CFA research team, has added constructors and destructors to \CFA. 273 Each type has an overridable default-generated zero-argument constructor, copy constructor, assignment operator, and destructor; for ©struct© types these functions each call their equivalents on each field of the ©struct©. 274 This affects expression resolution because an ©otype© type variable ©T© implicitly adds four type assertions, one for each of these four functions, so assertion resolution is pervasive in \CFA polymorphic functions, even those without any explicit type assertions. 273 Each type has an overridable default-generated zero-argument constructor, copy constructor, assignment operator, and destructor. 274 For ©struct© types these functions each call their equivalents on each field of the ©struct©. 275 This feature affects expression resolution because an ©otype© type variable ©T© implicitly adds four type assertions, one for each of these four functions, so assertion resolution is pervasive in \CFA polymorphic functions, even those without any explicit type assertions. 275 276 The following example shows the implicitly-generated code in green: 276 277 \begin{lstlisting} … … 280 281 }; 281 282 282 ¢void ?{}(kv *this) { 283 ?{}(& this->key);284 ?{}(& this->value);285 } 286 void ?{}(kv *this, kv that) { 287 ?{}(& this->key, that.key);288 ?{}(& this->value, that.value);289 } 290 kv ?=?(kv *this, kv that) { 291 ?=?(& this->key, that.key);292 ?=?(& this->value, that.value);283 ¢void ?{}(kv *this) { // default constructor 284 ?{}(&(this->key)); // call recursively on members 285 ?{}(&(this->value)); 286 } 287 void ?{}(kv *this, kv that) { // copy constructor 288 ?{}(&(this->key), that.key); 289 ?{}(&(this->value), that.value); 290 } 291 kv ?=?(kv *this, kv that) { // assignment operator 292 ?=?(&(this->key), that.key); 293 ?=?(&(this->value), that.value); 293 294 return *this; 294 295 } 295 void ^?{}(kv *this) { 296 ^?{}(& this->key);297 ^?{}(& this->value);296 void ^?{}(kv *this) { // destructor 297 ^?{}(&(this->key)); 298 ^?{}(&(this->value)); 298 299 }¢ 299 300 … … 335 336 \begin{itemize} 336 337 \item Since there is an implicit conversion from ©void*© to any pointer type, the highlighted expression can be interpreted as either a ©void*©, matching ©f // (1)©, or a ©box(S)*© for some type ©S©, matching ©f // (2)©. 337 \item To determine the cost of the ©box(S)© interpretation, a type must be found for ©S© whichsatisfies the ©otype© implicit type assertions (assignment operator, default and copy constructors, and destructor); one option is ©box(S2)© for some type ©S2©.338 \item To determine the cost of the ©box(S)© interpretation, a type must be found for ©S© that satisfies the ©otype© implicit type assertions (assignment operator, default and copy constructors, and destructor); one option is ©box(S2)© for some type ©S2©. 338 339 \item The assignment operator, default and copy constructors, and destructor of ©box(T)© are also polymorphic functions, each of which require the type parameter ©T© to have an assignment operator, default and copy constructors, and destructor. When choosing an interpretation for ©S2©, one option is ©box(S3)©, for some type ©S3©. 339 340 \item The previous step repeats until stopped, with four times as much work performed at each step. 340 341 \end{itemize} 341 This problem can occur in any resolution context where a polymorphic function that can satisfy its own type assertions is required for a possible interpretation of an expression with no constraints on its type, and is thus not limited to combinations of generic types with ©void*© conversions, though constructors for generic types often satisfy their own assertions and a polymorphic conversion such as the ©void*© conversion to a polymorphic variable can create an expression with no constraints on its type. 342 This problem can occur in any resolution context where a polymorphic function can satisfy its own type assertions is required for a possible interpretation of an expression with no constraints on its type, and is thus not limited to combinations of generic types with ©void*© conversions. 343 However, constructors for generic types often satisfy their own assertions and a polymorphic conversion such as the ©void*© conversion to a polymorphic variable is a common way to create an expression with no constraints on its type. 342 344 As discussed above, the \CFA expression resolver must handle this possible infinite recursion somehow, and it occurs fairly naturally in code like the above that uses generic types. 343 345 … … 345 347 \CFA adds \emph{tuple types} to C, a syntactic facility for referring to lists of values anonymously or with a single identifier. 346 348 An identifier may name a tuple, and a function may return one. 347 Particularly relevantly for resolution, a tuple may be implicitly \emph{destructured} into a list of values, as in the call to ©swap© below:348 \begin{lstlisting} 349 [char, char] x = [ '!', '?' ]; 350 int x = 42; 351 352 forall(otype T) [T, T] swap( T a, T b ) { return [b, a]; } 349 Particularly relevantly for resolution, a tuple may be implicitly \emph{destructured} into a list of values, as in the call to ©swap©: 350 \begin{lstlisting} 351 [char, char] x = [ '!', '?' ]; // (1) 352 int x = 42; // (2) 353 354 forall(otype T) [T, T] swap( T a, T b ) { return [b, a]; } // (3) 353 355 354 356 x = swap( x ); // destructure [char, char] x into two elements of parameter list 355 357 // cannot use int x for parameter, not enough arguments to swap 356 \end{lstlisting} 357 Tuple destructuring means that the mapping from the position of a subexpression in the argument list to the position of a paramter in the function declaration is not straightforward, as some arguments may be expandable to different numbers of parameters, like ©x© above. 358 359 void swap( int, char, char ); // (4) 360 361 swap( x, x ); // resolved as (4) on (2) and (1) 362 // (3) on (2) and (2) is close, but the polymorphic binding makes it not minimal-cost 363 \end{lstlisting} 364 Tuple destructuring means that the mapping from the position of a subexpression in the argument list to the position of a paramter in the function declaration is not straightforward, as some arguments may be expandable to different numbers of parameters, like ©x© above. 365 In the second example, the second ©x© argument can be resolved starting at the second or third parameter of ©swap©, depending which interpretation of ©x© was chosen for the first argument. 358 366 359 367 \subsection{Reference Types} 360 368 I have been designing \emph{reference types} for \CFA, in collaboration with the rest of the \CFA research team. 361 369 Given some type ©T©, a ©T&© (``reference to ©T©'') is essentially an automatically dereferenced pointer; with these semantics most of the C standard's discussions of lvalues can be expressed in terms of references instead, with the benefit of being able to express the difference between the reference and non-reference version of a type in user code. 362 References preserve C's existing qualifier-dropping lvalue-to-rvalue conversion (\eg a ©const volatile int&© can be implicitly converted to a bare ©int©); the reference proposal also adds a rvalue-to-lvalue conversion to \CFA, implemented by storing the value in a new compiler-generated temporary and passing a reference to the temporary. 363 These two conversions can chain, producing a qualifier-dropping conversion for references, for instance converting a reference to a ©const int© into a reference to a non-©const int© by copying the originally refered to value into a fresh temporary and taking a reference to this temporary, as below: 370 References preserve C's existing qualifier-dropping lvalue-to-rvalue conversion (\eg a ©const volatile int&© can be implicitly converted to a bare ©int©). 371 The reference proposal also adds a rvalue-to-lvalue conversion to \CFA, implemented by storing the value in a new compiler-generated temporary and passing a reference to the temporary. 372 These two conversions can chain, producing a qualifier-dropping conversion for references, for instance converting a reference to a ©const int© into a reference to a non-©const int© by copying the originally refered to value into a fresh temporary and taking a reference to this temporary, as in: 364 373 \begin{lstlisting} 365 374 const int magic = 42; … … 369 378 print_inc( magic ); // legal; implicitly generated code in green below: 370 379 371 ¢int tmp = magic;¢ // copiesto safely strip const-qualifier380 ¢int tmp = magic;¢ // to safely strip const-qualifier 372 381 ¢print_inc( tmp );¢ // tmp is incremented, magic is unchanged 373 382 \end{lstlisting} 374 These reference conversions may also chain with the other implicit type 375 The main implication of th is for expression resolution is the multiplication of available implicit conversions, though in a restricted context that may be able to be treated efficiently as a special case.383 These reference conversions may also chain with the other implicit type-conversions. 384 The main implication of the reference conversions for expression resolution is the multiplication of available implicit conversions, though given the restricted context reference conversions may be able to be treated efficiently as a special case of implicit conversions. 376 385 377 386 \subsection{Special Literal Types} 378 387 Another proposal currently under consideration for the \CFA type-system is assigning special types to the literal values ©0© and ©1©. 379 Implicit conversions from these types allow ©0© and ©1© to be considered as values of many different types, depending on context, allowing expression desugarings like ©if ( x ) {}© $\Rightarrow$ ©if ( x != 0 ) {}© to be implemented efficiently and preci cely.388 Implicit conversions from these types allow ©0© and ©1© to be considered as values of many different types, depending on context, allowing expression desugarings like ©if ( x ) {}© $\Rightarrow$ ©if ( x != 0 ) {}© to be implemented efficiently and precisely. 380 389 This approach is a generalization of C's existing behaviour of treating ©0© as either an integer zero or a null pointer constant, and treating either of those values as boolean false. 381 390 The main implication for expression resolution is that the frequently encountered expressions ©0© and ©1© may have a large number of valid interpretations. … … 386 395 int somefn(char) = delete; 387 396 \end{lstlisting} 388 This feature is typically used in \CCeleven to make a type non-copyable by deleting its copy constructor and assignment operator , or forbidding some interpretations of a polymorphic function by specifically deleting the forbidden overloads.389 To add a similar feature to \CFA would involve including the deleted function declarations in expression resolution along with the normal declarations, but producing a compiler error if the deleted function was the best resolution.397 This feature is typically used in \CCeleven to make a type non-copyable by deleting its copy constructor and assignment operator\footnote{In previous versions of \CC a type could be made non-copyable by declaring a private copy constructor and assignment operator, but not defining either. This idiom is well-known, but depends on some rather subtle and \CC-specific rules about private members and implicitly-generated functions; the deleted-function form is both clearer and less verbose.}, or forbidding some interpretations of a polymorphic function by specifically deleting the forbidden overloads\footnote{Specific polymorphic function overloads can also be forbidden in previous \CC versions through use of template metaprogramming techniques, though this advanced usage is beyond the skills of many programmers. A similar effect can be produced on an ad-hoc basis at the appropriate call sites through use of casts to determine the function type. In both cases, the deleted-function form is clearer and more concise.}. 398 To add a similar feature to \CFA involves including the deleted function declarations in expression resolution along with the normal declarations, but producing a compiler error if the deleted function is the best resolution. 390 399 How conflicts should be handled between resolution of an expression to both a deleted and a non-deleted function is a small but open research question. 391 400 … … 404 413 %TODO: look up and lit review 405 414 The second area of investigation is minimizing dependencies between argument-parameter matches; the current CFA compiler attempts to match entire argument combinations against functions at once, potentially attempting to match the same argument against the same parameter multiple times. 406 Whether the feature set of \CFA admits an expression resolution algorithm where arguments can be matched to parameters independently of other arguments in the same function application is an area of open research; polymorphic type paramters produce enough of a cross-argument dependencythat the problem is not trivial.415 Whether the feature set of \CFA admits an expression resolution algorithm where arguments can be matched to parameters independently of other arguments in the same function application is an area of open research; polymorphic type paramters produce enough cross-argument dependencies that the problem is not trivial. 407 416 If cross-argument resolution dependencies cannot be completely eliminated, effective caching strategies to reduce duplicated work between equivalent argument-parameter matches in different combinations may mitigate the asymptotic defecits of the whole-combination matching approach. 408 417 The final area of investigation is heuristics and algorithmic approaches to reduce the number of argument interpretations considered in the common case; if argument-parameter matches cannot be made independent, even small reductions in $i$ should yield significant reductions in the $i^{p+1}$ resolver runtime factor. … … 412 421 413 422 \subsection{Argument-Parameter Matching} 414 The first axis for consideration is argument-parameter matching direction --- whether the type matching for a candidate function to a set of candidate arguments is directed by the argument types or the parameter types.423 The first axis for consideration is the argument-parameter matching direction --- whether the type matching for a candidate function to a set of candidate arguments is directed by the argument types or the parameter types. 415 424 For programming languages without implicit conversions, argument-parameter matching is essentially the entirety of the expression resolution problem, and is generally referred to as ``overload resolution'' in the literature. 416 All expression resolution algorithms form a DAG of interpretations, some explicitly, some implicitly; in this DAG, arcs point from function-call interpretations to argument interpretations, as below:425 All expression-resolution algorithms form a DAG of interpretations, some explicitly, some implicitly; in this DAG, arcs point from function-call interpretations to argument interpretations, as in Figure~\ref{fig:res_dag}: 417 426 \begin{figure}[h] 418 427 \centering … … 433 442 \end{figure} 434 443 435 Note that some interpretations may be part of more than one super-interpretation, as with $p_i$ in the bottom row, while some valid subexpression interpretations, like $f_d$ in the middle row, are not used in any interpretation of their containingexpression.444 Note that some interpretations may be part of more than one super-interpretation, as with the second $p_i$ in the bottom row, while some valid subexpression interpretations, like $f_d$ in the middle row, are not used in any interpretation of their superexpression. 436 445 437 446 \subsubsection{Argument-directed (Bottom-up)} … … 451 460 A reasonable hybrid approach might take a top-down approach when the expression to be matched has a fixed type, and a bottom-up approach in untyped contexts. 452 461 This approach may involve switching from one type to another at different levels of the expression tree. 453 For instance :462 For instance, in: 454 463 \begin{lstlisting} 455 464 forall(otype T) … … 460 469 int x = f( f( '!' ) ); 461 470 \end{lstlisting} 462 The outer call to ©f© must have a return type that is (implicitly convertable to) ©int©, so a top-down approach is used to select \textit{(1)} as the proper interpretation of ©f©. \textit{(1)}'s parameter ©x©, however, is an unbound type variable, and can thus take a value of any complete type, providing no guidance for the choice of candidate for the inner call to ©f©. The leaf expression ©'!'©, however, determines a zero-cost interpretation of the inner ©f© as \textit{(2)}, providing a minimal-cost expression resolution where ©T© is bound to ©void*©. 463 464 Deciding when to switch between bottom-up and top-down resolution to minimize wasted work in a hybrid algorithm is a necessarily heuristic process, and though finding good heuristics for which subexpressions to swich matching strategies on is an open question, one reasonable approach might be to set a threshold $t$ for the number of candidate functions, and to use top-down resolution for any subexpression with fewer than $t$ candidate functions, to minimize the number of unmatchable argument interpretations computed, but to use bottom-up resolution for any subexpression with at least $t$ candidate functions, to reduce duplication in argument interpretation computation between the different candidate functions. 471 the outer call to ©f© must have a return type that is (implicitly convertable to) ©int©, so a top-down approach is used to select \textit{(1)} as the proper interpretation of ©f©. \textit{(1)}'s parameter ©x©, however, is an unbound type variable, and can thus take a value of any complete type, providing no guidance for the choice of candidate for the inner call to ©f©. The leaf expression ©'!'©, however, determines a zero-cost interpretation of the inner ©f© as \textit{(2)}, providing a minimal-cost expression resolution where ©T© is bound to ©void*©. 472 473 Deciding when to switch between bottom-up and top-down resolution to minimize wasted work in a hybrid algorithm is a necessarily heuristic process, and finding good heuristics for which subexpressions to swich matching strategies on is an open question. 474 One reasonable approach might be to set a threshold $t$ for the number of candidate functions, and to use top-down resolution for any subexpression with fewer than $t$ candidate functions, to minimize the number of unmatchable argument interpretations computed, but to use bottom-up resolution for any subexpression with at least $t$ candidate functions, to reduce duplication in argument interpretation computation between the different candidate functions. 465 475 466 476 Ganzinger and Ripken~\cite{Ganzinger80} propose an approach (later refined by Pennello~\etal~\cite{Pennello80}) that uses a top-down filtering pass followed by a bottom-up filtering pass to reduce the number of candidate interpretations; they prove that for the Ada programming language a small number of such iterations is sufficient to converge to a solution for the expression resolution problem. 467 477 Persch~\etal~\cite{PW:overload} developed a similar two-pass approach where the bottom-up pass is followed by the top-down pass. 468 These algorithms differ from the hybrid approach under investigation in that they take multiple passes over the expression tree to yield a solution, and also in that theyapply both filtering heuristics to all expression nodes; \CFA's polymorphic functions and implicit conversions make the approach of filtering out invalid types taken by all of these algorithms infeasible.478 These algorithms differ from the hybrid approach under investigation in that they take multiple passes over the expression tree to yield a solution, and that they also apply both filtering heuristics to all expression nodes; \CFA's polymorphic functions and implicit conversions make the approach of filtering out invalid types taken by all of these algorithms infeasible. 469 479 470 480 \subsubsection{Common Subexpression Caching} … … 480 490 \CC~\cite{ANSI98:C++} includes both name overloading and implicit conversions in its expression resolution specification, though unlike \CFA it does complete type-checking on a generated monomorphization of template functions, where \CFA simply checks a list of type constraints. 481 491 The upcoming Concepts standard~\cite{C++concepts} defines a system of type constraints similar in principle to \CFA's. 482 Cormack and Wright~\cite{Cormack90} present an algorithm whichintegrates overload resolution with a polymorphic type inference approach very similar to \CFA's.492 Cormack and Wright~\cite{Cormack90} present an algorithm that integrates overload resolution with a polymorphic type inference approach very similar to \CFA's. 483 493 However, their algorithm does not account for implicit conversions other than polymorphic type binding and their discussion of their overload resolution algorithm is not sufficiently detailed to classify it with the other argument-parameter matching approaches\footnote{Their overload resolution algorithm is possibly a variant of Ganzinger and Ripken~\cite{Ganzinger80} or Pennello~\etal~\cite{Pennello80}, modified to allow for polymorphic type binding.}. 484 494 … … 486 496 Bilson does account for implicit conversions in his algorithm, but it is unclear if the approach is optimal. 487 497 His algorithm integrates checking for valid implicit conversions into the argument-parameter-matching step, essentially trading more expensive matching for a smaller number of argument interpretations. 488 This approach may result in the same subexpression being checked for a type match with the same type multiple times, though again memoization may mitigate this cost, and this approach does not generate implicit conversions that are not useful to match the containing function. 489 Calculating implicit conversions on parameters pairs naturally with a top-down approach to expression resolution, though it can also be used in a bottom-up approach, as Bilson demonstrates. 498 This approach may result in the same subexpression being checked for a type match with the same type multiple times, though again memoization may mitigate this cost; however, this approach does not generate implicit conversions that are not useful to match the containing function. 490 499 491 500 \subsubsection{On Arguments} 492 501 Another approach is to generate a set of possible implicit conversions for each set of interpretations of a given argument. 493 502 This approach has the benefit of detecting ambiguous interpretations of arguments at the level of the argument rather than its containing call, never finds more than one interpretation of the argument with a given type, and re-uses calculation of implicit conversions between function candidates. 494 On the other hand, this approach may unncessarily generate argument interpretations that never match any parameter, wasting work. 495 Further, in the presence of tuple types this approach may lead to a combinatorial explosion of argument interpretations considered, unless the tuple can be considered as a sequence of elements rather than a unified whole. 496 Calculating implicit conversions on arguments is a viable approach for bottom-up expression resolution, though it may be difficult to apply in a top-down approach due to the presence of a target type for the expression interpretation. 503 On the other hand, this approach may unnecessarily generate argument interpretations that never match any parameter, wasting work. 504 Furthermore, in the presence of tuple types, this approach may lead to a combinatorial explosion of argument interpretations considered, unless the tuple can be considered as a sequence of elements rather than a unified whole. 497 505 498 506 \subsection{Candidate Set Generation} 499 All the algorithms discussed to this point generate the complete set of candidate argument interpretations before attempting to match the containing function 500 However, given that the top-level expression interpretation that is ultimately chosen is the minimal-cost valid interpretation, any consideration of non-minimal-cost interpretations is in some sensewasted work.501 Under the assumption that thatprogrammers generally write function calls with relatively low-cost interpretations, a possible work-saving heuristic is to generate only the lowest-cost argument interpretations first, attempt to find a valid top-level interpretation using them, and only if that fails generate the next higher-cost argument interpretations.507 All the algorithms discussed to this point generate the complete set of candidate argument interpretations before attempting to match the containing function-call expression. 508 However, given that the top-level expression interpretation that is ultimately chosen is the minimal-cost valid interpretation, any consideration of non-minimal-cost interpretations is wasted work. 509 Under the assumption that programmers generally write function calls with relatively low-cost interpretations, a possible work-saving heuristic is to generate only the lowest-cost argument interpretations first, attempt to find a valid top-level interpretation using them, and only if that fails generate the next higher-cost argument interpretations. 502 510 503 511 \subsubsection{Eager} … … 563 571 This comparison closes Baker's open research question, as well as potentially improving Bilson's \CFA compiler. 564 572 565 Rather than testing all of these algorithms in-place in the \CFA compiler, a resolver prototype is being developed whichacts on a simplified input language encapsulating the essential details of the \CFA type-system\footnote{Note this simplified input language is not a usable programming language.}.573 Rather than testing all of these algorithms in-place in the \CFA compiler, a resolver prototype is being developed that acts on a simplified input language encapsulating the essential details of the \CFA type-system\footnote{Note this simplified input language is not a usable programming language.}. 566 574 Multiple variants of this resolver prototype will be implemented, each encapsulating a different expression resolution variant, sharing as much code as feasible. 567 575 These variants will be instrumented to test runtime performance, and run on a variety of input files; the input files may be generated programmatically or from exisiting code in \CFA or similar languages. … … 571 579 As an example, there are currently multiple open proposals for how implicit conversions should interact with polymorphic type binding in \CFA, each with distinct levels of expressive power; if the resolver prototype is modified to support each proposal, the optimal algorithm for each proposal can be compared, providing an empirical demonstration of the trade-off between expressive power and compiler runtime. 572 580 573 This proposed project should provide valuable data on how to implement a performant compiler for modernprogramming languages such as \CFA with powerful static type-systems, specifically targeting the feature interaction between name overloading and implicit conversions.581 This proposed project should provide valuable data on how to implement a performant compiler for programming languages such as \CFA with powerful static type-systems, specifically targeting the feature interaction between name overloading and implicit conversions. 574 582 This work is not limited in applicability to \CFA, but may also be useful for supporting efficient compilation of the upcoming Concepts standard~\cite{C++concepts} for \CC template constraints, for instance. 575 583 -
doc/user/user.tex
r79841be r6943a987 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Tue Aug 2 17:39:02201614 %% Update Count : 1 28613 %% Last Modified On : Sun Aug 14 08:23:06 2016 14 %% Update Count : 1323 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 317 317 318 318 \item 319 \Indexc{-no-include-std }\index{compilation option!-no-include-std@©-no-include-std©}319 \Indexc{-no-include-stdhdr}\index{compilation option!-no-include-stdhdr@©-no-include-stdhdr©} 320 320 Do not supply ©extern "C"© wrappers for \Celeven standard include files (see~\VRef{s:StandardHeaders}). 321 321 \textbf{This option is \emph{not} the default.} … … 807 807 808 808 809 \section{Backquote Identifiers} 810 \label{s:BackquoteIdentifiers} 811 812 \CFA accommodates keyword clashes by syntactic transformations using the \CFA backquote escape-mechanism: 813 \begin{lstlisting} 814 int `otype` = 3; // make keyword an identifier 815 double `choose` = 3.5; 816 \end{lstlisting} 817 Programs can be converted easily by enclosing keyword identifiers in backquotes, and the backquotes can be removed later when the identifier name is changed to an non-keyword name. 818 Clashes in C header files (see~\VRef{s:StandardHeaders}) can be handled automatically using the preprocessor, ©#include_next© and ©-I filename©: 819 \begin{lstlisting} 820 // include file uses the CFA keyword "otype". 821 #if ! defined( otype ) // nesting ? 822 #define otype `otype` 823 #define __CFA_BFD_H__ 824 #endif // ! otype 825 826 #include_next <bfd.h> // must have internal check for multiple expansion 827 828 #if defined( otype ) && defined( __CFA_BFD_H__ ) // reset only if set 829 #undef otype 830 #undef __CFA_BFD_H__ 831 #endif // otype && __CFA_BFD_H__ 832 \end{lstlisting} 833 834 809 835 \section{Type Operators} 810 836 … … 1011 1037 Alternatively, prototype definitions can be eliminated by using a two-pass compilation, and implicitly creating header files for exports. 1012 1038 The former is easy to do, while the latter is more complex. 1013 Currently, \CFA does \emph{not} attempt to support named arguments. 1039 1040 Furthermore, named arguments do not work well in a \CFA-style programming-languages because they potentially introduces a new criteria for type matching. 1041 For example, it is technically possible to disambiguate between these two overloaded definitions of ©f© based on named arguments at the call site: 1042 \begin{lstlisting} 1043 int f( int i, int j ); 1044 int f( int x, double y ); 1045 1046 f( j : 3, i : 4 ); §\C{// 1st f}§ 1047 f( x : 7, y : 8.1 ); §\C{// 2nd f}§ 1048 f( 4, 5 ); §\C{// ambiguous call}§ 1049 \end{lstlisting} 1050 However, named arguments compound routine resolution in conjunction with conversions: 1051 \begin{lstlisting} 1052 f( i : 3, 5.7 ); §\C{// ambiguous call ?}§ 1053 \end{lstlisting} 1054 Depending on the cost associated with named arguments, this call could be resolvable or ambiguous. 1055 Adding named argument into the routine resolution algorithm does not seem worth the complexity. 1056 Therefore, \CFA does \emph{not} attempt to support named arguments. 1014 1057 1015 1058 \item[Default Arguments] … … 1021 1064 the allowable positional calls are: 1022 1065 \begin{lstlisting} 1023 p(); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§1024 p( 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§1025 p( 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§1026 p( 4, 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§1066 p(); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§ 1067 p( 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§ 1068 p( 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§ 1069 p( 4, 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 4 )}§ 1027 1070 // empty arguments 1028 p( , 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§1029 p( 4, , 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§1030 p( 4, 4, ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§1031 p( 4, , ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§1032 p( , 4, ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§1033 p( , , 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§1034 p( , , ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§1071 p( , 4, 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 4 )}§ 1072 p( 4, , 4 ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 4 )}§ 1073 p( 4, 4, ); §\C{// rewrite $\Rightarrow$ p( 4, 4, 3 )}§ 1074 p( 4, , ); §\C{// rewrite $\Rightarrow$ p( 4, 2, 3 )}§ 1075 p( , 4, ); §\C{// rewrite $\Rightarrow$ p( 1, 4, 3 )}§ 1076 p( , , 4 ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 4 )}§ 1077 p( , , ); §\C{// rewrite $\Rightarrow$ p( 1, 2, 3 )}§ 1035 1078 \end{lstlisting} 1036 1079 Here the missing arguments are inserted from the default values in the parameter list. … … 1067 1110 The conflict occurs because both named and ellipse arguments must appear after positional arguments, giving two possibilities: 1068 1111 \begin{lstlisting} 1069 p( /* positional */, . . ., /* named */ );1070 p( /* positional */, /* named */, . .. );1112 p( /* positional */, ... , /* named */ ); 1113 p( /* positional */, /* named */, ... ); 1071 1114 \end{lstlisting} 1072 1115 While it is possible to implement both approaches, the first possibly is more complex than the second, \eg: 1073 1116 \begin{lstlisting} 1074 p( int x, int y, int z, . .. );1075 p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, . . ., /* named */ );}§1076 p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, . .. );}§1117 p( int x, int y, int z, ... ); 1118 p( 1, 4, 5, 6, z : 3, y : 2 ); §\C{// assume p( /* positional */, ... , /* named */ );}§ 1119 p( 1, z : 3, y : 2, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§ 1077 1120 \end{lstlisting} 1078 1121 In the first call, it is necessary for the programmer to conceptually rewrite the call, changing named arguments into positional, before knowing where the ellipse arguments begin. … … 1082 1125 The problem is exacerbated with default arguments, \eg: 1083 1126 \begin{lstlisting} 1084 void p( int x, int y = 2, int z = 3. .. );1085 p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, . . ., /* named */ );}§1086 p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, . .. );}§1127 void p( int x, int y = 2, int z = 3... ); 1128 p( 1, 4, 5, 6, z : 3 ); §\C{// assume p( /* positional */, ... , /* named */ );}§ 1129 p( 1, z : 3, 4, 5, 6 ); §\C{// assume p( /* positional */, /* named */, ... );}§ 1087 1130 \end{lstlisting} 1088 1131 The first call is an error because arguments 4 and 5 are actually positional not ellipse arguments; … … 1129 1172 \subsection{Type Nesting} 1130 1173 1131 \CFA allows \Index{type nesting}, and type qualification of the nested typ es (see \VRef[Figure]{f:TypeNestingQualification}), where as C hoists\index{type hoisting} (refactors) nested types into the enclosing scope and has no type qualification.1174 \CFA allows \Index{type nesting}, and type qualification of the nested typres (see \VRef[Figure]{f:TypeNestingQualification}), where as C hoists\index{type hoisting} (refactors) nested types into the enclosing scope and has no type qualification. 1132 1175 \begin{figure} 1176 \centering 1133 1177 \begin{tabular}{@{}l@{\hspace{3em}}l|l@{}} 1134 1178 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}} & \multicolumn{1}{c}{\textbf{C Implicit Hoisting}} & \multicolumn{1}{|c}{\textbf{\CFA}} \\ … … 1397 1441 Mass assignment has the following form: 1398 1442 \begin{lstlisting} 1399 [ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = §\emph{expr}§;1443 [ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = §\emph{expr}§; 1400 1444 \end{lstlisting} 1401 1445 \index{lvalue} … … 1437 1481 Multiple assignment has the following form: 1438 1482 \begin{lstlisting} 1439 [ §\emph{lvalue}§, . . ., §\emph{lvalue}§ ] = [ §\emph{expr}§, . . ., §\emph{expr}§ ];1483 [ §\emph{lvalue}§, ... , §\emph{lvalue}§ ] = [ §\emph{expr}§, ... , §\emph{expr}§ ]; 1440 1484 \end{lstlisting} 1441 1485 \index{lvalue} … … 1873 1917 \begin{lstlisting} 1874 1918 switch ( i ) { 1875 ®case1, 3, 5®:1919 case ®1, 3, 5®: 1876 1920 ... 1877 ®case2, 4, 6®:1921 case ®2, 4, 6®: 1878 1922 ... 1879 1923 } … … 1906 1950 \begin{lstlisting} 1907 1951 switch ( i ) { 1908 ®case1~5:®1952 case ®1~5:® 1909 1953 ... 1910 ®case10~15:®1954 case ®10~15:® 1911 1955 ... 1912 1956 } … … 1915 1959 \begin{lstlisting} 1916 1960 switch ( i ) 1917 case 1 ... 5:1961 case ®1 ... 5®: 1918 1962 ... 1919 case 10 ... 15:1963 case ®10 ... 15®: 1920 1964 ... 1921 1965 } … … 4369 4413 4370 4414 4415 \section{Incompatible} 4416 4417 The following incompatibles exist between \CFA and C, and are similar to Annex C for \CC~\cite{ANSI14:C++}. 4418 4419 \begin{enumerate} 4420 \item 4421 \begin{description} 4422 \item[Change:] add new keywords \\ 4423 New keywords are added to \CFA (see~\VRef{s:NewKeywords}). 4424 \item[Rationale:] keywords added to implement new semantics of \CFA. 4425 \item[Effect on original feature:] change to semantics of well-defined feature. \\ 4426 Any ISO C programs using these keywords as identifiers are invalid \CFA programs. 4427 \item[Difficulty of converting:] keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism (see~\VRef{s:BackquoteIdentifiers}): 4428 \item[How widely used:] clashes among new \CFA keywords and existing identifiers are rare. 4429 \end{description} 4430 4431 \item 4432 \begin{description} 4433 \item[Change:] type of character literal ©int© to ©char© to allow more intuitive overloading: 4434 \begin{lstlisting} 4435 int rtn( int i ); 4436 int rtn( char c ); 4437 rtn( 'x' ); §\C{// programmer expects 2nd rtn to be called}§ 4438 \end{lstlisting} 4439 \item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first. 4440 In particular, output of ©char© variable now print a character rather than the decimal ASCII value of the character. 4441 \begin{lstlisting} 4442 sout | 'x' | " " | (int)'x' | endl; 4443 x 120 4444 \end{lstlisting} 4445 Having to cast ©'x'© to ©char© is non-intuitive. 4446 \item[Effect on original feature:] change to semantics of well-defined feature that depend on: 4447 \begin{lstlisting} 4448 sizeof( 'x' ) == sizeof( int ) 4449 \end{lstlisting} 4450 no long work the same in \CFA programs. 4451 \item[Difficulty of converting:] simple 4452 \item[How widely used:] programs that depend upon ©sizeof( 'x' )© are rare and can be changed to ©sizeof(char)©. 4453 \end{description} 4454 4455 \item 4456 \begin{description} 4457 \item[Change:] make string literals ©const©: 4458 \begin{lstlisting} 4459 char * p = "abc"; §\C{// valid in C, deprecated in \CFA}§ 4460 char * q = expr ? "abc" : "de"; §\C{// valid in C, invalid in \CFA}§ 4461 \end{lstlisting} 4462 The type of a string literal is changed from ©[] char© to ©const [] char©. 4463 Similarly, the type of a wide string literal is changed from ©[] wchar_t© to ©const [] wchar_t©. 4464 \item[Rationale:] This change is a safety issue: 4465 \begin{lstlisting} 4466 char * p = "abc"; 4467 p[0] = 'w'; §\C{// segment fault or change constant literal}§ 4468 \end{lstlisting} 4469 The same problem occurs when passing a string literal to a routine that changes its argument. 4470 \item[Effect on original feature:] change to semantics of well-defined feature. 4471 \item[Difficulty of converting:] simple syntactic transformation, because string literals can be converted to ©char *©. 4472 \item[How widely used:] programs that have a legitimate reason to treat string literals as pointers to potentially modifiable memory are rare. 4473 \end{description} 4474 4475 \item 4476 \begin{description} 4477 \item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope: 4478 \begin{lstlisting} 4479 int i; §\C{// forward definition}§ 4480 int *j = ®&i®; §\C{// forward reference, valid in C, invalid in \CFA}§ 4481 int i = 0; §\C{// definition}§ 4482 \end{lstlisting} 4483 is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed. 4484 This change makes it impossible to define mutually referential file-local static objects, if initializers are restricted to the syntactic forms of C. For example, 4485 \begin{lstlisting} 4486 struct X { int i; struct X *next; }; 4487 static struct X a; §\C{// forward definition}§ 4488 static struct X b = { 0, ®&a® }; §\C{// forward reference, valid in C, invalid in \CFA}§ 4489 static struct X a = { 1, &b }; §\C{// definition}§ 4490 \end{lstlisting} 4491 \item[Rationale:] avoids having different initialization rules for builtin types and userdefined types. 4492 \item[Effect on original feature:] change to semantics of well-defined feature. 4493 \item[Difficulty of converting:] the initializer for one of a set of mutually-referential file-local static objects must invoke a routine call to achieve the initialization. 4494 \item[How widely used:] seldom 4495 \end{description} 4496 4497 \item 4498 \begin{description} 4499 \item[Change:] have ©struct© introduce a scope for nested types: 4500 \begin{lstlisting} 4501 enum ®Colour® { R, G, B, Y, C, M }; 4502 struct Person { 4503 enum ®Colour® { R, G, B }; §\C{// nested type}§ 4504 struct Face { §\C{// nested type}§ 4505 ®Colour® Eyes, Hair; §\C{// type defined outside (1 level)}§ 4506 }; 4507 ß.ß®Colour® shirt; §\C{// type defined outside (top level)}§ 4508 ®Colour® pants; §\C{// type defined same level}§ 4509 Face looks[10]; §\C{// type defined same level}§ 4510 }; 4511 ®Colour® c = R; §\C{// type/enum defined same level}§ 4512 Personß.ß®Colour® pc = Personß.ßR; §\C{// type/enum defined inside}§ 4513 Personß.ßFace pretty; §\C{// type defined inside}§ 4514 \end{lstlisting} 4515 In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing structure, i.e., the nested types are hoisted to the scope of the outer-most type, which is not useful and confusing. 4516 \CFA is C \emph{incompatible} on this issue, and provides semantics similar to \Index*[C++]{\CC}. 4517 Nested types are not hoisted and can be referenced using the field selection operator ``©.©'', unlike the \CC scope-resolution operator ``©::©''. 4518 \item[Rationale:] ©struct© scope is crucial to \CFA as an information structuring and hiding mechanism. 4519 \item[Effect on original feature:] change to semantics of well-defined feature. 4520 \item[Difficulty of converting:] Semantic transformation. 4521 \item[How widely used:] C programs rarely have nest types because they are equivalent to the hoisted version. 4522 \end{description} 4523 4524 \item 4525 \begin{description} 4526 \item[Change:] In C++, the name of a nested class is local to its enclosing class. 4527 \item[Rationale:] C++ classes have member functions which require that classes establish scopes. 4528 \item[Difficulty of converting:] Semantic transformation. To make the struct type name visible in the scope of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing struct is defined. Example: 4529 \begin{lstlisting} 4530 struct Y; §\C{// struct Y and struct X are at the same scope}§ 4531 struct X { 4532 struct Y { /* ... */ } y; 4533 }; 4534 \end{lstlisting} 4535 All the definitions of C struct types enclosed in other struct definitions and accessed outside the scope of the enclosing struct could be exported to the scope of the enclosing struct. 4536 Note: this is a consequence of the difference in scope rules, which is documented in 3.3. 4537 \item[How widely used:] Seldom. 4538 \end{description} 4539 4540 \item 4541 \begin{description} 4542 \item[Change:] comma expression is disallowed as subscript 4543 \item[Rationale:] safety issue to prevent subscripting error for multidimensional arrays: ©x[i,j]© instead of ©x[i][j]©, and this syntactic form then taken by \CFA for new style arrays. 4544 \item[Effect on original feature:] change to semantics of well-defined feature. 4545 \item[Difficulty of converting:] semantic transformation of ©x[i,j]© to ©x[(i,j)]© 4546 \item[How widely used:] seldom. 4547 \end{description} 4548 \end{enumerate} 4549 4550 4371 4551 \section{New Keywords} 4372 4552 \label{s:NewKeywords} 4373 4553 4374 4554 \begin{quote2} 4375 \begin{tabular}{ll} 4376 ©catch© & ©lvalue© \\ 4377 ©catchResume© & \\ 4378 ©choose© & ©otype© \\ 4379 & \\ 4380 ©disable© & ©throw© \\ 4381 ©dtype© & ©throwResume© \\ 4382 & ©trait© \\ 4383 ©enable© & ©try© \\ 4384 & \\ 4385 ©fallthrough© \\ 4386 ©fallthru© \\ 4387 ©finally© \\ 4388 ©forall© \\ 4389 ©ftype© \\ 4555 \begin{tabular}{lll} 4556 ©catch© & ©fallthrough© & ©otype© \\ 4557 ©catchResume© & ©fallthru© & ©throw© \\ 4558 ©choose© & ©finally© & ©throwResume© \\ 4559 ©disable© & ©forall© & ©trait© \\ 4560 ©dtype© & ©ftype© & ©try© \\ 4561 ©enable© & ©lvalue© & \\ 4390 4562 \end{tabular} 4391 4563 \end{quote2} … … 4395 4567 \label{s:StandardHeaders} 4396 4568 4397 C prescribes the following standard header-files :4569 C prescribes the following standard header-files~\cite[\S~7.1.2]{C11}: 4398 4570 \begin{quote2} 4399 4571 \begin{minipage}{\linewidth} … … 4412 4584 \end{minipage} 4413 4585 \end{quote2} 4414 For the prescribed head-files, \CFA implicit wraps their includes in an ©extern "C"©;4586 For the prescribed head-files, \CFA implicitly wraps their includes in an ©extern "C"©; 4415 4587 hence, names in these include files are not mangled\index{mangling!name} (see~\VRef{s:Interoperability}). 4416 4588 All other C header files must be explicitly wrapped in ©extern "C"© to prevent name mangling. 4417 4418 4419 \section{Incompatible}4420 4421 The following incompatibles exist between \CFA and C, and are similar to Annex C for \CC~\cite{ANSI14:C++}.4422 4423 \begin{enumerate}4424 \item4425 \begin{description}4426 \item[Change:] add new keywords (see~\VRef{s:NewKeywords}) \\4427 New keywords are added to \CFA.4428 \item[Rationale:] keywords added to implement new semantics of \CFA.4429 \item[Effect on original feature:] change to semantics of well-defined feature. \\4430 Any ISO C programs using these keywords as identifiers are invalid \CFA programs.4431 \item[Difficulty of converting:] keyword clashes are accommodated by syntactic transformations using the \CFA backquote escape-mechanism:4432 \begin{lstlisting}4433 int `otype` = 3; // make keyword an identifier4434 double `choose` = 3.5;4435 \end{lstlisting}4436 Programs can be converted automatically by enclosing keyword identifiers in backquotes, and the backquotes can be remove later when the identifier name is changed.4437 Clashes in C system libraries (include files) can be handled automatically using preprocessor, ©#include_next© and ©-Ifilename©:4438 \begin{lstlisting}4439 // include file uses the CFA keyword "otype".4440 #if ! defined( otype ) // nesting ?4441 #define otype `otype`4442 #define __CFA_BFD_H__4443 #endif // ! otype4444 4445 #include_next <bfd.h> // must have internal check for multiple expansion4446 4447 #if defined( otype ) && defined( __CFA_BFD_H__ ) // reset only if set4448 #undef otype4449 #undef __CFA_BFD_H__4450 #endif // otype && __CFA_BFD_H__4451 \end{lstlisting}4452 \item[How widely used:] clashes among new \CFA keywords and existing identifiers are rare.4453 \end{description}4454 4455 \item4456 \begin{description}4457 \item[Change:] type of character literal ©int© to ©char© to allow more intuitive overloading:4458 \begin{lstlisting}4459 int rtn( int i );4460 int rtn( char c );4461 rtn( 'x' ); // programmer expects 2nd rtn to be called4462 \end{lstlisting}4463 \item[Rationale:] it is more intuitive for the call to ©rtn© to match the second version of definition of ©rtn© rather than the first.4464 In particular, output of ©char© variable now print a character rather than the decimal ASCII value of the character.4465 \begin{lstlisting}4466 sout | 'x' | " " | (int)'x' | endl;4467 x 1204468 \end{lstlisting}4469 Having to cast ©'x'© to ©char© is non-intuitive.4470 \item[Effect on original feature:] change to semantics of well-defined feature that depend on:4471 \begin{lstlisting}4472 sizeof( 'x' ) == sizeof( int )4473 \end{lstlisting}4474 no long work the same in \CFA programs.4475 \item[Difficulty of converting:] simple4476 \item[How widely used:] programs that depend upon ©sizeof( 'x' )© are rare and can be changed to ©sizeof(char)©.4477 \end{description}4478 4479 \item4480 \begin{description}4481 \item[Change:] make string literals ©const©:4482 \begin{lstlisting}4483 char * p = "abc"; // valid in C, deprecated in §\CFA§4484 char * q = expr ? "abc" : "de"; // valid in C, invalid in §\CFA§4485 \end{lstlisting}4486 The type of a string literal is changed from ©[] char© to ©const [] char©.4487 Similarly, the type of a wide string literal is changed from ©[] wchar_t© to ©const [] wchar_t©.4488 \item[Rationale:] This change is a safety issue:4489 \begin{lstlisting}4490 char * p = "abc";4491 p[0] = 'w'; // segment fault or change constant literal4492 \end{lstlisting}4493 The same problem occurs when passing a string literal to a routine that changes its argument.4494 \item[Effect on original feature:] change to semantics of well-defined feature.4495 \item[Difficulty of converting:] simple syntactic transformation, because string literals can be converted to ©char *©.4496 \item[How widely used:] programs that have a legitimate reason to treat string literals as pointers to potentially modifiable memory are rare.4497 \end{description}4498 4499 \item4500 \begin{description}4501 \item[Change:] remove \newterm{tentative definitions}, which only occurs at file scope:4502 \begin{lstlisting}4503 int i; // forward definition4504 int *j = ®&i®; // forward reference, valid in C, invalid in §\CFA§4505 int i = 0; // definition4506 \end{lstlisting}4507 is valid in C, and invalid in \CFA because duplicate overloaded object definitions at the same scope level are disallowed.4508 This change makes it impossible to define mutually referential file-local static objects, if initializers are restricted to the syntactic forms of C. For example,4509 \begin{lstlisting}4510 struct X { int i; struct X *next; };4511 static struct X a; // forward definition4512 static struct X b = { 0, ®&a® }; // forward reference, valid in C, invalid in §\CFA§4513 static struct X a = { 1, &b }; // definition4514 \end{lstlisting}4515 \item[Rationale:] avoids having different initialization rules for builtin types and userdefined types.4516 \item[Effect on original feature:] change to semantics of well-defined feature.4517 \item[Difficulty of converting:] the initializer for one of a set of mutually-referential file-local static objects must invoke a routine call to achieve the initialization.4518 \item[How widely used:] seldom4519 \end{description}4520 4521 \item4522 \begin{description}4523 \item[Change:] have ©struct© introduce a scope for nested types4524 In C, the name of the nested types belongs to the same scope as the name of the outermost enclosing4525 Example:4526 \begin{lstlisting}4527 enum ®Colour® { R, G, B, Y, C, M };4528 struct Person {4529 enum ®Colour® { R, G, B }; // nested type4530 struct Face { // nested type4531 ®Colour® Eyes, Hair; // type defined outside (1 level)4532 };4533 ß.ß®Colour® shirt; // type defined outside (top level)4534 ®Colour® pants; // type defined same level4535 Face looks[10]; // type defined same level4536 };4537 ®Colour® c = R; // type/enum defined same level4538 Personß.ß®Colour® pc = Personß.ßR; // type/enum defined inside4539 Personß.ßFace pretty; // type defined inside4540 \end{lstlisting}4541 \item[Rationale:] ©struct© scope is crucial to \CFA as an information structuring and hiding mechanism.4542 \item[Effect on original feature:] change to semantics of well-defined feature.4543 \item[Difficulty of converting:] Semantic transformation.4544 \item[How widely used:] C programs rarely have nest types because they are equivalent to the hoisted version.4545 4546 \CFA is C \emph{incompatible} on this issue, and provides semantics similar to \Index*[C++]{\CC}.4547 Nested types are not hoisted and can be referenced using the field selection operator ``©.©'', unlike the \CC scope-resolution operator ``©::©''.4548 Given that nested types in C are equivalent to not using them, \ie they are essentially useless, it is unlikely there are any realistic usages that break because of this incompatibility.4549 \end{description}4550 4551 \item4552 \begin{description}4553 \item[Change:] In C++, the name of a nested class is local to its enclosing class.4554 \item[Rationale:] C++ classes have member functions which require that classes establish scopes.4555 \item[Difficulty of converting:] Semantic transformation. To make the struct type name visible in the scope of the enclosing struct, the struct tag could be declared in the scope of the enclosing struct, before the enclosing struct is defined. Example:4556 \begin{lstlisting}4557 struct Y; // struct Y and struct X are at the same scope4558 struct X {4559 struct Y { /* ... */ } y;4560 };4561 \end{lstlisting}4562 All the definitions of C struct types enclosed in other struct definitions and accessed outside the scope of the enclosing struct could be exported to the scope of the enclosing struct.4563 Note: this is a consequence of the difference in scope rules, which is documented in 3.3.4564 \item[How widely used:] Seldom.4565 \end{description}4566 4567 \item4568 \begin{description}4569 \item[Change:] comma expression is disallowed as subscript4570 \item[Rationale:] safety issue to prevent subscripting error for multidimensional arrays: ©x[i,j]© instead of ©x[i][j]©, and this syntactic form then taken by \CFA for new style arrays.4571 \item[Effect on original feature:] change to semantics of well-defined feature.4572 \item[Difficulty of converting:] semantic transformation of ©x[i,j]© to ©x[(i,j)]©4573 \item[How widely used:] seldom.4574 \end{description}4575 \end{enumerate}4576 4589 4577 4590 … … 4749 4762 \subsection{malloc} 4750 4763 4764 \leavevmode 4751 4765 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4752 4766 forall( otype T ) T * malloc( void );§\indexc{malloc}§ … … 4765 4779 forall( otype T ) T * memset( T * ptr ); // remove when default value available 4766 4780 \end{lstlisting} 4767 \ 4781 4768 4782 4769 4783 \subsection{ato / strto} 4770 4784 4785 \leavevmode 4771 4786 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4772 4787 int ato( const char * ptr );§\indexc{ato}§ … … 4796 4811 long double _Complex strto( const char * sptr, char ** eptr ); 4797 4812 \end{lstlisting} 4798 \4799 4813 4800 4814 4801 4815 \subsection{bsearch / qsort} 4802 4816 4817 \leavevmode 4803 4818 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4804 4819 forall( otype T | { int ?<?( T, T ); } ) … … 4808 4823 void qsort( const T * arr, size_t dimension );§\indexc{qsort}§ 4809 4824 \end{lstlisting} 4810 \4811 4825 4812 4826 4813 4827 \subsection{abs} 4814 4828 4829 \leavevmode 4815 4830 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4816 4831 char abs( char );§\indexc{abs}§ … … 4825 4840 long double abs( long double _Complex ); 4826 4841 \end{lstlisting} 4827 \4828 4842 4829 4843 4830 4844 \subsection{random} 4831 4845 4846 \leavevmode 4832 4847 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4833 4848 void rand48seed( long int s );§\indexc{rand48seed}§ … … 4843 4858 long double _Complex rand48(); 4844 4859 \end{lstlisting} 4845 \4846 4860 4847 4861 4848 4862 \subsection{min / max / clamp / swap} 4849 4863 4864 \leavevmode 4850 4865 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4851 4866 forall( otype T | { int ?<?( T, T ); } ) … … 4861 4876 void swap( T * t1, T * t2 );§\indexc{swap}§ 4862 4877 \end{lstlisting} 4863 \4864 4878 4865 4879 … … 4872 4886 \subsection{General} 4873 4887 4888 \leavevmode 4874 4889 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4875 4890 float fabs( float );§\indexc{fabs}§ … … 4917 4932 long double nan( const char * ); 4918 4933 \end{lstlisting} 4919 \4920 4934 4921 4935 4922 4936 \subsection{Exponential} 4923 4937 4938 \leavevmode 4924 4939 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4925 4940 float exp( float );§\indexc{exp}§ … … 4974 4989 long double logb( long double ); 4975 4990 \end{lstlisting} 4976 \4977 4991 4978 4992 4979 4993 \subsection{Power} 4980 4994 4995 \leavevmode 4981 4996 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 4982 4997 float sqrt( float );§\indexc{sqrt}§ … … 5002 5017 long double _Complex pow( long double _Complex, long double _Complex ); 5003 5018 \end{lstlisting} 5004 \5005 5019 5006 5020 5007 5021 \subsection{Trigonometric} 5008 5022 5023 \leavevmode 5009 5024 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 5010 5025 float sin( float );§\indexc{sin}§ … … 5058 5073 long double atan( long double, long double ); 5059 5074 \end{lstlisting} 5060 \5061 5075 5062 5076 5063 5077 \subsection{Hyperbolic} 5064 5078 5079 \leavevmode 5065 5080 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 5066 5081 float sinh( float );§\indexc{sinh}§ … … 5106 5121 long double _Complex atanh( long double _Complex ); 5107 5122 \end{lstlisting} 5108 \5109 5123 5110 5124 5111 5125 \subsection{Error / Gamma} 5112 5126 5127 \leavevmode 5113 5128 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 5114 5129 float erf( float );§\indexc{erf}§ … … 5137 5152 long double tgamma( long double ); 5138 5153 \end{lstlisting} 5139 \5140 5154 5141 5155 5142 5156 \subsection{Nearest Integer} 5143 5157 5158 \leavevmode 5144 5159 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 5145 5160 float floor( float );§\indexc{floor}§ … … 5191 5206 long long int llround( long double ); 5192 5207 \end{lstlisting} 5193 \5194 5208 5195 5209 5196 5210 \subsection{Manipulation} 5197 5211 5212 \leavevmode 5198 5213 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt] 5199 5214 float copysign( float, float );§\indexc{copysign}§ … … 5232 5247 long double scalbln( long double, long int ); 5233 5248 \end{lstlisting} 5234 \5235 5249 5236 5250 -
src/CodeGen/CodeGenerator.cc
r79841be r6943a987 83 83 } 84 84 85 CodeGenerator::CodeGenerator( std::ostream & os ) : indent( *this), cur_indent( 0 ), insideFunction( false ), output( os ), printLabels( *this) {}85 CodeGenerator::CodeGenerator( std::ostream & os, bool mangle ) : indent( *this), cur_indent( 0 ), insideFunction( false ), output( os ), printLabels( *this ), mangle( mangle ) {} 86 86 87 87 CodeGenerator::CodeGenerator( std::ostream & os, std::string init, int indentation, bool infunp ) … … 95 95 } 96 96 97 string mangleName( DeclarationWithType * decl ) { 97 string CodeGenerator::mangleName( DeclarationWithType * decl ) { 98 if ( ! mangle ) return decl->get_name(); 98 99 if ( decl->get_mangleName() != "" ) { 99 100 // need to incorporate scope level in order to differentiate names for destructors … … 311 312 Type * type = InitTweak::getPointerBase( (*arg)->get_results().front() ); 312 313 assert( type ); 313 newExpr->get_results().push_back( type );314 newExpr->get_results().push_back( type->clone() ); 314 315 *arg = newExpr; 315 316 } // if -
src/CodeGen/CodeGenerator.h
r79841be r6943a987 30 30 static int tabsize; 31 31 32 CodeGenerator( std::ostream &os );32 CodeGenerator( std::ostream &os, bool mangle = true ); 33 33 CodeGenerator( std::ostream &os, std::string, int indent = 0, bool infun = false ); 34 34 CodeGenerator( std::ostream &os, char *, int indent = 0, bool infun = false ); … … 114 114 std::ostream &output; 115 115 LabelPrinter printLabels; 116 bool mangle = true; 116 117 117 118 void printDesignators( std::list< Expression * > & ); … … 119 120 void handleAggregate( AggregateDecl *aggDecl ); 120 121 void handleTypedef( NamedTypeDecl *namedType ); 122 std::string mangleName( DeclarationWithType * decl ); 121 123 }; // CodeGenerator 122 124 -
src/CodeGen/GenType.cc
r79841be r6943a987 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // GenType.cc -- 7 // GenType.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 28 28 class GenType : public Visitor { 29 29 public: 30 GenType( const std::string &typeString );30 GenType( const std::string &typeString, bool mangle = true ); 31 31 std::string get_typeString() const { return typeString; } 32 32 void set_typeString( const std::string &newValue ) { typeString = newValue; } 33 33 34 34 virtual void visit( FunctionType *funcType ); 35 35 virtual void visit( VoidType *voidType ); … … 42 42 virtual void visit( TypeInstType *typeInst ); 43 43 virtual void visit( VarArgsType *varArgsType ); 44 44 45 45 private: 46 46 void handleQualifiers( Type *type ); 47 47 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic ); 48 48 49 49 std::string typeString; 50 bool mangle = true; 50 51 }; 51 52 52 std::string genType( Type *type, const std::string &baseString ) {53 GenType gt( baseString );53 std::string genType( Type *type, const std::string &baseString, bool mangle ) { 54 GenType gt( baseString, mangle ); 54 55 type->accept( gt ); 55 56 return gt.get_typeString(); 56 57 } 57 58 58 GenType::GenType( const std::string &typeString ) : typeString( typeString) {}59 GenType::GenType( const std::string &typeString, bool mangle ) : typeString( typeString ), mangle( mangle ) {} 59 60 60 61 void GenType::visit( VoidType *voidType ) { … … 100 101 } // if 101 102 if ( dimension != 0 ) { 102 CodeGenerator cg( os );103 CodeGenerator cg( os, mangle ); 103 104 dimension->accept( cg ); 104 105 } else if ( isVarLen ) { … … 109 110 110 111 typeString = os.str(); 111 112 112 113 base->accept( *this ); 113 114 } … … 142 143 } // if 143 144 } // if 144 145 145 146 /************* parameters ***************/ 146 147 … … 154 155 } // if 155 156 } else { 156 CodeGenerator cg( os );157 CodeGenerator cg( os, mangle ); 157 158 os << "(" ; 158 159 … … 164 165 os << ")"; 165 166 } // if 166 167 167 168 typeString = os.str(); 168 169 -
src/CodeGen/GenType.h
r79841be r6943a987 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // GenType.h -- 7 // GenType.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 21 21 22 22 namespace CodeGen { 23 std::string genType( Type *type, const std::string &baseString );23 std::string genType( Type *type, const std::string &baseString, bool mangle = true ); 24 24 } // namespace CodeGen 25 25 -
src/Common/CompilerError.h
r79841be r6943a987 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue May 19 07:20:37 201513 // Update Count : 212 // Last Modified On : Thu Aug 18 23:41:30 2016 13 // Update Count : 3 14 14 // 15 15 … … 18 18 19 19 #include <string> 20 //#include "../config.h"21 20 22 21 class CompilerError : public std::exception { -
src/Common/module.mk
r79841be r6943a987 11 11 ## Created On : Mon Jun 1 17:49:17 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Mon Jun 1 17:51:23 201514 ## Update Count : 113 ## Last Modified On : Thu Aug 18 13:29:04 2016 14 ## Update Count : 2 15 15 ############################################################################### 16 16 17 17 SRC += Common/SemanticError.cc \ 18 Common/UniqueName.cc 18 Common/UniqueName.cc \ 19 Common/Assert.cc -
src/Common/utility.h
r79841be r6943a987 49 49 } 50 50 51 template< typename T, typename U > 52 static inline T * maybeMoveBuild( const U *orig ) { 53 T* ret = maybeBuild<T>(orig); 54 delete orig; 55 return ret; 56 } 57 51 58 template< typename Input_iterator > 52 59 void printEnums( Input_iterator begin, Input_iterator end, const char * const *name_array, std::ostream &os ) { … … 137 144 138 145 template < typename T > 139 std::string toString ( T value ) { 146 void toString_single ( std::ostream & os, const T & value ) { 147 os << value; 148 } 149 150 template < typename T, typename... Params > 151 void toString_single ( std::ostream & os, const T & value, const Params & ... params ) { 152 os << value; 153 toString_single( os, params ... ); 154 } 155 156 template < typename ... Params > 157 std::string toString ( const Params & ... params ) { 140 158 std::ostringstream os; 141 os << value; // << std::ends;159 toString_single( os, params... ); 142 160 return os.str(); 143 161 } … … 211 229 } 212 230 231 template< typename T > 232 void warn_single( const T & arg ) { 233 std::cerr << arg << std::endl; 234 } 235 236 template< typename T, typename... Params > 237 void warn_single(const T & arg, const Params & ... params ) { 238 std::cerr << arg; 239 warn_single( params... ); 240 } 241 242 template< typename... Params > 243 void warn( const Params & ... params ) { 244 std::cerr << "Warning: "; 245 warn_single( params... ); 246 } 247 213 248 #endif // _UTILITY_H 214 249 -
src/InitTweak/FixInit.cc
r79841be r6943a987 33 33 #include "GenPoly/PolyMutator.h" 34 34 #include "SynTree/AddStmtVisitor.h" 35 #include "CodeGen/GenType.h" // for warnings 35 36 36 37 bool ctordtorp = false; … … 174 175 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 175 176 }; 177 178 class WarnStructMembers : public Visitor { 179 public: 180 typedef Visitor Parent; 181 /// warn if a user-defined constructor or destructor is missing calls for 182 /// a struct member or if a member is used before constructed 183 static void warnings( std::list< Declaration * > & translationUnit ); 184 185 virtual void visit( FunctionDecl * funcDecl ); 186 187 virtual void visit( MemberExpr * memberExpr ); 188 virtual void visit( ApplicationExpr * appExpr ); 189 190 private: 191 void handleFirstParam( Expression * firstParam ); 192 193 FunctionDecl * function = 0; 194 std::set< DeclarationWithType * > unhandled; 195 ObjectDecl * thisParam = 0; 196 }; 176 197 } // namespace 177 198 … … 187 208 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly 188 209 FixCopyCtors::fixCopyCtors( translationUnit ); 210 211 WarnStructMembers::warnings( translationUnit ); 189 212 } 190 213 … … 231 254 } 232 255 256 void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) { 257 if ( true ) { // fix this condition to skip this pass if warnings aren't enabled 258 WarnStructMembers warner; 259 acceptAll( translationUnit, warner ); 260 } 261 } 262 233 263 Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) { 234 264 appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) ); … … 242 272 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 243 273 assert( ftype ); 244 if ( ( funcDecl->get_name() == "?{}"|| funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) {274 if ( (isConstructor( funcDecl->get_name() ) || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) { 245 275 Type * t1 = ftype->get_parameters().front()->get_type(); 246 276 Type * t2 = ftype->get_parameters().back()->get_type(); … … 253 283 return appExpr; 254 284 } // if 255 } else if ( funcDecl->get_name() == "^?{}") {285 } else if ( isDestructor( funcDecl->get_name() ) ) { 256 286 // correctness: never copy construct arguments to a destructor 257 287 return appExpr; … … 284 314 UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) ); 285 315 untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) ); 286 if (cpArg) untyped->get_args().push_back( cpArg );316 if (cpArg) untyped->get_args().push_back( cpArg->clone() ); 287 317 288 318 // resolve copy constructor … … 670 700 } // switch 671 701 } 702 703 bool checkWarnings( FunctionDecl * funcDecl ) { 704 // only check for warnings if the current function is a user-defined 705 // constructor or destructor 706 if ( ! funcDecl ) return false; 707 if ( ! funcDecl->get_statements() ) return false; 708 return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() ); 709 } 710 711 void WarnStructMembers::visit( FunctionDecl * funcDecl ) { 712 WarnStructMembers old = *this; 713 *this = WarnStructMembers(); 714 715 function = funcDecl; 716 if ( checkWarnings( funcDecl ) ) { 717 FunctionType * type = funcDecl->get_functionType(); 718 assert( ! type->get_parameters().empty() ); 719 thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() ); 720 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() ); 721 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() ); 722 if ( structType ) { 723 StructDecl * structDecl = structType->get_baseStruct(); 724 for ( Declaration * member : structDecl->get_members() ) { 725 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 726 // record all of the struct type's members that need to be constructed or 727 // destructed by the end of the function 728 unhandled.insert( field ); 729 } 730 } 731 } 732 } 733 Parent::visit( funcDecl ); 734 735 for ( DeclarationWithType * member : unhandled ) { 736 // emit a warning for each unhandled member 737 warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" ); 738 } 739 740 *this = old; 741 } 742 743 void WarnStructMembers::visit( ApplicationExpr * appExpr ) { 744 if ( ! checkWarnings( function ) ) return; 745 746 std::string fname = getFunctionName( appExpr ); 747 if ( fname == function->get_name() ) { 748 // call to same kind of function 749 Expression * firstParam = appExpr->get_args().front(); 750 751 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) { 752 // if calling another constructor on thisParam, assume that function handles 753 // all members - if it doesn't a warning will appear in that function. 754 if ( varExpr->get_var() == thisParam ) { 755 unhandled.clear(); 756 } 757 } else { 758 // if first parameter is a member expression then 759 // remove the member from unhandled set. 760 handleFirstParam( firstParam ); 761 } 762 } else if ( fname == "?=?" && isIntrinsicCallExpr( appExpr ) ) { 763 // forgive use of intrinsic assignment to construct, since instrinsic constructors 764 // codegen as assignment anyway. 765 assert( appExpr->get_args().size() == 2 ); 766 handleFirstParam( appExpr->get_args().front() ); 767 } 768 769 Parent::visit( appExpr ); 770 } 771 772 void WarnStructMembers::handleFirstParam( Expression * firstParam ) { 773 using namespace std; 774 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) { 775 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) { 776 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 777 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 778 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 779 if ( varExpr->get_var() == thisParam ) { 780 unhandled.erase( memberExpr->get_member() ); 781 } 782 } 783 } 784 } 785 } 786 } 787 } 788 789 void WarnStructMembers::visit( MemberExpr * memberExpr ) { 790 if ( ! checkWarnings( function ) ) return; 791 if ( ! isConstructor( function->get_name() ) ) return; 792 793 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 794 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 795 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 796 if ( varExpr->get_var() == thisParam ) { 797 if ( unhandled.count( memberExpr->get_member() ) ) { 798 // emit a warning because a member was used before it was constructed 799 warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" ); 800 } 801 } 802 } 803 } 804 } 805 Parent::visit( memberExpr ); 806 } 672 807 } // namespace 673 808 } // namespace InitTweak -
src/InitTweak/InitTweak.cc
r79841be r6943a987 291 291 } 292 292 293 namespace { 294 template <typename Predicate> 295 bool allofCtorDtor( Statement * stmt, const Predicate & pred ) { 296 std::list< Expression * > callExprs; 297 collectCtorDtorCalls( stmt, callExprs ); 298 // if ( callExprs.empty() ) return false; // xxx - do I still need this check? 299 return std::all_of( callExprs.begin(), callExprs.end(), pred); 300 } 301 } 302 293 303 bool isIntrinsicSingleArgCallStmt( Statement * stmt ) { 294 std::list< Expression * > callExprs; 295 collectCtorDtorCalls( stmt, callExprs ); 296 // if ( callExprs.empty() ) return false; // xxx - do I still need this check? 297 return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){ 304 return allofCtorDtor( stmt, []( Expression * callExpr ){ 298 305 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 299 306 assert( ! appExpr->get_function()->get_results().empty() ); … … 303 310 } 304 311 return false; 312 }); 313 } 314 315 bool isIntrinsicCallStmt( Statement * stmt ) { 316 return allofCtorDtor( stmt, []( Expression * callExpr ) { 317 return isIntrinsicCallExpr( callExpr ); 305 318 }); 306 319 } … … 420 433 } 421 434 435 bool isConstructor( const std::string & str ) { return str == "?{}"; } 436 bool isDestructor( const std::string & str ) { return str == "^?{}"; } 437 bool isCtorDtor( const std::string & str ) { return isConstructor( str ) || isDestructor( str ); } 422 438 } -
src/InitTweak/InitTweak.h
r79841be r6943a987 26 26 // helper functions for initialization 27 27 namespace InitTweak { 28 bool isConstructor( const std::string & ); 29 bool isDestructor( const std::string & ); 30 bool isCtorDtor( const std::string & ); 31 28 32 /// transform Initializer into an argument list that can be passed to a call expression 29 33 std::list< Expression * > makeInitList( Initializer * init ); … … 41 45 /// Intended to be used for default ctor/dtor calls, but might have use elsewhere. 42 46 /// Currently has assertions that make it less than fully general. 43 bool isIntrinsicSingleArgCallStmt( Statement * expr ); 47 bool isIntrinsicSingleArgCallStmt( Statement * stmt ); 48 49 /// True if stmt is a call statement where the function called is intrinsic. 50 bool isIntrinsicCallStmt( Statement * stmt ); 44 51 45 52 /// get all Ctor/Dtor call expressions from a Statement -
src/Makefile.am
r79841be r6943a987 11 11 ## Created On : Sun May 31 08:51:46 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Fri Jul 8 12:22:25201614 ## Update Count : 6013 ## Last Modified On : Sat Aug 20 11:13:12 2016 14 ## Update Count : 71 15 15 ############################################################################### 16 16 … … 42 42 cfa_cpplib_PROGRAMS = driver/cfa-cpp 43 43 driver_cfa_cpp_SOURCES = ${SRC} 44 driver_cfa_cpp_LDADD = ${LEXLIB} # yywrap 45 # need files Common/utility.h 46 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL 47 48 AM_CXXFLAGS = -g -std=c++11 44 driver_cfa_cpp_LDADD = ${LEXLIB} # yywrap 45 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL -rdynamic -I${abs_top_srcdir}/src/include 49 46 50 47 MAINTAINERCLEANFILES += ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}} -
src/Makefile.in
r79841be r6943a987 105 105 Common/driver_cfa_cpp-SemanticError.$(OBJEXT) \ 106 106 Common/driver_cfa_cpp-UniqueName.$(OBJEXT) \ 107 Common/driver_cfa_cpp-Assert.$(OBJEXT) \ 107 108 ControlStruct/driver_cfa_cpp-LabelGenerator.$(OBJEXT) \ 108 109 ControlStruct/driver_cfa_cpp-LabelFixer.$(OBJEXT) \ … … 137 138 Parser/driver_cfa_cpp-LinkageSpec.$(OBJEXT) \ 138 139 Parser/driver_cfa_cpp-parseutility.$(OBJEXT) \ 139 Parser/driver_cfa_cpp-Parser.$(OBJEXT) \140 140 ResolvExpr/driver_cfa_cpp-AlternativeFinder.$(OBJEXT) \ 141 141 ResolvExpr/driver_cfa_cpp-Alternative.$(OBJEXT) \ … … 370 370 CodeGen/CodeGenerator.cc CodeGen/GenType.cc \ 371 371 CodeGen/FixNames.cc CodeGen/OperatorTable.cc \ 372 Common/SemanticError.cc Common/UniqueName.cc \372 Common/SemanticError.cc Common/UniqueName.cc Common/Assert.cc \ 373 373 ControlStruct/LabelGenerator.cc ControlStruct/LabelFixer.cc \ 374 374 ControlStruct/MLEMutator.cc ControlStruct/Mutate.cc \ … … 385 385 Parser/ExpressionNode.cc Parser/StatementNode.cc \ 386 386 Parser/InitializerNode.cc Parser/TypeData.cc \ 387 Parser/LinkageSpec.cc Parser/parseutility.cc Parser/Parser.cc\387 Parser/LinkageSpec.cc Parser/parseutility.cc \ 388 388 ResolvExpr/AlternativeFinder.cc ResolvExpr/Alternative.cc \ 389 389 ResolvExpr/Unify.cc ResolvExpr/PtrsAssignable.cc \ … … 426 426 cfa_cpplibdir = ${libdir} 427 427 driver_cfa_cpp_SOURCES = ${SRC} 428 driver_cfa_cpp_LDADD = ${LEXLIB} # yywrap 429 # need files Common/utility.h 430 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL 431 AM_CXXFLAGS = -g -std=c++11 428 driver_cfa_cpp_LDADD = ${LEXLIB} # yywrap 429 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL -rdynamic -I${abs_top_srcdir}/src/include 432 430 all: $(BUILT_SOURCES) 433 431 $(MAKE) $(AM_MAKEFLAGS) all-am … … 528 526 Common/$(DEPDIR)/$(am__dirstamp) 529 527 Common/driver_cfa_cpp-UniqueName.$(OBJEXT): Common/$(am__dirstamp) \ 528 Common/$(DEPDIR)/$(am__dirstamp) 529 Common/driver_cfa_cpp-Assert.$(OBJEXT): Common/$(am__dirstamp) \ 530 530 Common/$(DEPDIR)/$(am__dirstamp) 531 531 ControlStruct/$(am__dirstamp): … … 632 632 Parser/$(DEPDIR)/$(am__dirstamp) 633 633 Parser/driver_cfa_cpp-parseutility.$(OBJEXT): Parser/$(am__dirstamp) \ 634 Parser/$(DEPDIR)/$(am__dirstamp)635 Parser/driver_cfa_cpp-Parser.$(OBJEXT): Parser/$(am__dirstamp) \636 634 Parser/$(DEPDIR)/$(am__dirstamp) 637 635 ResolvExpr/$(am__dirstamp): … … 817 815 -rm -f CodeGen/driver_cfa_cpp-Generate.$(OBJEXT) 818 816 -rm -f CodeGen/driver_cfa_cpp-OperatorTable.$(OBJEXT) 817 -rm -f Common/driver_cfa_cpp-Assert.$(OBJEXT) 819 818 -rm -f Common/driver_cfa_cpp-SemanticError.$(OBJEXT) 820 819 -rm -f Common/driver_cfa_cpp-UniqueName.$(OBJEXT) … … 845 844 -rm -f Parser/driver_cfa_cpp-LinkageSpec.$(OBJEXT) 846 845 -rm -f Parser/driver_cfa_cpp-ParseNode.$(OBJEXT) 847 -rm -f Parser/driver_cfa_cpp-Parser.$(OBJEXT)848 846 -rm -f Parser/driver_cfa_cpp-StatementNode.$(OBJEXT) 849 847 -rm -f Parser/driver_cfa_cpp-TypeData.$(OBJEXT) … … 927 925 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-Generate.Po@am__quote@ 928 926 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/driver_cfa_cpp-OperatorTable.Po@am__quote@ 927 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-Assert.Po@am__quote@ 929 928 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-SemanticError.Po@am__quote@ 930 929 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/driver_cfa_cpp-UniqueName.Po@am__quote@ … … 955 954 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-LinkageSpec.Po@am__quote@ 956 955 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-ParseNode.Po@am__quote@ 957 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-Parser.Po@am__quote@958 956 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-StatementNode.Po@am__quote@ 959 957 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-TypeData.Po@am__quote@ … … 1169 1167 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-UniqueName.obj `if test -f 'Common/UniqueName.cc'; then $(CYGPATH_W) 'Common/UniqueName.cc'; else $(CYGPATH_W) '$(srcdir)/Common/UniqueName.cc'; fi` 1170 1168 1169 Common/driver_cfa_cpp-Assert.o: Common/Assert.cc 1170 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-Assert.o -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo -c -o Common/driver_cfa_cpp-Assert.o `test -f 'Common/Assert.cc' || echo '$(srcdir)/'`Common/Assert.cc 1171 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo Common/$(DEPDIR)/driver_cfa_cpp-Assert.Po 1172 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Common/Assert.cc' object='Common/driver_cfa_cpp-Assert.o' libtool=no @AMDEPBACKSLASH@ 1173 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1174 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-Assert.o `test -f 'Common/Assert.cc' || echo '$(srcdir)/'`Common/Assert.cc 1175 1176 Common/driver_cfa_cpp-Assert.obj: Common/Assert.cc 1177 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Common/driver_cfa_cpp-Assert.obj -MD -MP -MF Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo -c -o Common/driver_cfa_cpp-Assert.obj `if test -f 'Common/Assert.cc'; then $(CYGPATH_W) 'Common/Assert.cc'; else $(CYGPATH_W) '$(srcdir)/Common/Assert.cc'; fi` 1178 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) Common/$(DEPDIR)/driver_cfa_cpp-Assert.Tpo Common/$(DEPDIR)/driver_cfa_cpp-Assert.Po 1179 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Common/Assert.cc' object='Common/driver_cfa_cpp-Assert.obj' libtool=no @AMDEPBACKSLASH@ 1180 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1181 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Common/driver_cfa_cpp-Assert.obj `if test -f 'Common/Assert.cc'; then $(CYGPATH_W) 'Common/Assert.cc'; else $(CYGPATH_W) '$(srcdir)/Common/Assert.cc'; fi` 1182 1171 1183 ControlStruct/driver_cfa_cpp-LabelGenerator.o: ControlStruct/LabelGenerator.cc 1172 1184 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-LabelGenerator.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Tpo -c -o ControlStruct/driver_cfa_cpp-LabelGenerator.o `test -f 'ControlStruct/LabelGenerator.cc' || echo '$(srcdir)/'`ControlStruct/LabelGenerator.cc … … 1616 1628 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 1617 1629 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-parseutility.obj `if test -f 'Parser/parseutility.cc'; then $(CYGPATH_W) 'Parser/parseutility.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/parseutility.cc'; fi` 1618 1619 Parser/driver_cfa_cpp-Parser.o: Parser/Parser.cc1620 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-Parser.o -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-Parser.Tpo -c -o Parser/driver_cfa_cpp-Parser.o `test -f 'Parser/Parser.cc' || echo '$(srcdir)/'`Parser/Parser.cc1621 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-Parser.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-Parser.Po1622 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Parser/Parser.cc' object='Parser/driver_cfa_cpp-Parser.o' libtool=no @AMDEPBACKSLASH@1623 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1624 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-Parser.o `test -f 'Parser/Parser.cc' || echo '$(srcdir)/'`Parser/Parser.cc1625 1626 Parser/driver_cfa_cpp-Parser.obj: Parser/Parser.cc1627 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Parser/driver_cfa_cpp-Parser.obj -MD -MP -MF Parser/$(DEPDIR)/driver_cfa_cpp-Parser.Tpo -c -o Parser/driver_cfa_cpp-Parser.obj `if test -f 'Parser/Parser.cc'; then $(CYGPATH_W) 'Parser/Parser.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/Parser.cc'; fi`1628 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) Parser/$(DEPDIR)/driver_cfa_cpp-Parser.Tpo Parser/$(DEPDIR)/driver_cfa_cpp-Parser.Po1629 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Parser/Parser.cc' object='Parser/driver_cfa_cpp-Parser.obj' libtool=no @AMDEPBACKSLASH@1630 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1631 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Parser/driver_cfa_cpp-Parser.obj `if test -f 'Parser/Parser.cc'; then $(CYGPATH_W) 'Parser/Parser.cc'; else $(CYGPATH_W) '$(srcdir)/Parser/Parser.cc'; fi`1632 1630 1633 1631 ResolvExpr/driver_cfa_cpp-AlternativeFinder.o: ResolvExpr/AlternativeFinder.cc -
src/Parser/DeclarationNode.cc
r79841be r6943a987 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Aug 9 08:39:20201613 // Update Count : 16912 // Last Modified On : Sun Aug 28 22:12:44 2016 13 // Update Count : 278 14 14 // 15 15 … … 25 25 #include "SynTree/Expression.h" 26 26 27 #include "Parser.h"28 27 #include "TypedefTable.h" 29 28 extern TypedefTable typedefTable; … … 42 41 UniqueName DeclarationNode::anonymous( "__anonymous" ); 43 42 44 extern LinkageSpec:: Typelinkage; // defined in parser.yy43 extern LinkageSpec::Spec linkage; // defined in parser.yy 45 44 46 45 DeclarationNode *DeclarationNode::clone() const { … … 48 47 newnode->type = maybeClone( type ); 49 48 newnode->name = name; 50 newnode->storageClasses = storageClasses; 51 //PAB newnode->bitfieldWidth = maybeClone( bitfieldWidth ); 52 newnode->bitfieldWidth = bitfieldWidth; 49 newnode->storageClass = storageClass; 50 newnode->isInline = isInline; 51 newnode->isNoreturn = isNoreturn; 52 newnode->bitfieldWidth = maybeClone( bitfieldWidth ); 53 53 newnode->hasEllipsis = hasEllipsis; 54 newnode->initializer = initializer;55 newnode-> next = maybeClone( next);54 newnode->initializer = maybeClone( initializer ); 55 newnode->set_next( maybeClone( get_next() ) ); 56 56 newnode->linkage = linkage; 57 57 return newnode; 58 58 } // DeclarationNode::clone 59 59 60 DeclarationNode::DeclarationNode() : type( 0 ), bitfieldWidth( 0 ), initializer( 0 ), hasEllipsis( false ), linkage( ::linkage ) { 60 DeclarationNode::DeclarationNode() 61 : type( 0 ) 62 , storageClass( NoStorageClass ) 63 , isInline( false ) 64 , isNoreturn( false ) 65 , bitfieldWidth( 0 ) 66 , initializer( 0 ) 67 , hasEllipsis( false ) 68 , linkage( ::linkage ) 69 , extension( false ) 70 , error() { 61 71 } 62 72 … … 83 93 } // if 84 94 85 printEnums( storageClasses.begin(), storageClasses.end(), DeclarationNode::storageName, os ); 95 if ( storageClass != NoStorageClass ) os << DeclarationNode::storageName[storageClass] << ' '; 96 if ( isInline ) os << DeclarationNode::storageName[Inline] << ' '; 97 if ( isNoreturn ) os << DeclarationNode::storageName[Noreturn] << ' '; 86 98 if ( type ) { 87 99 type->print( os, indent ); … … 135 147 } // DeclarationNode::newFunction 136 148 137 DeclarationNode * DeclarationNode::newQualifier( Qualifier q ) {149 DeclarationNode * DeclarationNode::newQualifier( Qualifier q ) { 138 150 DeclarationNode *newnode = new DeclarationNode; 139 151 newnode->type = new TypeData(); 140 newnode->type->qualifiers .push_back( q );152 newnode->type->qualifiers[ q ] = 1; 141 153 return newnode; 142 154 } // DeclarationNode::newQualifier 143 155 144 DeclarationNode *DeclarationNode::newStorageClass( DeclarationNode::StorageClass sc ) { 145 DeclarationNode *newnode = new DeclarationNode; 146 newnode->storageClasses.push_back( sc ); 156 DeclarationNode * DeclarationNode::newForall( DeclarationNode *forall ) { 157 DeclarationNode *newnode = new DeclarationNode; 158 newnode->type = new TypeData( TypeData::Unknown ); 159 newnode->type->forall = forall; 160 return newnode; 161 } // DeclarationNode::newForall 162 163 DeclarationNode * DeclarationNode::newStorageClass( DeclarationNode::StorageClass sc ) { 164 DeclarationNode *newnode = new DeclarationNode; 165 //switch (sc) { 166 // case Inline: newnode->isInline = true; break; 167 // case Noreturn: newnode->isNoreturn = true; break; 168 // default: newnode->storageClass = sc; break; 169 //} 170 newnode->storageClass = sc; 147 171 return newnode; 148 172 } // DeclarationNode::newStorageClass 149 173 150 DeclarationNode * DeclarationNode::newBasicType( BasicType bt ) {174 DeclarationNode * DeclarationNode::newBasicType( BasicType bt ) { 151 175 DeclarationNode *newnode = new DeclarationNode; 152 176 newnode->type = new TypeData( TypeData::Basic ); … … 155 179 } // DeclarationNode::newBasicType 156 180 157 DeclarationNode *DeclarationNode::newBuiltinType( BuiltinType bt ) { 181 DeclarationNode * DeclarationNode::newModifier( Modifier mod ) { 182 DeclarationNode *newnode = new DeclarationNode; 183 newnode->type = new TypeData( TypeData::Basic ); 184 newnode->type->basic->modifiers.push_back( mod ); 185 return newnode; 186 } // DeclarationNode::newModifier 187 188 DeclarationNode * DeclarationNode::newBuiltinType( BuiltinType bt ) { 158 189 DeclarationNode *newnode = new DeclarationNode; 159 190 newnode->type = new TypeData( TypeData::Builtin ); … … 162 193 } // DeclarationNode::newBuiltinType 163 194 164 DeclarationNode *DeclarationNode::newModifier( Modifier mod ) { 165 DeclarationNode *newnode = new DeclarationNode; 166 newnode->type = new TypeData( TypeData::Basic ); 167 newnode->type->basic->modifiers.push_back( mod ); 168 return newnode; 169 } // DeclarationNode::newModifier 170 171 DeclarationNode *DeclarationNode::newForall( DeclarationNode *forall ) { 172 DeclarationNode *newnode = new DeclarationNode; 173 newnode->type = new TypeData( TypeData::Unknown ); 174 newnode->type->forall = forall; 175 return newnode; 176 } // DeclarationNode::newForall 177 178 DeclarationNode *DeclarationNode::newFromTypedef( std::string *name ) { 195 DeclarationNode * DeclarationNode::newFromTypedef( std::string *name ) { 179 196 DeclarationNode *newnode = new DeclarationNode; 180 197 newnode->type = new TypeData( TypeData::SymbolicInst ); … … 185 202 } // DeclarationNode::newFromTypedef 186 203 187 DeclarationNode * DeclarationNode::newAggregate( Aggregate kind, const std::string *name, ExpressionNode *actuals, DeclarationNode *fields, bool body ) {204 DeclarationNode * DeclarationNode::newAggregate( Aggregate kind, const std::string *name, ExpressionNode *actuals, DeclarationNode *fields, bool body ) { 188 205 DeclarationNode *newnode = new DeclarationNode; 189 206 newnode->type = new TypeData( TypeData::Aggregate ); … … 214 231 DeclarationNode *newnode = new DeclarationNode; 215 232 newnode->name = assign_strptr( name ); 216 newnode->enumeratorValue = constant;233 newnode->enumeratorValue.reset( constant ); 217 234 typedefTable.addToEnclosingScope( newnode->name, TypedefTable::ID ); 218 235 return newnode; … … 284 301 newnode->type->array->dimension = size; 285 302 newnode->type->array->isStatic = isStatic; 286 if ( newnode->type->array->dimension == 0 || dynamic_cast<ConstantExpr *>( newnode->type->array->dimension->build()) ) {303 if ( newnode->type->array->dimension == 0 || newnode->type->array->dimension->isExpressionType<ConstantExpr *>() ) { 287 304 newnode->type->array->isVarLen = false; 288 305 } else { … … 353 370 src = 0; 354 371 } else { 355 dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers ); 356 } // if 357 } // if 358 } 372 dst->qualifiers |= src->qualifiers; 373 } // if 374 } // if 375 } 376 377 void DeclarationNode::checkQualifiers( const TypeData *src, const TypeData *dst ) { 378 TypeData::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; 379 380 if ( (qsrc & qdst).any() ) { // common bits between qualifier masks ? 381 error = "duplicate qualifier "; 382 int j = 0; // separator detector 383 for ( int i = 0; i < DeclarationNode::NoOfQualifier; i += 1 ) { 384 if ( qsrc[i] & qdst[i] ) { // find specific qualifiers in common 385 if ( j > 0 ) error += ", "; 386 error += DeclarationNode::qualifierName[i]; 387 j += 1; 388 } // if 389 } // for 390 error += " in declaration of "; 391 } // if 392 } // DeclarationNode::checkQualifiers 359 393 360 394 DeclarationNode *DeclarationNode::addQualifiers( DeclarationNode *q ) { 361 395 if ( q ) { 362 storageClasses.splice( storageClasses.end(), q->storageClasses);396 copyStorageClasses(q); 363 397 if ( q->type ) { 364 398 if ( ! type ) { 365 399 type = new TypeData; 400 } else { 401 checkQualifiers( q->type, type ); 366 402 } // if 367 403 addQualifiersToType( q->type, type ); … … 387 423 388 424 DeclarationNode *DeclarationNode::copyStorageClasses( DeclarationNode *q ) { 389 storageClasses = q->storageClasses; 425 isInline = isInline || q->isInline; 426 isNoreturn = isNoreturn || q->isNoreturn; 427 if ( storageClass == NoStorageClass ) { 428 storageClass = q->storageClass; 429 } else if ( q->storageClass != NoStorageClass ) { 430 q->error = "invalid combination of storage classes in declaration of "; 431 } // if 432 if ( error.empty() ) error = q->error; 390 433 return this; 391 434 } … … 406 449 switch ( dst->kind ) { 407 450 case TypeData::Unknown: 408 src->qualifiers .splice( src->qualifiers.end(), dst->qualifiers );451 src->qualifiers |= dst->qualifiers; 409 452 dst = src; 410 453 src = 0; 411 454 break; 412 455 case TypeData::Basic: 413 dst->qualifiers .splice( dst->qualifiers.end(), src->qualifiers );456 dst->qualifiers |= src->qualifiers; 414 457 if ( src->kind != TypeData::Unknown ) { 415 458 assert( src->kind == TypeData::Basic ); … … 427 470 dst->base->aggInst->params = maybeClone( src->aggregate->actuals ); 428 471 } // if 429 dst->base->qualifiers .splice( dst->base->qualifiers.end(), src->qualifiers );472 dst->base->qualifiers |= src->qualifiers; 430 473 src = 0; 431 474 break; … … 447 490 DeclarationNode *DeclarationNode::addType( DeclarationNode *o ) { 448 491 if ( o ) { 449 storageClasses.splice( storageClasses.end(), o->storageClasses);492 copyStorageClasses( o ); 450 493 if ( o->type ) { 451 494 if ( ! type ) { … … 456 499 type->aggInst->params = maybeClone( o->type->aggregate->actuals ); 457 500 } // if 458 type->qualifiers .splice( type->qualifiers.end(), o->type->qualifiers );501 type->qualifiers |= o->type->qualifiers; 459 502 } else { 460 503 type = o->type; … … 470 513 471 514 // there may be typedefs chained onto the type 472 if ( o->get_ link() ) {473 set_l ink( o->get_link()->clone() );515 if ( o->get_next() ) { 516 set_last( o->get_next()->clone() ); 474 517 } // if 475 518 } // if … … 591 634 p->type->base->aggInst->params = maybeClone( type->aggregate->actuals ); 592 635 } // if 593 p->type->base->qualifiers .splice( p->type->base->qualifiers.end(), type->qualifiers );636 p->type->base->qualifiers |= type->qualifiers; 594 637 break; 595 638 … … 628 671 lastArray->base->aggInst->params = maybeClone( type->aggregate->actuals ); 629 672 } // if 630 lastArray->base->qualifiers .splice( lastArray->base->qualifiers.end(), type->qualifiers );673 lastArray->base->qualifiers |= type->qualifiers; 631 674 break; 632 675 default: … … 694 737 } // if 695 738 newnode->type->forall = maybeClone( type->forall ); 696 newnode-> storageClasses = storageClasses;739 newnode->copyStorageClasses( this ); 697 740 newnode->name = assign_strptr( newName ); 698 741 return newnode; … … 701 744 DeclarationNode *DeclarationNode::cloneBaseType( DeclarationNode *o ) { 702 745 if ( o ) { 703 o-> storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end());746 o->copyStorageClasses( this ); 704 747 if ( type ) { 705 748 TypeData *srcType = type; … … 734 777 DeclarationNode *newnode = new DeclarationNode; 735 778 newnode->type = maybeClone( type ); 736 newnode-> storageClasses = storageClasses;779 newnode->copyStorageClasses( this ); 737 780 newnode->name = assign_strptr( newName ); 738 781 return newnode; … … 741 784 DeclarationNode *DeclarationNode::cloneType( DeclarationNode *o ) { 742 785 if ( o ) { 743 o-> storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end());786 o->copyStorageClasses( this ); 744 787 if ( type ) { 745 788 TypeData *newType = type->clone(); … … 752 795 } // if 753 796 } // if 797 delete o; 754 798 return o; 755 }756 757 DeclarationNode *DeclarationNode::appendList( DeclarationNode *node ) {758 if ( node != 0 ) {759 set_link( node );760 } // if761 return this;762 799 } 763 800 764 801 DeclarationNode *DeclarationNode::extractAggregate() const { 765 802 if ( type ) { 766 TypeData *ret = type ->extractAggregate();803 TypeData *ret = typeextractAggregate( type ); 767 804 if ( ret ) { 768 805 DeclarationNode *newnode = new DeclarationNode; … … 776 813 void buildList( const DeclarationNode *firstNode, std::list< Declaration * > &outputList ) { 777 814 SemanticError errors; 778 std::back_insert_iterator< std::list< Declaration * > > out( outputList );815 std::back_insert_iterator< std::list< Declaration * > > out( outputList ); 779 816 const DeclarationNode *cur = firstNode; 780 817 while ( cur ) { … … 786 823 *out++ = decl; 787 824 } // if 825 delete extr; 788 826 } // if 789 827 Declaration *decl = cur->build(); … … 794 832 errors.append( e ); 795 833 } // try 796 cur = dynamic_cast< DeclarationNode *>( cur->get_link() );834 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 797 835 } // while 798 836 if ( ! errors.isEmpty() ) { … … 801 839 } 802 840 803 void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType * > &outputList ) {841 void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType * > &outputList ) { 804 842 SemanticError errors; 805 std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );843 std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList ); 806 844 const DeclarationNode *cur = firstNode; 807 845 while ( cur ) { … … 817 855 Declaration *decl = cur->build(); 818 856 if ( decl ) { 819 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {857 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 820 858 *out++ = dwt; 821 } else if ( StructDecl *agg = dynamic_cast< StructDecl * >( decl ) ) {859 } else if ( StructDecl *agg = dynamic_cast< StructDecl * >( decl ) ) { 822 860 StructInstType *inst = new StructInstType( Type::Qualifiers(), agg->get_name() ); 823 861 *out++ = new ObjectDecl( "", DeclarationNode::NoStorageClass, linkage, 0, inst, 0 ); 824 862 delete agg; 825 } else if ( UnionDecl *agg = dynamic_cast< UnionDecl * >( decl ) ) {863 } else if ( UnionDecl *agg = dynamic_cast< UnionDecl * >( decl ) ) { 826 864 UnionInstType *inst = new UnionInstType( Type::Qualifiers(), agg->get_name() ); 827 865 *out++ = new ObjectDecl( "", DeclarationNode::NoStorageClass, linkage, 0, inst, 0 ); … … 831 869 errors.append( e ); 832 870 } // try 833 cur = dynamic_cast< DeclarationNode * >( cur->get_link() );871 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 834 872 } // while 835 873 if ( ! errors.isEmpty() ) { … … 838 876 } 839 877 840 void buildTypeList( const DeclarationNode *firstNode, std::list< Type * > &outputList ) {878 void buildTypeList( const DeclarationNode *firstNode, std::list< Type * > &outputList ) { 841 879 SemanticError errors; 842 std::back_insert_iterator< std::list< Type * > > out( outputList );880 std::back_insert_iterator< std::list< Type * > > out( outputList ); 843 881 const DeclarationNode *cur = firstNode; 844 882 while ( cur ) { … … 848 886 errors.append( e ); 849 887 } // try 850 cur = dynamic_cast< DeclarationNode * >( cur->get_link() );888 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 851 889 } // while 852 890 if ( ! errors.isEmpty() ) { … … 856 894 857 895 Declaration *DeclarationNode::build() const { 896 if ( ! error.empty() ) throw SemanticError( error, this ); 858 897 if ( type ) { 859 return type->buildDecl( name, buildStorageClass(), maybeBuild< Expression >( bitfieldWidth ), buildFuncSpecifier( Inline ), buildFuncSpecifier( Noreturn ), linkage, maybeBuild< Initializer >(initializer) )->set_extension( extension );860 } // if 861 if ( ! buildFuncSpecifier( Inline ) && ! buildFuncSpecifier( Noreturn )) {862 return (new ObjectDecl( name, buildStorageClass(), linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) ))->set_extension( extension );898 return buildDecl( type, name, storageClass, maybeBuild< Expression >( bitfieldWidth ), isInline, isNoreturn, linkage, maybeBuild< Initializer >(initializer) )->set_extension( extension ); 899 } // if 900 if ( ! isInline && ! isNoreturn ) { 901 return (new ObjectDecl( name, storageClass, linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) ))->set_extension( extension ); 863 902 } // if 864 903 throw SemanticError( "invalid function specifier in declaration of ", this ); … … 870 909 switch ( type->kind ) { 871 910 case TypeData::Enum: 872 return new EnumInstType( type->buildQualifiers(), type->enumeration->name );911 return new EnumInstType( buildQualifiers( type ), type->enumeration->name ); 873 912 case TypeData::Aggregate: { 874 913 ReferenceToType *ret; 875 914 switch ( type->aggregate->kind ) { 876 915 case DeclarationNode::Struct: 877 ret = new StructInstType( type->buildQualifiers(), type->aggregate->name );916 ret = new StructInstType( buildQualifiers( type ), type->aggregate->name ); 878 917 break; 879 918 case DeclarationNode::Union: 880 ret = new UnionInstType( type->buildQualifiers(), type->aggregate->name );919 ret = new UnionInstType( buildQualifiers( type ), type->aggregate->name ); 881 920 break; 882 921 case DeclarationNode::Trait: 883 ret = new TraitInstType( type->buildQualifiers(), type->aggregate->name );922 ret = new TraitInstType( buildQualifiers( type ), type->aggregate->name ); 884 923 break; 885 924 default: … … 890 929 } 891 930 case TypeData::Symbolic: { 892 TypeInstType *ret = new TypeInstType( type->buildQualifiers(), type->symbolic->name, false );931 TypeInstType *ret = new TypeInstType( buildQualifiers( type ), type->symbolic->name, false ); 893 932 buildList( type->symbolic->actuals, ret->get_parameters() ); 894 933 return ret; 895 934 } 896 935 default: 897 return type ->build();936 return typebuild( type ); 898 937 } // switch 899 938 } 900 939 901 DeclarationNode::StorageClass DeclarationNode::buildStorageClass() const {902 DeclarationNode::StorageClass ret = DeclarationNode::NoStorageClass;903 for ( std::list< DeclarationNode::StorageClass >::const_iterator i = storageClasses.begin(); i != storageClasses.end(); ++i ) {904 if ( *i == DeclarationNode::Inline || *i == DeclarationNode::Noreturn ) continue; // ignore function specifiers905 if ( ret != DeclarationNode::NoStorageClass ) { // already have a valid storage class ?906 throw SemanticError( "invalid combination of storage classes in declaration of ", this );907 } // if908 ret = *i;909 } // for910 return ret;911 }912 913 bool DeclarationNode::buildFuncSpecifier( DeclarationNode::StorageClass key ) const {914 std::list< DeclarationNode::StorageClass >::const_iterator first = std::find( storageClasses.begin(), storageClasses.end(), key );915 if ( first == storageClasses.end() ) return false; // not found916 first = std::find( ++first, storageClasses.end(), key ); // found917 if ( first == storageClasses.end() ) return true; // not found again918 throw SemanticError( "duplicate function specifier in declaration of ", this );919 }940 // DeclarationNode::StorageClass DeclarationNode::buildStorageClass() const { 941 // DeclarationNode::StorageClass ret = DeclarationNode::NoStorageClass; 942 // for ( std::list< DeclarationNode::StorageClass >::const_iterator i = storageClasses.begin(); i != storageClasses.end(); ++i ) { 943 // if ( *i == DeclarationNode::Inline || *i == DeclarationNode::Noreturn ) continue; // ignore function specifiers 944 // if ( ret != DeclarationNode::NoStorageClass ) { // already have a valid storage class ? 945 // throw SemanticError( "invalid combination of storage classes in declaration of ", this ); 946 // } // if 947 // ret = *i; 948 // } // for 949 // return ret; 950 // } 951 952 // bool DeclarationNode::buildFuncSpecifier( DeclarationNode::StorageClass key ) const { 953 // std::list< DeclarationNode::StorageClass >::const_iterator first = std::find( storageClasses.begin(), storageClasses.end(), key ); 954 // if ( first == storageClasses.end() ) return false; // not found 955 // first = std::find( ++first, storageClasses.end(), key ); // found 956 // if ( first == storageClasses.end() ) return true; // not found again 957 // throw SemanticError( "duplicate function specifier in declaration of ", this ); 958 // } 920 959 921 960 // Local Variables: // -
src/Parser/ExpressionNode.cc
r79841be r6943a987 10 10 // Created On : Sat May 16 13:17:07 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Aug 10 11:07:38201613 // Update Count : 48612 // Last Modified On : Thu Aug 25 21:39:40 2016 13 // Update Count : 503 14 14 // 15 15 … … 32 32 using namespace std; 33 33 34 ExpressionNode::ExpressionNode( const ExpressionNode &other ) : ParseNode( other. name), extension( other.extension ) {}34 ExpressionNode::ExpressionNode( const ExpressionNode &other ) : ParseNode( other.get_name() ), extension( other.extension ) {} 35 35 36 36 //############################################################################## … … 57 57 static inline bool checkX( char c ) { return c == 'x' || c == 'X'; } 58 58 59 Expression *build_constantInteger( std::string & str ) {59 Expression *build_constantInteger( const std::string & str ) { 60 60 static const BasicType::Kind kind[2][3] = { 61 61 { BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt }, … … 120 120 } // if 121 121 122 return new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[Unsigned][size] ), str ) ); 122 Expression * ret = new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[Unsigned][size] ), str ) ); 123 delete &str; // created by lex 124 return ret; 123 125 } // build_constantInteger 124 126 125 Expression *build_constantFloat( std::string & str ) {127 Expression *build_constantFloat( const std::string & str ) { 126 128 static const BasicType::Kind kind[2][3] = { 127 129 { BasicType::Float, BasicType::Double, BasicType::LongDouble }, … … 150 152 } // if 151 153 152 return new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[complx][size] ), str ) ); 154 Expression * ret = new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[complx][size] ), str ) ); 155 delete &str; // created by lex 156 return ret; 153 157 } // build_constantFloat 154 158 155 Expression *build_constantChar( std::string & str ) { 156 return new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::Char ), str ) ); 159 Expression *build_constantChar( const std::string & str ) { 160 Expression * ret = new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::Char ), str ) ); 161 delete &str; // created by lex 162 return ret; 157 163 } // build_constantChar 158 164 159 ConstantExpr *build_constantStr( std::string & str ) {165 ConstantExpr *build_constantStr( const std::string & str ) { 160 166 // string should probably be a primitive type 161 167 ArrayType *at = new ArrayType( emptyQualifiers, new BasicType( emptyQualifiers, BasicType::Char ), … … 163 169 toString( str.size()+1-2 ) ) ), // +1 for '\0' and -2 for '"' 164 170 false, false ); 165 return new ConstantExpr( Constant( at, str ) ); 171 ConstantExpr * ret = new ConstantExpr( Constant( at, str ) ); 172 delete &str; // created by lex 173 return ret; 166 174 } // build_constantStr 167 175 168 //##############################################################################169 170 176 NameExpr * build_varref( const string *name, bool labelp ) { 171 returnnew NameExpr( *name, nullptr );172 } 173 174 //############################################################################## 177 NameExpr *expr = new NameExpr( *name, nullptr ); 178 delete name; 179 return expr; 180 } 175 181 176 182 static const char *OperName[] = { … … 178 184 "SizeOf", "AlignOf", "OffsetOf", "?+?", "?-?", "?*?", "?/?", "?%?", "||", "&&", 179 185 "?|?", "?&?", "?^?", "Cast", "?<<?", "?>>?", "?<?", "?>?", "?<=?", "?>=?", "?==?", "?!=?", 180 "?=?", "? *=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?",186 "?=?", "?@=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?", 181 187 "?[?]", "...", 182 188 // monadic … … 184 190 }; 185 191 186 //##############################################################################187 188 192 Expression *build_cast( DeclarationNode *decl_node, ExpressionNode *expr_node ) { 189 Type *targetType = decl_node->buildType();193 Type *targetType = maybeMoveBuildType( decl_node ); 190 194 if ( dynamic_cast< VoidType * >( targetType ) ) { 191 195 delete targetType; 192 return new CastExpr( maybe Build<Expression>(expr_node) );196 return new CastExpr( maybeMoveBuild< Expression >(expr_node) ); 193 197 } else { 194 return new CastExpr( maybe Build<Expression>(expr_node), targetType );198 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType ); 195 199 } // if 196 200 } 197 201 198 202 Expression *build_fieldSel( ExpressionNode *expr_node, NameExpr *member ) { 199 UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), maybe Build<Expression>(expr_node) );203 UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), maybeMoveBuild< Expression >(expr_node) ); 200 204 delete member; 201 205 return ret; … … 204 208 Expression *build_pfieldSel( ExpressionNode *expr_node, NameExpr *member ) { 205 209 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 206 deref->get_args().push_back( maybe Build<Expression>(expr_node) );210 deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) ); 207 211 UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref ); 208 212 delete member; … … 211 215 212 216 Expression *build_addressOf( ExpressionNode *expr_node ) { 213 return new AddressExpr( maybe Build<Expression>(expr_node) );217 return new AddressExpr( maybeMoveBuild< Expression >(expr_node) ); 214 218 } 215 219 Expression *build_sizeOfexpr( ExpressionNode *expr_node ) { 216 return new SizeofExpr( maybe Build<Expression>(expr_node) );220 return new SizeofExpr( maybeMoveBuild< Expression >(expr_node) ); 217 221 } 218 222 Expression *build_sizeOftype( DeclarationNode *decl_node ) { 219 return new SizeofExpr( decl_node->buildType() );223 return new SizeofExpr( maybeMoveBuildType( decl_node ) ); 220 224 } 221 225 Expression *build_alignOfexpr( ExpressionNode *expr_node ) { 222 return new AlignofExpr( maybe Build<Expression>(expr_node) );226 return new AlignofExpr( maybeMoveBuild< Expression >(expr_node) ); 223 227 } 224 228 Expression *build_alignOftype( DeclarationNode *decl_node ) { 225 return new AlignofExpr( decl_node->buildType() );229 return new AlignofExpr( maybeMoveBuildType( decl_node) ); 226 230 } 227 231 Expression *build_offsetOf( DeclarationNode *decl_node, NameExpr *member ) { 228 return new UntypedOffsetofExpr( decl_node->buildType(), member->get_name() ); 232 Expression* ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() ); 233 delete member; 234 return ret; 229 235 } 230 236 231 237 Expression *build_and_or( ExpressionNode *expr_node1, ExpressionNode *expr_node2, bool kind ) { 232 return new LogicalExpr( notZeroExpr( maybe Build<Expression>(expr_node1) ), notZeroExpr( maybeBuild<Expression>(expr_node2) ), kind );238 return new LogicalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), notZeroExpr( maybeMoveBuild< Expression >(expr_node2) ), kind ); 233 239 } 234 240 235 241 Expression *build_unary_val( OperKinds op, ExpressionNode *expr_node ) { 236 std::list< Expression *> args;237 args.push_back( maybe Build<Expression>(expr_node) );242 std::list< Expression * > args; 243 args.push_back( maybeMoveBuild< Expression >(expr_node) ); 238 244 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 239 245 } 240 246 Expression *build_unary_ptr( OperKinds op, ExpressionNode *expr_node ) { 241 std::list< Expression *> args;242 args.push_back( new AddressExpr( maybe Build<Expression>(expr_node) ) );247 std::list< Expression * > args; 248 args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node) ) ); 243 249 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 244 250 } 245 251 Expression *build_binary_val( OperKinds op, ExpressionNode *expr_node1, ExpressionNode *expr_node2 ) { 246 std::list< Expression *> args;247 args.push_back( maybe Build<Expression>(expr_node1) );248 args.push_back( maybe Build<Expression>(expr_node2) );252 std::list< Expression * > args; 253 args.push_back( maybeMoveBuild< Expression >(expr_node1) ); 254 args.push_back( maybeMoveBuild< Expression >(expr_node2) ); 249 255 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 250 256 } 251 257 Expression *build_binary_ptr( OperKinds op, ExpressionNode *expr_node1, ExpressionNode *expr_node2 ) { 252 std::list< Expression *> args;253 args.push_back( new AddressExpr( maybe Build<Expression>(expr_node1) ) );254 args.push_back( maybe Build<Expression>(expr_node2) );258 std::list< Expression * > args; 259 args.push_back( new AddressExpr( maybeMoveBuild< Expression >(expr_node1) ) ); 260 args.push_back( maybeMoveBuild< Expression >(expr_node2) ); 255 261 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 256 262 } 257 263 258 264 Expression *build_cond( ExpressionNode *expr_node1, ExpressionNode *expr_node2, ExpressionNode *expr_node3 ) { 259 return new ConditionalExpr( notZeroExpr( maybe Build<Expression>(expr_node1) ), maybeBuild<Expression>(expr_node2), maybeBuild<Expression>(expr_node3) );265 return new ConditionalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), maybeMoveBuild< Expression >(expr_node2), maybeMoveBuild< Expression >(expr_node3) ); 260 266 } 261 267 262 268 Expression *build_comma( ExpressionNode *expr_node1, ExpressionNode *expr_node2 ) { 263 return new CommaExpr( maybe Build<Expression>(expr_node1), maybeBuild<Expression>(expr_node2) );269 return new CommaExpr( maybeMoveBuild< Expression >(expr_node1), maybeMoveBuild< Expression >(expr_node2) ); 264 270 } 265 271 266 272 Expression *build_attrexpr( NameExpr *var, ExpressionNode * expr_node ) { 267 return new AttrExpr( var, maybe Build<Expression>(expr_node) );273 return new AttrExpr( var, maybeMoveBuild< Expression >(expr_node) ); 268 274 } 269 275 Expression *build_attrtype( NameExpr *var, DeclarationNode * decl_node ) { 270 return new AttrExpr( var, decl_node->buildType() );276 return new AttrExpr( var, maybeMoveBuildType( decl_node ) ); 271 277 } 272 278 273 279 Expression *build_tuple( ExpressionNode * expr_node ) { 274 280 TupleExpr *ret = new TupleExpr(); 275 build List( expr_node, ret->get_exprs() );281 buildMoveList( expr_node, ret->get_exprs() ); 276 282 return ret; 277 283 } 278 284 279 285 Expression *build_func( ExpressionNode * function, ExpressionNode * expr_node ) { 280 std::list<Expression *> args; 281 282 buildList( expr_node, args ); 283 return new UntypedExpr( maybeBuild<Expression>(function), args, nullptr ); 286 std::list< Expression * > args; 287 buildMoveList( expr_node, args ); 288 return new UntypedExpr( maybeMoveBuild< Expression >(function), args, nullptr ); 284 289 } 285 290 286 291 Expression *build_range( ExpressionNode * low, ExpressionNode *high ) { 287 Expression *low_cexpr = maybeBuild<Expression>( low ); 288 Expression *high_cexpr = maybeBuild<Expression>( high ); 289 return new RangeExpr( low_cexpr, high_cexpr ); 290 } 291 292 //############################################################################## 293 294 Expression *build_asm( ExpressionNode *inout, ConstantExpr *constraint, ExpressionNode *operand ) { 295 return new AsmExpr( maybeBuild< Expression >( inout ), constraint, maybeBuild<Expression>(operand) ); 296 } 297 298 //############################################################################## 299 300 void LabelNode::print( std::ostream &os, int indent ) const {} 301 302 void LabelNode::printOneLine( std::ostream &os, int indent ) const {} 303 304 //############################################################################## 292 return new RangeExpr( maybeMoveBuild< Expression >( low ), maybeMoveBuild< Expression >( high ) ); 293 } 294 295 Expression *build_asmexpr( ExpressionNode *inout, ConstantExpr *constraint, ExpressionNode *operand ) { 296 return new AsmExpr( maybeMoveBuild< Expression >( inout ), constraint, maybeMoveBuild< Expression >(operand) ); 297 } 305 298 306 299 Expression *build_valexpr( StatementNode *s ) { 307 return new UntypedValofExpr( maybeBuild<Statement>(s), nullptr ); 308 } 309 310 //############################################################################## 311 312 // ForCtlExprNode::ForCtlExprNode( ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr ) throw ( SemanticError ) : condition( cond ), change( incr ) { 313 // if ( init_ == 0 ) 314 // init = 0; 315 // else { 316 // DeclarationNode *decl; 317 // ExpressionNode *exp; 318 319 // if (( decl = dynamic_cast<DeclarationNode *>(init_) ) != 0) 320 // init = new StatementNode( decl ); 321 // else if (( exp = dynamic_cast<ExpressionNode *>( init_)) != 0) 322 // init = new StatementNode( StatementNode::Exp, exp ); 323 // else 324 // throw SemanticError("Error in for control expression"); 325 // } 326 // } 327 328 // ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other ) 329 // : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) { 330 // } 331 332 // ForCtlExprNode::~ForCtlExprNode() { 333 // delete init; 334 // delete condition; 335 // delete change; 336 // } 337 338 // Expression *ForCtlExprNode::build() const { 339 // // this shouldn't be used! 340 // assert( false ); 341 // return 0; 342 // } 343 344 // void ForCtlExprNode::print( std::ostream &os, int indent ) const{ 345 // os << string( indent,' ' ) << "For Control Expression -- :" << endl; 346 347 // os << string( indent + 2, ' ' ) << "initialization:" << endl; 348 // if ( init != 0 ) 349 // init->printList( os, indent + 4 ); 350 351 // os << string( indent + 2, ' ' ) << "condition: " << endl; 352 // if ( condition != 0 ) 353 // condition->print( os, indent + 4 ); 354 // os << string( indent + 2, ' ' ) << "increment: " << endl; 355 // if ( change != 0 ) 356 // change->print( os, indent + 4 ); 357 // } 358 359 // void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const { 360 // assert( false ); 361 // } 362 363 //############################################################################## 364 300 return new UntypedValofExpr( maybeMoveBuild< Statement >(s), nullptr ); 301 } 365 302 Expression *build_typevalue( DeclarationNode *decl ) { 366 return new TypeExpr( decl->buildType() ); 367 } 368 369 //############################################################################## 303 return new TypeExpr( maybeMoveBuildType( decl ) ); 304 } 370 305 371 306 Expression *build_compoundLiteral( DeclarationNode *decl_node, InitializerNode *kids ) { 372 Declaration * newDecl = maybeBuild< Declaration>(decl_node); // compound literal type307 Declaration * newDecl = maybeBuild< Declaration >(decl_node); // compound literal type 373 308 if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type 374 return new CompoundLiteralExpr( newDeclWithType->get_type(), maybe Build<Initializer>(kids) );309 return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild< Initializer >(kids) ); 375 310 // these types do not have associated type information 376 311 } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl ) ) { 377 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybe Build<Initializer>(kids) );312 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 378 313 } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl ) ) { 379 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybe Build<Initializer>(kids) );314 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 380 315 } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl ) ) { 381 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybe Build<Initializer>(kids) );316 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 382 317 } else { 383 318 assert( false ); -
src/Parser/InitializerNode.cc
r79841be r6943a987 10 10 // Created On : Sat May 16 13:20:24 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jul 4 15:37:15201613 // Update Count : 1512 // Last Modified On : Mon Aug 15 18:27:02 2016 13 // Update Count : 20 14 14 // 15 15 … … 25 25 : expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ), maybeConstructed( true ) { 26 26 if ( aggrp ) 27 kids = dynamic_cast< InitializerNode * >( get_link() );27 kids = dynamic_cast< InitializerNode * >( get_next() ); 28 28 29 29 if ( kids != 0 ) 30 set_l ink( 0 );30 set_last( 0 ); 31 31 } 32 32 … … 34 34 : expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ), maybeConstructed( true ) { 35 35 if ( init != 0 ) 36 set_l ink(init);36 set_last( init ); 37 37 38 38 if ( aggrp ) 39 kids = dynamic_cast< InitializerNode * >( get_link() );39 kids = dynamic_cast< InitializerNode * >( get_next() ); 40 40 41 41 if ( kids != 0 ) … … 45 45 InitializerNode::~InitializerNode() { 46 46 delete expr; 47 delete designator; 48 delete kids; 47 49 } 48 50 … … 58 60 while ( curdes != 0) { 59 61 curdes->printOneLine(os); 60 curdes = (ExpressionNode *)(curdes->get_ link());62 curdes = (ExpressionNode *)(curdes->get_next()); 61 63 if ( curdes ) os << ", "; 62 64 } // while … … 72 74 73 75 InitializerNode *moreInit; 74 if ( get_ link() != 0 && ((moreInit = dynamic_cast< InitializerNode * >( get_link() ) ) != 0) )76 if ( get_next() != 0 && ((moreInit = dynamic_cast< InitializerNode * >( get_next() ) ) != 0) ) 75 77 moreInit->printOneLine( os ); 76 78 } … … 82 84 //assert( next_init() != 0 ); 83 85 84 std::list< Initializer * > initlist;85 buildList< Initializer, InitializerNode>( next_init(), initlist );86 std::list< Initializer * > initlist; 87 buildList< Initializer, InitializerNode >( next_init(), initlist ); 86 88 87 std::list< Expression * > designlist;89 std::list< Expression * > designlist; 88 90 89 91 if ( designator != 0 ) { 90 buildList< Expression, ExpressionNode>( designator, designlist );92 buildList< Expression, ExpressionNode >( designator, designlist ); 91 93 } // if 92 94 93 95 return new ListInit( initlist, designlist, maybeConstructed ); 94 96 } else { 95 std::list< Expression * > designators;97 std::list< Expression * > designators; 96 98 97 99 if ( designator != 0 ) 98 buildList< Expression, ExpressionNode>( designator, designators );100 buildList< Expression, ExpressionNode >( designator, designators ); 99 101 100 102 if ( get_expression() != 0) 101 return new SingleInit( maybeBuild< Expression>( get_expression() ), designators, maybeConstructed );103 return new SingleInit( maybeBuild< Expression >( get_expression() ), designators, maybeConstructed ); 102 104 } // if 103 105 -
src/Parser/LinkageSpec.cc
r79841be r6943a987 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // LinkageSpec.cc -- 8 // 7 // LinkageSpec.cc -- 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:22:09 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Wed Aug 19 15:53:05 201513 // Update Count : 514 // 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Aug 21 12:32:53 2016 13 // Update Count : 17 14 // 15 15 16 16 #include <string> … … 20 20 #include "Common/SemanticError.h" 21 21 22 LinkageSpec:: Type LinkageSpec::fromString( const std::string &stringSpec ) {23 if ( s tringSpec == "\"Cforall\"" ) {22 LinkageSpec::Spec LinkageSpec::fromString( const std::string &spec ) { 23 if ( spec == "\"Cforall\"" ) { 24 24 return Cforall; 25 } else if ( s tringSpec == "\"C\"" ) {25 } else if ( spec == "\"C\"" ) { 26 26 return C; 27 27 } else { 28 throw SemanticError( "Invalid linkage specifier " + stringSpec ); 29 } 28 throw SemanticError( "Invalid linkage specifier " + spec ); 29 } // if 30 delete &spec; // allocated by lexer 30 31 } 31 32 32 std::string LinkageSpec::toString( LinkageSpec::Type linkage ) { 33 switch ( linkage ) { 34 case Intrinsic: 35 return "intrinsic"; 36 case Cforall: 37 return "Cforall"; 38 case C: 39 return "C"; 40 case AutoGen: 41 return "automatically generated"; 42 case Compiler: 43 return "compiler built-in"; 44 } 45 assert( false ); 46 return ""; 33 std::string LinkageSpec::toString( LinkageSpec::Spec linkage ) { 34 assert( linkage >= 0 && linkage < LinkageSpec::NoOfSpecs ); 35 static const char *linkageKinds[LinkageSpec::NoOfSpecs] = { 36 "intrinsic", "Cforall", "C", "automatically generated", "compiler built-in", 37 }; 38 return linkageKinds[linkage]; 47 39 } 48 40 49 bool LinkageSpec::isDecoratable( Type t ) { 50 switch ( t ) { 51 case Intrinsic: 52 case Cforall: 53 case AutoGen: 54 return true; 55 case C: 56 case Compiler: 57 return false; 58 } 59 assert( false ); 60 return false; 41 bool LinkageSpec::isDecoratable( Spec spec ) { 42 assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs ); 43 static bool decoratable[LinkageSpec::NoOfSpecs] = { 44 // Intrinsic, Cforall, C, AutoGen, Compiler 45 true, true, false, true, false, 46 }; 47 return decoratable[spec]; 61 48 } 62 49 63 bool LinkageSpec::isGeneratable( Type t ) { 64 switch ( t ) { 65 case Intrinsic: 66 case Cforall: 67 case AutoGen: 68 case C: 69 return true; 70 case Compiler: 71 return false; 72 } 73 assert( false ); 74 return false; 50 bool LinkageSpec::isGeneratable( Spec spec ) { 51 assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs ); 52 static bool generatable[LinkageSpec::NoOfSpecs] = { 53 // Intrinsic, Cforall, C, AutoGen, Compiler 54 true, true, true, true, false, 55 }; 56 return generatable[spec]; 75 57 } 76 58 77 bool LinkageSpec::isOverloadable( Type t ) { 78 return isDecoratable( t ); 59 bool LinkageSpec::isOverridable( Spec spec ) { 60 assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs ); 61 static bool overridable[LinkageSpec::NoOfSpecs] = { 62 // Intrinsic, Cforall, C, AutoGen, Compiler 63 true, false, false, true, false, 64 }; 65 return overridable[spec]; 79 66 } 80 67 81 82 bool LinkageSpec::isOverridable( Type t ) { 83 switch ( t ) { 84 case Intrinsic: 85 case AutoGen: 86 return true; 87 case Cforall: 88 case C: 89 case Compiler: 90 return false; 91 } 92 assert( false ); 93 return false; 94 } 95 96 bool LinkageSpec::isBuiltin( Type t ) { 97 switch ( t ) { 98 case Cforall: 99 case AutoGen: 100 case C: 101 return false; 102 case Intrinsic: 103 case Compiler: 104 return true; 105 } 106 assert( false ); 107 return false; 68 bool LinkageSpec::isBuiltin( Spec spec ) { 69 assert( spec >= 0 && spec < LinkageSpec::NoOfSpecs ); 70 static bool builtin[LinkageSpec::NoOfSpecs] = { 71 // Intrinsic, Cforall, C, AutoGen, Compiler 72 true, false, false, false, true, 73 }; 74 return builtin[spec]; 108 75 } 109 76 -
src/Parser/LinkageSpec.h
r79841be r6943a987 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:24:28 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Tue Aug 18 14:11:55 201513 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 20 19:22:23 2016 13 // Update Count : 8 14 14 // 15 15 … … 20 20 21 21 struct LinkageSpec { 22 enum Type{22 enum Spec { 23 23 Intrinsic, // C built-in defined in prelude 24 24 Cforall, // ordinary 25 25 C, // not overloadable, not mangled 26 26 AutoGen, // built by translator (struct assignment) 27 Compiler // gcc internal 27 Compiler, // gcc internal 28 NoOfSpecs 28 29 }; 29 30 30 static TypefromString( const std::string & );31 static std::string toString( Type);31 static Spec fromString( const std::string & ); 32 static std::string toString( Spec ); 32 33 33 static bool isDecoratable( Type ); 34 static bool isGeneratable( Type ); 35 static bool isOverloadable( Type ); 36 static bool isOverridable( Type ); 37 static bool isBuiltin( Type ); 34 static bool isDecoratable( Spec ); 35 static bool isGeneratable( Spec ); 36 static bool isOverridable( Spec ); 37 static bool isBuiltin( Spec ); 38 38 }; 39 39 -
src/Parser/ParseNode.cc
r79841be r6943a987 10 10 // Created On : Sat May 16 13:26:29 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Aug 7 23:32:47201613 // Update Count : 9412 // Last Modified On : Wed Aug 17 23:14:16 2016 13 // Update Count : 126 14 14 // 15 15 … … 17 17 using namespace std; 18 18 19 // Builder20 19 int ParseNode::indent_by = 4; 21 22 ParseNode::ParseNode() : next( 0 ) {};23 ParseNode::ParseNode( const string *name ) : name( *name ), next( 0 ) { delete name; }24 ParseNode::ParseNode( const string &name ) : name( name ), next( 0 ) { }25 26 ParseNode::~ParseNode() {27 delete next;28 };29 30 ParseNode *ParseNode::get_last() {31 ParseNode *current = this;32 33 while ( current->get_link() != 0 )34 current = current->get_link();35 36 return current;37 }38 39 ParseNode *ParseNode::set_link( ParseNode *next_ ) {40 if ( next_ != 0 ) get_last()->next = next_;41 return this;42 }43 44 void ParseNode::print( std::ostream &os, int indent ) const {}45 46 47 void ParseNode::printList( std::ostream &os, int indent ) const {48 print( os, indent );49 50 if ( next ) {51 next->printList( os, indent );52 } // if53 }54 55 ParseNode &ParseNode::operator,( ParseNode &p ) {56 set_link( &p );57 58 return *this;59 }60 61 ParseNode *mkList( ParseNode &pn ) {62 // it just relies on `operator,' to take care of the "arguments" and provides a nice interface to an awful-looking63 // address-of, rendering, for example (StatementNode *)(&(*$5 + *$7)) into (StatementNode *)mkList(($5, $7))64 // (although "nice" is probably not the word)65 return &pn;66 }67 20 68 21 // Local Variables: // -
src/Parser/ParseNode.h
r79841be r6943a987 10 10 // Created On : Sat May 16 13:28:16 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 11 12:24:11 201613 // Update Count : 44312 // Last Modified On : Sun Aug 28 21:14:51 2016 13 // Update Count : 575 14 14 // 15 15 … … 22 22 #include <memory> 23 23 24 #include "Common/utility.h"25 24 #include "Parser/LinkageSpec.h" 26 25 #include "SynTree/Type.h" 27 26 #include "SynTree/Expression.h" 28 27 #include "SynTree/Statement.h" 29 //#include "SynTree/Declaration.h" 28 #include "SynTree/Label.h" 29 #include "Common/utility.h" 30 30 #include "Common/UniqueName.h" 31 #include "SynTree/Label.h"32 31 33 32 class StatementNode; … … 37 36 class InitializerNode; 38 37 39 // Builder 38 //############################################################################## 39 40 40 class ParseNode { 41 41 public: 42 ParseNode(); 43 ParseNode( const std::string * ); 44 ParseNode( const std::string & ); // for copy constructing subclasses 45 virtual ~ParseNode(); 46 47 ParseNode *get_link() const { return next; } 48 ParseNode *get_last(); 49 ParseNode *set_link( ParseNode * ); 50 void set_next( ParseNode *newlink ) { next = newlink; } 51 52 virtual ParseNode *clone() const { return 0; }; 42 ParseNode() {}; 43 ParseNode( const std::string *name ) : name( *name ) { assert( false ); delete name; } 44 ParseNode( const std::string &name ) : name( name ) { assert( false ); } 45 virtual ~ParseNode() { delete next; }; 46 virtual ParseNode *clone() const = 0; 47 48 ParseNode *get_next() const { return next; } 49 ParseNode *set_next( ParseNode *newlink ) { next = newlink; return this; } 50 ParseNode *get_last() { 51 ParseNode *current; 52 for ( current = this; current->get_next() != 0; current = current->get_next() ); 53 return current; 54 } 55 ParseNode *set_last( ParseNode *newlast ) { 56 if ( newlast != 0 ) get_last()->set_next( newlast ); 57 return this; 58 } 53 59 54 60 const std::string &get_name() const { return name; } 55 61 void set_name( const std::string &newValue ) { name = newValue; } 56 62 57 virtual void print( std::ostream &os, int indent = 0 ) const; 58 virtual void printList( std::ostream &os, int indent = 0 ) const; 59 60 ParseNode &operator,( ParseNode & ); 61 protected: 63 virtual void print( std::ostream &os, int indent = 0 ) const {} 64 virtual void printList( std::ostream &os, int indent = 0 ) const {} 65 private: 66 static int indent_by; 67 68 ParseNode *next = nullptr; 62 69 std::string name; 63 static int indent_by; 64 ParseNode *next; 65 }; 66 67 ParseNode *mkList( ParseNode & ); 70 }; // ParseNode 68 71 69 72 //############################################################################## … … 74 77 InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode *des = 0 ); 75 78 ~InitializerNode(); 79 virtual InitializerNode *clone() const { assert( false ); return nullptr; } 76 80 77 81 ExpressionNode *get_expression() const { return expr; } … … 92 96 ExpressionNode *expr; 93 97 bool aggregate; 94 ExpressionNode *designator; 98 ExpressionNode *designator; // may be list 95 99 InitializerNode *kids; 96 100 bool maybeConstructed; 97 }; 98 99 //############################################################################## 100 101 class ExpressionNode : public ParseNode {101 }; // InitializerNode 102 103 //############################################################################## 104 105 class ExpressionNode final : public ParseNode { 102 106 public: 103 107 ExpressionNode( Expression * expr = nullptr ) : expr( expr ) {} … … 105 109 ExpressionNode( const ExpressionNode &other ); 106 110 virtual ~ExpressionNode() {} 107 108 virtual ExpressionNode *clone() const { return 0; } 111 virtual ExpressionNode *clone() const { return expr ? new ExpressionNode( expr->clone() ) : nullptr; } 109 112 110 113 bool get_extension() const { return extension; } 111 114 ExpressionNode *set_extension( bool exten ) { extension = exten; return this; } 112 115 113 virtual void print( std::ostream &os, int indent = 0 ) const {} 114 virtual void printOneLine( std::ostream &os, int indent = 0 ) const {} 115 116 virtual Expression *build() const { return expr; } 116 void print( std::ostream &os, int indent = 0 ) const {} 117 void printOneLine( std::ostream &os, int indent = 0 ) const {} 118 119 template<typename T> 120 bool isExpressionType() const { 121 return nullptr != dynamic_cast<T>(expr.get()); 122 } 123 124 Expression *build() const { return const_cast<ExpressionNode*>(this)->expr.release(); } 117 125 private: 118 126 bool extension = false; 119 Expression *expr;120 }; 127 std::unique_ptr<Expression> expr; 128 }; // ExpressionNode 121 129 122 130 template< typename T > 123 struct maybeBuild_t< Expression, T> {131 struct maybeBuild_t< Expression, T > { 124 132 static inline Expression * doit( const T *orig ) { 125 133 if ( orig ) { … … 128 136 return p; 129 137 } else { 130 return 0;138 return nullptr; 131 139 } // if 132 140 } 133 141 }; 134 135 //##############################################################################136 137 Expression *build_constantInteger( std::string &str );138 Expression *build_constantFloat( std::string &str );139 Expression *build_constantChar( std::string &str );140 ConstantExpr *build_constantStr( std::string &str );141 142 //##############################################################################143 144 NameExpr *build_varref( const std::string *name, bool labelp = false );145 146 //##############################################################################147 148 Expression *build_typevalue( DeclarationNode *decl );149 150 //##############################################################################151 142 152 143 enum class OperKinds { … … 154 145 SizeOf, AlignOf, OffsetOf, Plus, Minus, Mul, Div, Mod, Or, And, 155 146 BitOr, BitAnd, Xor, Cast, LShift, RShift, LThan, GThan, LEThan, GEThan, Eq, Neq, 156 Assign, MulAssn, DivAssn, ModAssn, PlusAssn, MinusAssn, LSAssn, RSAssn, AndAssn, ERAssn, OrAssn,147 Assign, AtAssn, MulAssn, DivAssn, ModAssn, PlusAssn, MinusAssn, LSAssn, RSAssn, AndAssn, ERAssn, OrAssn, 157 148 Index, Range, 158 149 // monadic 159 150 UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress, 160 151 Ctor, Dtor, 152 }; // OperKinds 153 154 struct LabelNode { 155 std::list< Label > labels; 161 156 }; 157 158 Expression *build_constantInteger( const std::string &str ); 159 Expression *build_constantFloat( const std::string &str ); 160 Expression *build_constantChar( const std::string &str ); 161 ConstantExpr *build_constantStr( const std::string &str ); 162 163 NameExpr *build_varref( const std::string *name, bool labelp = false ); 164 Expression *build_typevalue( DeclarationNode *decl ); 162 165 163 166 Expression *build_cast( DeclarationNode * decl_node, ExpressionNode *expr_node ); … … 183 186 Expression *build_func( ExpressionNode * function, ExpressionNode * expr_node ); 184 187 Expression *build_range( ExpressionNode * low, ExpressionNode *high ); 185 186 //############################################################################## 187 188 Expression *build_asm( ExpressionNode *inout, ConstantExpr *constraint, ExpressionNode *operand ); 189 190 //############################################################################## 191 192 class LabelNode : public ExpressionNode { 193 public: 194 virtual Expression *build() const { return NULL; } 195 virtual LabelNode *clone() const { assert( false ); return new LabelNode( *this ); } 196 197 virtual void print( std::ostream &os, int indent = 0) const; 198 virtual void printOneLine( std::ostream &os, int indent = 0) const; 199 200 const std::list< Label > &get_labels() const { return labels; }; 201 void append_label( std::string * label ) { labels.push_back( *label ); delete label; } 202 private: 203 std::list< Label > labels; 204 }; 205 206 //############################################################################## 207 188 Expression *build_asmexpr( ExpressionNode *inout, ConstantExpr *constraint, ExpressionNode *operand ); 208 189 Expression *build_valexpr( StatementNode *s ); 209 210 //##############################################################################211 212 190 Expression *build_compoundLiteral( DeclarationNode *decl_node, InitializerNode *kids ); 213 191 … … 218 196 class DeclarationNode : public ParseNode { 219 197 public: 220 enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic };198 enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic, NoOfQualifier }; 221 199 enum StorageClass { Extern, Static, Auto, Register, Inline, Fortran, Noreturn, Threadlocal, NoStorageClass, }; 222 200 enum BasicType { Char, Int, Float, Double, Void, Bool, Complex, Imaginary }; … … 226 204 enum BuiltinType { Valist }; 227 205 206 static const char *qualifierName[]; 228 207 static const char *storageName[]; 229 static const char *qualifierName[];230 208 static const char *basicTypeName[]; 231 209 static const char *modifierName[]; … … 236 214 static DeclarationNode *newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param, StatementNode *body, bool newStyle = false ); 237 215 static DeclarationNode *newQualifier( Qualifier ); 216 static DeclarationNode *newForall( DeclarationNode *); 238 217 static DeclarationNode *newStorageClass( StorageClass ); 239 218 static DeclarationNode *newBasicType( BasicType ); 240 219 static DeclarationNode *newModifier( Modifier ); 241 static DeclarationNode *new Forall( DeclarationNode *);220 static DeclarationNode *newBuiltinType( BuiltinType ); 242 221 static DeclarationNode *newFromTypedef( std::string *); 243 222 static DeclarationNode *newAggregate( Aggregate kind, const std::string *name, ExpressionNode *actuals, DeclarationNode *fields, bool body ); … … 258 237 static DeclarationNode *newAttr( std::string *, ExpressionNode *expr ); 259 238 static DeclarationNode *newAttr( std::string *, DeclarationNode *type ); 260 static DeclarationNode *newBuiltinType( BuiltinType ); 239 240 DeclarationNode(); 241 ~DeclarationNode(); 242 DeclarationNode *clone() const; 261 243 262 244 DeclarationNode *addQualifiers( DeclarationNode *); 245 void checkQualifiers( const TypeData *, const TypeData * ); 263 246 DeclarationNode *copyStorageClasses( DeclarationNode *); 264 247 DeclarationNode *addType( DeclarationNode *); … … 275 258 DeclarationNode *addNewArray( DeclarationNode *array ); 276 259 DeclarationNode *addParamList( DeclarationNode *list ); 277 DeclarationNode *addIdList( DeclarationNode *list ); 260 DeclarationNode *addIdList( DeclarationNode *list ); // old-style functions 278 261 DeclarationNode *addInitializer( InitializerNode *init ); 279 262 … … 284 267 DeclarationNode *cloneBaseType( DeclarationNode *newdecl ); 285 268 286 DeclarationNode *appendList( DeclarationNode * ); 287 288 DeclarationNode *clone() const; 269 DeclarationNode *appendList( DeclarationNode *node ) { 270 return (DeclarationNode *)set_last( node ); 271 } 272 289 273 void print( std::ostream &os, int indent = 0 ) const; 290 274 void printList( std::ostream &os, int indent = 0 ) const; … … 295 279 bool get_hasEllipsis() const; 296 280 const std::string &get_name() const { return name; } 297 LinkageSpec:: Typeget_linkage() const { return linkage; }281 LinkageSpec::Spec get_linkage() const { return linkage; } 298 282 DeclarationNode *extractAggregate() const; 299 ExpressionNode *get_enumeratorValue() const { return enumeratorValue; } 283 bool has_enumeratorValue() const { return (bool)enumeratorValue; } 284 ExpressionNode *consume_enumeratorValue() const { return const_cast<DeclarationNode*>(this)->enumeratorValue.release(); } 300 285 301 286 bool get_extension() const { return extension; } 302 287 DeclarationNode *set_extension( bool exten ) { extension = exten; return this; } 303 304 DeclarationNode(); 305 ~DeclarationNode(); 306 private: 307 StorageClass buildStorageClass() const; 308 bool buildFuncSpecifier( StorageClass key ) const; 288 public: 289 // StorageClass buildStorageClass() const; 290 // bool buildFuncSpecifier( StorageClass key ) const; 309 291 310 292 TypeData *type; 311 293 std::string name; 312 std::list< StorageClass > storageClasses; 294 // std::list< StorageClass > storageClasses; 295 StorageClass storageClass; 296 bool isInline, isNoreturn; 313 297 std::list< std::string > attributes; 314 298 ExpressionNode *bitfieldWidth; 315 ExpressionNode *enumeratorValue;299 std::unique_ptr<ExpressionNode> enumeratorValue; 316 300 InitializerNode *initializer; 317 301 bool hasEllipsis; 318 LinkageSpec:: Typelinkage;302 LinkageSpec::Spec linkage; 319 303 bool extension = false; 304 std::string error; 320 305 321 306 static UniqueName anonymous; … … 323 308 324 309 Type *buildType( TypeData *type ); 325 326 //############################################################################## 327 328 class StatementNode : public ParseNode { 329 public: 330 enum Type { Exp, If, Switch, Case, Default, Choose, Fallthru, 331 While, Do, For, 332 Goto, Continue, Break, Return, Throw, 333 Try, Catch, Finally, Asm, 334 Decl 335 }; 336 337 StatementNode(); 338 StatementNode( const std::string *name ); 339 StatementNode( Type t, ExpressionNode *control = 0, StatementNode *block = 0 ); 340 StatementNode( Type t, std::string *target ); 310 //Type::Qualifiers buildQualifiers( const TypeData::Qualifiers & qualifiers ); 311 312 static inline Type * maybeMoveBuildType( const DeclarationNode *orig ) { 313 Type* ret = orig ? orig->buildType() : nullptr; 314 delete orig; 315 return ret; 316 } 317 318 //############################################################################## 319 320 class StatementNode final : public ParseNode { 321 public: 322 StatementNode() { stmt = nullptr; } 323 StatementNode( Statement *stmt ) : stmt( stmt ) {} 341 324 StatementNode( DeclarationNode *decl ); 342 343 ~StatementNode(); 344 345 static StatementNode *newCatchStmt( DeclarationNode *d = 0, StatementNode *s = 0, bool catchRestP = false ); 346 347 StatementNode *set_block( StatementNode *b ) { block = b; return this; } 348 StatementNode *get_block() const { return block; } 349 350 void set_control( ExpressionNode *c ) { control = c; } 351 ExpressionNode *get_control() const { return control; } 352 353 StatementNode::Type get_type() const { return type; } 354 355 virtual StatementNode *add_label( const std::string * ); 356 virtual std::list<std::string> get_labels() const { return labels; } 357 358 void addDeclaration( DeclarationNode *newDecl ) { decl = newDecl; } 359 void setCatchRest( bool newVal ) { isCatchRest = newVal; } 360 361 std::string get_target() const; 362 363 // StatementNode *add_controlexp( ExpressionNode * ); 364 StatementNode *append_block( StatementNode * ); 325 virtual ~StatementNode() {} 326 327 virtual StatementNode *clone() const final { assert( false ); return nullptr; } 328 Statement *build() const { return const_cast<StatementNode*>(this)->stmt.release(); } 329 330 virtual StatementNode *add_label( const std::string * name ) { 331 stmt->get_labels().emplace_back( *name ); 332 delete name; 333 return this; 334 } 335 365 336 virtual StatementNode *append_last_case( StatementNode * ); 366 367 void print( std::ostream &os, int indent = 0) const;368 virtual StatementNode *clone() const;369 virtual Statement *build() const;370 private:371 static const char *StType[];372 Type type;373 ExpressionNode *control;374 StatementNode *block;375 std::list<std::string> labels;376 std::string *target; // target label for jump statements377 DeclarationNode *decl;378 bool isCatchRest;379 }; // StatementNode380 381 class StatementNode2 : public StatementNode {382 public:383 StatementNode2() {}384 StatementNode2( Statement *stmt ) : stmt( stmt ) {}385 virtual ~StatementNode2() {}386 387 virtual StatementNode2 *clone() const { assert( false ); return nullptr; }388 virtual Statement *build() const { return stmt; }389 390 virtual StatementNode2 *add_label( const std::string * name ) {391 stmt->get_labels().emplace_back( *name );392 return this;393 }394 virtual StatementNode *append_last_case( StatementNode * );395 virtual std::list<std::string> get_labels() const { assert( false ); return StatementNode::get_labels(); }396 337 397 338 virtual void print( std::ostream &os, int indent = 0 ) {} 398 339 virtual void printList( std::ostream &os, int indent = 0 ) {} 399 340 private: 400 Statement *stmt;341 std::unique_ptr<Statement> stmt; 401 342 }; // StatementNode 343 344 Statement *build_expr( ExpressionNode *ctl ); 402 345 403 346 struct ForCtl { 404 347 ForCtl( ExpressionNode *expr, ExpressionNode *condition, ExpressionNode *change ) : 405 init( new StatementNode( StatementNode::Exp, expr) ), condition( condition ), change( change ) {}348 init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {} 406 349 ForCtl( DeclarationNode *decl, ExpressionNode *condition, ExpressionNode *change ) : 407 350 init( new StatementNode( decl ) ), condition( condition ), change( change ) {} … … 412 355 }; 413 356 414 Statement *build_expr( ExpressionNode *ctl );415 357 Statement *build_if( ExpressionNode *ctl, StatementNode *then_stmt, StatementNode *else_stmt ); 416 358 Statement *build_switch( ExpressionNode *ctl, StatementNode *stmt ); … … 419 361 Statement *build_while( ExpressionNode *ctl, StatementNode *stmt, bool kind = false ); 420 362 Statement *build_for( ForCtl *forctl, StatementNode *stmt ); 421 Statement *build_branch( std::string identifier, BranchStmt::Type kind ); 363 Statement *build_branch( BranchStmt::Type kind ); 364 Statement *build_branch( std::string *identifier, BranchStmt::Type kind ); 422 365 Statement *build_computedgoto( ExpressionNode *ctl ); 423 366 Statement *build_return( ExpressionNode *ctl ); 424 367 Statement *build_throw( ExpressionNode *ctl ); 425 426 //############################################################################## 427 428 class CompoundStmtNode : public StatementNode { 429 public: 430 CompoundStmtNode(); 431 CompoundStmtNode( const std::string * ); 432 CompoundStmtNode( StatementNode * ); 433 ~CompoundStmtNode(); 434 435 void add_statement( StatementNode * ); 436 437 void print( std::ostream &os, int indent = 0 ) const; 438 virtual Statement *build() const; 439 private: 440 StatementNode *first, *last; 441 }; 442 443 //############################################################################## 444 445 class AsmStmtNode : public StatementNode { 446 public: 447 AsmStmtNode( Type, bool voltile, ConstantExpr *instruction, ExpressionNode *output = 0, ExpressionNode *input = 0, ExpressionNode *clobber = 0, LabelNode *gotolabels = 0 ); 448 ~AsmStmtNode(); 449 450 void print( std::ostream &os, int indent = 0 ) const; 451 Statement *build() const; 452 private: 453 bool voltile; 454 ConstantExpr *instruction; 455 ExpressionNode *output, *input; 456 ExpressionNode *clobber; 457 std::list< Label > gotolabels; 458 }; 368 Statement *build_try( StatementNode *try_stmt, StatementNode *catch_stmt, StatementNode *finally_stmt ); 369 Statement *build_catch( DeclarationNode *decl, StatementNode *stmt, bool catchAny = false ); 370 Statement *build_finally( StatementNode *stmt ); 371 Statement *build_compound( StatementNode *first ); 372 Statement *build_asmstmt( bool voltile, ConstantExpr *instruction, ExpressionNode *output = 0, ExpressionNode *input = 0, ExpressionNode *clobber = 0, LabelNode *gotolabels = 0 ); 459 373 460 374 //############################################################################## … … 463 377 void buildList( const NodeType *firstNode, std::list< SynTreeType * > &outputList ) { 464 378 SemanticError errors; 465 std::back_insert_iterator< std::list< SynTreeType * > > out( outputList );379 std::back_insert_iterator< std::list< SynTreeType * > > out( outputList ); 466 380 const NodeType *cur = firstNode; 467 381 468 382 while ( cur ) { 469 383 try { 470 // SynTreeType *result = dynamic_cast< SynTreeType * >( maybeBuild<typename std::result_of<decltype(&NodeType::build)(NodeType)>::type>( cur ) );471 SynTreeType *result = dynamic_cast< SynTreeType * >( maybeBuild<typename std::pointer_traits<decltype(cur->build())>::element_type>( cur ) );384 // SynTreeType *result = dynamic_cast< SynTreeType * >( maybeBuild< typename std::result_of< decltype(&NodeType::build)(NodeType)>::type >( cur ) ); 385 SynTreeType *result = dynamic_cast< SynTreeType * >( maybeBuild< typename std::pointer_traits< decltype(cur->build())>::element_type >( cur ) ); 472 386 if ( result ) { 473 387 *out++ = result; … … 477 391 errors.append( e ); 478 392 } // try 479 cur = dynamic_cast< NodeType * >( cur->get_link() );393 cur = dynamic_cast< NodeType * >( cur->get_next() ); 480 394 } // while 481 395 if ( ! errors.isEmpty() ) { … … 486 400 // in DeclarationNode.cc 487 401 void buildList( const DeclarationNode *firstNode, std::list< Declaration * > &outputList ); 488 void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType * > &outputList );402 void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType * > &outputList ); 489 403 void buildTypeList( const DeclarationNode *firstNode, std::list< Type * > &outputList ); 404 405 template< typename SynTreeType, typename NodeType > 406 void buildMoveList( const NodeType *firstNode, std::list< SynTreeType * > &outputList ) { 407 buildList(firstNode, outputList); 408 delete firstNode; 409 } 410 490 411 491 412 #endif // PARSENODE_H -
src/Parser/StatementNode.cc
r79841be r6943a987 10 10 // Created On : Sat May 16 14:59:41 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 11 16:19:45201613 // Update Count : 21012 // Last Modified On : Sun Aug 21 11:59:37 2016 13 // Update Count : 325 14 14 // 15 15 … … 26 26 using namespace std; 27 27 28 const char *StatementNode::StType[] = { 29 "Exp", "If", "Switch", "Case", "Default", "Choose", "Fallthru", 30 "While", "Do", "For", 31 "Goto", "Continue", "Break", "Return", "Throw", 32 "Try", "Catch", "Finally", "Asm", 33 "Decl" 34 }; 35 36 StatementNode::StatementNode() : ParseNode(), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {} 37 38 StatementNode::StatementNode( const string *name ) : ParseNode( name ), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {} 39 40 StatementNode::StatementNode( DeclarationNode *decl ) : type( Decl ), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), isCatchRest ( false ) { 28 29 StatementNode::StatementNode( DeclarationNode *decl ) { 41 30 if ( decl ) { 42 if ( DeclarationNode *agg = decl->extractAggregate() ) { 43 this->decl = agg; 44 StatementNode *nextStmt = new StatementNode; 45 nextStmt->type = Decl; 46 nextStmt->decl = decl; 47 next = nextStmt; 48 if ( decl->get_link() ) { 49 next->set_next( new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) ) ); 31 DeclarationNode *agg = decl->extractAggregate(); 32 if ( agg ) { 33 StatementNode *nextStmt = new StatementNode( new DeclStmt( noLabels, maybeBuild< Declaration >( decl ) ) ); 34 set_next( nextStmt ); 35 if ( decl->get_next() ) { 36 get_next()->set_next( new StatementNode( dynamic_cast< DeclarationNode * >(decl->get_next()) ) ); 50 37 decl->set_next( 0 ); 51 38 } // if 52 39 } else { 53 if ( decl->get_ link() ) {54 next = new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) );40 if ( decl->get_next() ) { 41 set_next(new StatementNode( dynamic_cast< DeclarationNode * >( decl->get_next() ) ) ); 55 42 decl->set_next( 0 ); 56 43 } // if 57 this->decl= decl;44 agg = decl; 58 45 } // if 46 stmt.reset( new DeclStmt( noLabels, maybeMoveBuild< Declaration >(agg) ) ); 47 } else { 48 assert( false ); 59 49 } // if 60 50 } 61 51 62 StatementNode::StatementNode( Type t, ExpressionNode *ctrl_label, StatementNode *block ) : type( t ), control( ctrl_label ), block( block ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {63 this->control = ( t == Default ) ? 0 : control;64 }65 66 StatementNode::StatementNode( Type t, string *target ) : type( t ), control( 0 ), block( 0 ), labels( 0 ), target( target ), decl( 0 ), isCatchRest ( false ) {}67 68 StatementNode::~StatementNode() {69 delete control;70 delete block;71 delete target;72 delete decl;73 }74 75 StatementNode * StatementNode::newCatchStmt( DeclarationNode *d, StatementNode *s, bool catchRestP ) {76 StatementNode *ret = new StatementNode( StatementNode::Catch, 0, s );77 ret->addDeclaration( d );78 ret->setCatchRest( catchRestP );79 80 return ret;81 }82 83 std::string StatementNode::get_target() const{84 if ( target )85 return *target;86 87 return string("");88 }89 90 StatementNode * StatementNode::clone() const {91 StatementNode *newnode = new StatementNode( type, maybeClone( control ), maybeClone( block ) );92 if ( target ) {93 newnode->target = new string( *target );94 } else {95 newnode->target = 0;96 } // if97 newnode->decl = maybeClone( decl );98 return newnode;99 }100 101 StatementNode *StatementNode::add_label( const std::string *l ) {102 if ( l != 0 ) {103 labels.push_front( *l );104 delete l;105 } // if106 return this;107 }108 109 StatementNode *StatementNode::append_block( StatementNode *stmt ) {110 if ( stmt != 0 ) {111 if ( block == 0 )112 block = stmt;113 else114 block->set_link( stmt );115 } // if116 return this;117 }118 119 52 StatementNode *StatementNode::append_last_case( StatementNode *stmt ) { 120 assert( false );121 if ( stmt != 0 ) {122 StatementNode *next = ( StatementNode *)get_link();123 if ( next && ( next->get_type() == StatementNode::Case || next->get_type() == StatementNode::Default ) )124 next->append_last_case( stmt );125 else126 if ( block == 0 )127 block = stmt;128 else129 block->set_link( stmt );130 } // if131 return this;132 }133 134 StatementNode *StatementNode2::append_last_case( StatementNode *stmt ) {135 53 StatementNode *prev = this; 136 for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_link() ) {137 StatementNode2 *node = dynamic_cast<StatementNode2 *>(curr);138 assert( node);139 assert( dynamic_cast< CaseStmt *>(node->stmt) );54 // find end of list and maintain previous pointer 55 for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) { 56 StatementNode *node = safe_dynamic_cast< StatementNode * >(curr); 57 assert( dynamic_cast< CaseStmt * >(node->stmt.get()) ); 140 58 prev = curr; 141 59 } // for 142 StatementNode2 *node = dynamic_cast<StatementNode2 *>(prev); 143 std::list<Statement *> stmts; 144 buildList( stmt, stmts ); 145 CaseStmt * caseStmt; 146 caseStmt = dynamic_cast<CaseStmt *>(node->stmt); 60 // convert from StatementNode list to Statement list 61 StatementNode *node = dynamic_cast< StatementNode * >(prev); 62 std::list< Statement * > stmts; 63 buildMoveList( stmt, stmts ); 64 // splice any new Statements to end of current Statements 65 CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get()); 147 66 caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts ); 148 67 return this; 149 68 } 150 69 151 void StatementNode::print( std::ostream &os, int indent ) const {152 if ( ! labels.empty() ) {153 std::list<std::string>::const_iterator i;154 155 os << string( indent, ' ' );156 for ( i = labels.begin(); i != labels.end(); i++ )157 os << *i << ":";158 os << endl;159 } // if160 161 switch ( type ) {162 case Decl:163 decl->print( os, indent );164 break;165 case Exp:166 if ( control ) {167 os << string( indent, ' ' );168 control->print( os, indent );169 os << endl;170 } else171 os << string( indent, ' ' ) << "Null Statement" << endl;172 break;173 default:174 os << string( indent, ' ' ) << StatementNode::StType[type] << endl;175 if ( type == Catch ) {176 if ( decl ) {177 os << string( indent + ParseNode::indent_by, ' ' ) << "Declaration: " << endl;178 decl->print( os, indent + 2 * ParseNode::indent_by );179 } else if ( isCatchRest ) {180 os << string( indent + ParseNode::indent_by, ' ' ) << "Catches the rest " << endl;181 } else {182 ; // should never reach here183 } // if184 } // if185 if ( control ) {186 os << string( indent + ParseNode::indent_by, ' ' ) << "Control: " << endl;187 control->printList( os, indent + 2 * ParseNode::indent_by );188 } // if189 if ( block ) {190 os << string( indent + ParseNode::indent_by, ' ' ) << "Cases: " << endl;191 block->printList( os, indent + 2 * ParseNode::indent_by );192 } // if193 if ( target ) {194 os << string( indent + ParseNode::indent_by, ' ' ) << "Target: " << get_target() << endl;195 } // if196 break;197 } // switch198 }199 200 Statement *StatementNode::build() const {201 std::list<Statement *> branches;202 std::list<Expression *> exps;203 std::list<Label> labs;204 205 if ( ! labels.empty() ) {206 std::back_insert_iterator< std::list<Label> > lab_it( labs );207 copy( labels.begin(), labels.end(), lab_it );208 } // if209 210 // try {211 buildList<Statement, StatementNode>( get_block(), branches );212 213 switch ( type ) {214 case Decl:215 return new DeclStmt( labs, maybeBuild< Declaration >( decl ) );216 case Exp:217 {218 Expression *e = maybeBuild< Expression >( get_control() );219 220 if ( e )221 return new ExprStmt( labs, e );222 else223 return new NullStmt( labs );224 }225 assert( false );226 case If:227 // {228 // Statement *thenb = 0, *elseb = 0;229 // assert( branches.size() >= 1 );230 231 // thenb = branches.front();232 // branches.pop_front();233 // if ( ! branches.empty() ) {234 // elseb = branches.front();235 // branches.pop_front();236 // } // if237 // return new IfStmt( labs, notZeroExpr( maybeBuild<Expression>(get_control()) ), thenb, elseb );238 // }239 assert( false );240 case Switch:241 // return new SwitchStmt( labs, maybeBuild<Expression>(get_control()), branches );242 assert( false );243 case Case:244 //return new CaseStmt( labs, maybeBuild<Expression>(get_control() ), branches );245 assert( false );246 case Default:247 //return new CaseStmt( labs, 0, branches, true );248 assert( false );249 case While:250 // assert( branches.size() == 1 );251 // return new WhileStmt( labs, notZeroExpr( maybeBuild<Expression>(get_control()) ), branches.front() );252 assert( false );253 case Do:254 // assert( branches.size() == 1 );255 // return new WhileStmt( labs, notZeroExpr( maybeBuild<Expression>(get_control()) ), branches.front(), true );256 assert( false );257 case For:258 // {259 // assert( branches.size() == 1 );260 261 // ForCtlExprNode *ctl = dynamic_cast<ForCtlExprNode *>( get_control() );262 // assert( ctl != 0 );263 264 // std::list<Statement *> init;265 // if ( ctl->get_init() != 0 ) {266 // buildList( ctl->get_init(), init );267 // } // if268 269 // Expression *cond = 0;270 // if ( ctl->get_condition() != 0 )271 // cond = notZeroExpr( maybeBuild<Expression>(ctl->get_condition()) );272 273 // Expression *incr = 0;274 // if ( ctl->get_change() != 0 )275 // incr = maybeBuild<Expression>(ctl->get_change());276 277 // return new ForStmt( labs, init, cond, incr, branches.front() );278 // }279 assert( false );280 case Goto:281 // {282 // if ( get_target() == "" ) { // computed goto283 // assert( get_control() != 0 );284 // return new BranchStmt( labs, maybeBuild<Expression>(get_control()), BranchStmt::Goto );285 // } // if286 287 // return new BranchStmt( labs, get_target(), BranchStmt::Goto );288 // }289 assert( false );290 case Break:291 // return new BranchStmt( labs, get_target(), BranchStmt::Break );292 assert( false );293 case Continue:294 // return new BranchStmt( labs, get_target(), BranchStmt::Continue );295 assert( false );296 case Return:297 case Throw :298 // buildList( get_control(), exps );299 // if ( exps.size() ==0 )300 // return new ReturnStmt( labs, 0, type == Throw );301 // if ( exps.size() > 0 )302 // return new ReturnStmt( labs, exps.back(), type == Throw );303 assert( false );304 case Try:305 {306 assert( branches.size() >= 0 );307 CompoundStmt *tryBlock = dynamic_cast<CompoundStmt *>( branches.front());308 branches.pop_front();309 FinallyStmt *finallyBlock = 0;310 if ( ( finallyBlock = dynamic_cast<FinallyStmt *>( branches.back())) ) {311 branches.pop_back();312 } // if313 return new TryStmt( labs, tryBlock, branches, finallyBlock );314 }315 case Catch:316 {317 assert( branches.size() == 1 );318 319 return new CatchStmt( labs, maybeBuild< Declaration >( decl ), branches.front(), isCatchRest );320 }321 case Finally:322 {323 assert( branches.size() == 1 );324 CompoundStmt *block = dynamic_cast<CompoundStmt *>( branches.front() );325 assert( block != 0 );326 327 return new FinallyStmt( labs, block );328 }329 case Asm:330 assert( false );331 default:332 // shouldn't be here333 return 0;334 } // switch335 }336 337 70 Statement *build_expr( ExpressionNode *ctl ) { 338 Expression *e = maybe Build< Expression >( ctl );71 Expression *e = maybeMoveBuild< Expression >( ctl ); 339 72 340 73 if ( e ) … … 346 79 Statement *build_if( ExpressionNode *ctl, StatementNode *then_stmt, StatementNode *else_stmt ) { 347 80 Statement *thenb, *elseb = 0; 348 std::list< Statement *> branches;349 build List<Statement, StatementNode>( then_stmt, branches );81 std::list< Statement * > branches; 82 buildMoveList< Statement, StatementNode >( then_stmt, branches ); 350 83 assert( branches.size() == 1 ); 351 84 thenb = branches.front(); 352 85 353 86 if ( else_stmt ) { 354 std::list< Statement *> branches;355 build List<Statement, StatementNode>( else_stmt, branches );87 std::list< Statement * > branches; 88 buildMoveList< Statement, StatementNode >( else_stmt, branches ); 356 89 assert( branches.size() == 1 ); 357 90 elseb = branches.front(); 358 91 } // if 359 return new IfStmt( noLabels, notZeroExpr( maybe Build<Expression>(ctl) ), thenb, elseb );92 return new IfStmt( noLabels, notZeroExpr( maybeMoveBuild< Expression >(ctl) ), thenb, elseb ); 360 93 } 361 94 362 95 Statement *build_switch( ExpressionNode *ctl, StatementNode *stmt ) { 363 std::list< Statement *> branches;364 build List<Statement, StatementNode>( stmt, branches );96 std::list< Statement * > branches; 97 buildMoveList< Statement, StatementNode >( stmt, branches ); 365 98 assert( branches.size() >= 0 ); // size == 0 for switch (...) {}, i.e., no declaration or statements 366 return new SwitchStmt( noLabels, maybe Build<Expression>(ctl), branches );99 return new SwitchStmt( noLabels, maybeMoveBuild< Expression >(ctl), branches ); 367 100 } 368 101 Statement *build_case( ExpressionNode *ctl ) { 369 std::list< Statement *> branches;370 return new CaseStmt( noLabels, maybe Build<Expression>(ctl), branches );102 std::list< Statement * > branches; 103 return new CaseStmt( noLabels, maybeMoveBuild< Expression >(ctl), branches ); 371 104 } 372 105 Statement *build_default() { 373 std::list< Statement *> branches;106 std::list< Statement * > branches; 374 107 return new CaseStmt( noLabels, nullptr, branches, true ); 375 108 } 376 109 377 110 Statement *build_while( ExpressionNode *ctl, StatementNode *stmt, bool kind ) { 378 std::list< Statement *> branches;379 build List<Statement, StatementNode>( stmt, branches );380 assert( branches.size() == 1 ); 381 return new WhileStmt( noLabels, notZeroExpr( maybe Build<Expression>(ctl) ), branches.front(), kind );111 std::list< Statement * > branches; 112 buildMoveList< Statement, StatementNode >( stmt, branches ); 113 assert( branches.size() == 1 ); 114 return new WhileStmt( noLabels, notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), kind ); 382 115 } 383 116 384 117 Statement *build_for( ForCtl *forctl, StatementNode *stmt ) { 385 std::list< Statement *> branches;386 build List<Statement, StatementNode>( stmt, branches );387 assert( branches.size() == 1 ); 388 389 std::list< Statement *> init;118 std::list< Statement * > branches; 119 buildMoveList< Statement, StatementNode >( stmt, branches ); 120 assert( branches.size() == 1 ); 121 122 std::list< Statement * > init; 390 123 if ( forctl->init != 0 ) { 391 build List( forctl->init, init );124 buildMoveList( forctl->init, init ); 392 125 } // if 393 126 394 127 Expression *cond = 0; 395 128 if ( forctl->condition != 0 ) 396 cond = notZeroExpr( maybe Build<Expression>(forctl->condition) );129 cond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) ); 397 130 398 131 Expression *incr = 0; 399 132 if ( forctl->change != 0 ) 400 incr = maybe Build<Expression>(forctl->change);133 incr = maybeMoveBuild< Expression >(forctl->change); 401 134 402 135 delete forctl; … … 404 137 } 405 138 406 Statement *build_branch( std::string identifier, BranchStmt::Type kind ) { 407 return new BranchStmt( noLabels, identifier, kind ); 139 Statement *build_branch( BranchStmt::Type kind ) { 140 Statement * ret = new BranchStmt( noLabels, "", kind ); 141 return ret; 142 } 143 Statement *build_branch( std::string *identifier, BranchStmt::Type kind ) { 144 Statement * ret = new BranchStmt( noLabels, *identifier, kind ); 145 delete identifier; // allocated by lexer 146 return ret; 408 147 } 409 148 Statement *build_computedgoto( ExpressionNode *ctl ) { 410 return new BranchStmt( noLabels, maybe Build<Expression>(ctl), BranchStmt::Goto );149 return new BranchStmt( noLabels, maybeMoveBuild< Expression >(ctl), BranchStmt::Goto ); 411 150 } 412 151 413 152 Statement *build_return( ExpressionNode *ctl ) { 414 std::list< Expression *> exps;415 build List( ctl, exps );153 std::list< Expression * > exps; 154 buildMoveList( ctl, exps ); 416 155 return new ReturnStmt( noLabels, exps.size() > 0 ? exps.back() : nullptr ); 417 156 } 418 157 Statement *build_throw( ExpressionNode *ctl ) { 419 std::list<Expression *> exps; 420 buildList( ctl, exps ); 421 return new ReturnStmt( noLabels, exps.size() > 0 ? exps.back() : nullptr, true ); 422 } 423 424 425 CompoundStmtNode::CompoundStmtNode() : first( 0 ), last( 0 ) {} 426 427 CompoundStmtNode::CompoundStmtNode( const string *name_ ) : StatementNode( name_ ), first( 0 ), last( 0 ) {} 428 429 CompoundStmtNode::CompoundStmtNode( StatementNode *stmt ) : first( stmt ) { 430 if ( first ) { 431 last = ( StatementNode *)( stmt->get_last()); 432 } else { 433 last = 0; 434 } // if 435 } 436 437 CompoundStmtNode::~CompoundStmtNode() { 438 delete first; 439 } 440 441 void CompoundStmtNode::add_statement( StatementNode *stmt ) { 442 if ( stmt != 0 ) { 443 last->set_link( stmt ); 444 last = ( StatementNode *)( stmt->get_link()); 445 } // if 446 } 447 448 void CompoundStmtNode::print( ostream &os, int indent ) const { 449 if ( first ) { 450 first->printList( os, indent+2 ); 451 } // if 452 } 453 454 Statement *CompoundStmtNode::build() const { 455 std::list<Label> labs; 456 const std::list<std::string> &labels = get_labels(); 457 458 if ( ! labels.empty() ) { 459 std::back_insert_iterator< std::list<Label> > lab_it( labs ); 460 copy( labels.begin(), labels.end(), lab_it ); 461 } // if 462 463 CompoundStmt *cs = new CompoundStmt( labs ); 464 buildList( first, cs->get_kids() ); 158 std::list< Expression * > exps; 159 buildMoveList( ctl, exps ); 160 assertf( exps.size() < 2, "This means we are leaking memory"); 161 return new ReturnStmt( noLabels, !exps.empty() ? exps.back() : nullptr, true ); 162 } 163 164 Statement *build_try( StatementNode *try_stmt, StatementNode *catch_stmt, StatementNode *finally_stmt ) { 165 std::list< Statement * > branches; 166 buildMoveList< Statement, StatementNode >( catch_stmt, branches ); 167 CompoundStmt *tryBlock = safe_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_stmt)); 168 FinallyStmt *finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_stmt) ); 169 return new TryStmt( noLabels, tryBlock, branches, finallyBlock ); 170 } 171 Statement *build_catch( DeclarationNode *decl, StatementNode *stmt, bool catchAny ) { 172 std::list< Statement * > branches; 173 buildMoveList< Statement, StatementNode >( stmt, branches ); 174 assert( branches.size() == 1 ); 175 return new CatchStmt( noLabels, maybeMoveBuild< Declaration >(decl), branches.front(), catchAny ); 176 } 177 Statement *build_finally( StatementNode *stmt ) { 178 std::list< Statement * > branches; 179 buildMoveList< Statement, StatementNode >( stmt, branches ); 180 assert( branches.size() == 1 ); 181 return new FinallyStmt( noLabels, dynamic_cast< CompoundStmt * >( branches.front() ) ); 182 } 183 184 Statement *build_compound( StatementNode *first ) { 185 CompoundStmt *cs = new CompoundStmt( noLabels ); 186 buildMoveList( first, cs->get_kids() ); 465 187 return cs; 466 188 } 467 189 468 469 AsmStmtNode::AsmStmtNode( Type t, bool voltile, ConstantExpr *instruction, ExpressionNode *output, ExpressionNode *input, ExpressionNode *clobber, LabelNode *gotolabels ) : 470 StatementNode( t ), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ) { 471 if ( gotolabels ) { 472 this->gotolabels = gotolabels->get_labels(); 473 delete gotolabels; 474 } // if 475 } 476 477 AsmStmtNode::~AsmStmtNode() { 478 delete output; delete input; delete clobber; 479 } 480 481 void AsmStmtNode::print( std::ostream &os, int indent ) const { 482 StatementNode::print( os, indent ); // print statement labels 483 os << string( indent + ParseNode::indent_by, ' ' ) << "volatile:" << voltile << endl; 484 if ( instruction ) { 485 os << string( indent + ParseNode::indent_by, ' ' ) << "Instruction:" << endl; 486 // instruction->printList( os, indent + 2 * ParseNode::indent_by ); 487 } // if 488 if ( output ) { 489 os << string( indent + ParseNode::indent_by, ' ' ) << "Output:" << endl; 490 output->printList( os, indent + 2 * ParseNode::indent_by ); 491 } // if 492 if ( input ) { 493 os << string( indent + ParseNode::indent_by, ' ' ) << "Input:" << endl; 494 input->printList( os, indent + 2 * ParseNode::indent_by ); 495 } // if 496 if ( clobber ) { 497 os << string( indent + ParseNode::indent_by, ' ' ) << "Clobber:" << endl; 498 // clobber->printList( os, indent + 2 * ParseNode::indent_by ); 499 } // if 500 if ( ! gotolabels.empty() ) { 501 os << string( indent + ParseNode::indent_by, ' ' ) << "Goto Labels:" << endl; 502 os << string( indent + 2 * ParseNode::indent_by, ' ' ); 503 for ( std::list<Label>::const_iterator i = gotolabels.begin();; ) { 504 os << *i; 505 i++; 506 if ( i == gotolabels.end() ) break; 507 os << ", "; 508 } 509 os << endl; 510 } // if 511 } 512 513 Statement *AsmStmtNode::build() const { 514 std::list<Label> labs; 515 516 if ( ! get_labels().empty() ) { 517 std::back_insert_iterator< std::list<Label> > lab_it( labs ); 518 copy( get_labels().begin(), get_labels().end(), lab_it ); 519 } // if 520 190 Statement *build_asmstmt( bool voltile, ConstantExpr *instruction, ExpressionNode *output, ExpressionNode *input, ExpressionNode *clobber, LabelNode *gotolabels ) { 521 191 std::list< Expression * > out, in; 522 192 std::list< ConstantExpr * > clob; 523 buildList( output, out ); 524 build List( input, in);525 build List( clobber, clob);526 std::list< Label > gotolabs = gotolabels;527 return new AsmStmt( labs, voltile, instruction, out, in, clob, gotolabs );193 194 buildMoveList( output, out ); 195 buildMoveList( input, in ); 196 buildMoveList( clobber, clob ); 197 return new AsmStmt( noLabels, voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels ); 528 198 } 529 199 -
src/Parser/TypeData.cc
r79841be r6943a987 10 10 // Created On : Sat May 16 15:12:51 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Aug 7 07:51:48 201613 // Update Count : 5812 // Last Modified On : Sun Aug 28 18:28:58 2016 13 // Update Count : 223 14 14 // 15 15 … … 94 94 break; 95 95 } // switch 96 } 96 } // TypeData::TypeData 97 97 98 98 TypeData::~TypeData() { … … 163 163 break; 164 164 } // switch 165 } 166 167 TypeData * TypeData::clone() const {168 TypeData * newtype = new TypeData( kind );165 } // TypeData::~TypeData 166 167 TypeData * TypeData::clone() const { 168 TypeData * newtype = new TypeData( kind ); 169 169 newtype->qualifiers = qualifiers; 170 170 newtype->base = maybeClone( base ); … … 182 182 break; 183 183 case Array: 184 //PAB newtype->array->dimension = maybeClone( array->dimension ); 185 newtype->array->dimension = array->dimension; 184 newtype->array->dimension = maybeClone( array->dimension ); 186 185 newtype->array->isVarLen = array->isVarLen; 187 186 newtype->array->isStatic = array->isStatic; … … 239 238 } // switch 240 239 return newtype; 241 } 240 } // TypeData::clone 242 241 243 242 void TypeData::print( std::ostream &os, int indent ) const { … … 245 244 using std::string; 246 245 247 printEnums( qualifiers.begin(), qualifiers.end(), DeclarationNode::qualifierName, os ); 246 for ( int i = 0; i < DeclarationNode::NoOfQualifier; i += 1 ) { 247 if ( qualifiers[i] ) os << DeclarationNode::qualifierName[ i ] << ' '; 248 } // for 248 249 249 250 if ( forall ) { … … 417 418 assert( false ); 418 419 } // switch 419 } 420 421 TypeData *TypeData::extractAggregate( bool toplevel ) const { 422 TypeData *ret = 0; 423 424 switch ( kind ) { 425 case Aggregate: 426 if ( ! toplevel && aggregate->fields ) { 427 ret = clone(); 428 ret->qualifiers.clear(); 429 } // if 430 break; 431 case Enum: 432 if ( ! toplevel && enumeration->constants ) { 433 ret = clone(); 434 ret->qualifiers.clear(); 435 } // if 436 break; 437 case AggregateInst: 438 if ( aggInst->aggregate ) { 439 ret = aggInst->aggregate->extractAggregate( false ); 440 } // if 441 break; 442 default: 443 if ( base ) { 444 ret = base->extractAggregate( false ); 445 } // if 446 } // switch 447 return ret; 448 } 449 450 void buildForall( const DeclarationNode *firstNode, std::list< TypeDecl* > &outputList ) { 420 } // TypeData::print 421 422 void buildForall( const DeclarationNode * firstNode, std::list< TypeDecl* > &outputList ) { 451 423 buildList( firstNode, outputList ); 452 424 for ( std::list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) { … … 454 426 // add assertion parameters to `type' tyvars in reverse order 455 427 // add dtor: void ^?{}(T *) 456 FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false );428 FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false ); 457 429 dtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); 458 430 (*i)->get_assertions().push_front( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, dtorType, 0, false, false ) ); 459 431 460 432 // add copy ctor: void ?{}(T *, T) 461 FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false );433 FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false ); 462 434 copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); 463 435 copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) ); … … 465 437 466 438 // add default ctor: void ?{}(T *) 467 FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false );439 FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false ); 468 440 ctorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); 469 441 (*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, ctorType, 0, false, false ) ); 470 442 471 443 // add assignment operator: T * ?=?(T *, T) 472 FunctionType * assignType = new FunctionType( Type::Qualifiers(), false );444 FunctionType * assignType = new FunctionType( Type::Qualifiers(), false ); 473 445 assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) ); 474 446 assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) ); … … 479 451 } 480 452 481 Declaration *TypeData::buildDecl( std::string name, DeclarationNode::StorageClass sc, Expression *bitfieldWidth, bool isInline, bool isNoreturn, LinkageSpec::Type linkage, Initializer *init ) const { 482 if ( kind == TypeData::Function ) { 483 FunctionDecl *decl; 484 if ( function->hasBody ) { 485 if ( function->body ) { 486 Statement *stmt = function->body->build(); 487 CompoundStmt *body = dynamic_cast< CompoundStmt* >( stmt ); 488 assert( body ); 489 decl = new FunctionDecl( name, sc, linkage, buildFunction(), body, isInline, isNoreturn ); 490 } else { 491 // std::list<Label> ls; 492 decl = new FunctionDecl( name, sc, linkage, buildFunction(), new CompoundStmt( std::list<Label>() ), isInline, isNoreturn ); 493 } // if 494 } else { 495 decl = new FunctionDecl( name, sc, linkage, buildFunction(), 0, isInline, isNoreturn ); 496 } // if 497 for ( DeclarationNode *cur = function->idList; cur != 0; cur = dynamic_cast< DeclarationNode* >( cur->get_link() ) ) { 498 if ( cur->get_name() != "" ) { 499 decl->get_oldIdents().insert( decl->get_oldIdents().end(), cur->get_name() ); 500 } // if 501 } // for 502 buildList( function->oldDeclList, decl->get_oldDecls() ); 503 return decl; 504 } else if ( kind == TypeData::Aggregate ) { 505 return buildAggregate(); 506 } else if ( kind == TypeData::Enum ) { 507 return buildEnum(); 508 } else if ( kind == TypeData::Symbolic ) { 509 return buildSymbolic( name, sc ); 510 } else if ( kind == TypeData::Variable ) { 511 return buildVariable(); 512 } else { 513 return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, std::list< Attribute * >(), isInline, isNoreturn ); 514 } // if 515 return 0; 516 } 517 518 Type *TypeData::build() const { 519 switch ( kind ) { 520 case Unknown: 453 Type * typebuild( const TypeData * td ) { 454 assert( td ); 455 switch ( td->kind ) { 456 case TypeData::Unknown: 521 457 // fill in implicit int 522 return new BasicType( buildQualifiers( ), BasicType::SignedInt );523 case Basic:524 return buildBasicType( );525 case Pointer:526 return buildPointer( );527 case Array:528 return buildArray( );529 case Function:530 return buildFunction( );531 case AggregateInst:532 return buildAggInst( );533 case EnumConstant:458 return new BasicType( buildQualifiers( td ), BasicType::SignedInt ); 459 case TypeData::Basic: 460 return buildBasicType( td ); 461 case TypeData::Pointer: 462 return buildPointer( td ); 463 case TypeData::Array: 464 return buildArray( td ); 465 case TypeData::Function: 466 return buildFunction( td ); 467 case TypeData::AggregateInst: 468 return buildAggInst( td ); 469 case TypeData::EnumConstant: 534 470 // the name gets filled in later -- by SymTab::Validate 535 return new EnumInstType( buildQualifiers( ), "" );536 case SymbolicInst:537 return buildSymbolicInst( );;538 case T uple:539 return buildTuple( );540 case Type of:541 return buildTypeof( );542 case Builtin:543 return new VarArgsType( buildQualifiers( ) );544 case Attr:545 return buildAttr( );546 case Symbolic:547 case Enum:548 case Aggregate:549 case Variable:471 return new EnumInstType( buildQualifiers( td ), "" ); 472 case TypeData::SymbolicInst: 473 return buildSymbolicInst( td );; 474 case TypeData::Tuple: 475 return buildTuple( td ); 476 case TypeData::Typeof: 477 return buildTypeof( td ); 478 case TypeData::Builtin: 479 return new VarArgsType( buildQualifiers( td ) ); 480 case TypeData::Attr: 481 return buildAttr( td ); 482 case TypeData::Symbolic: 483 case TypeData::Enum: 484 case TypeData::Aggregate: 485 case TypeData::Variable: 550 486 assert( false ); 551 487 } // switch 552 488 return 0; 553 } 554 555 Type::Qualifiers TypeData::buildQualifiers() const { 489 } // typebuild 490 491 TypeData * typeextractAggregate( const TypeData * td, bool toplevel ) { 492 TypeData * ret = 0; 493 494 switch ( td->kind ) { 495 case TypeData::Aggregate: 496 if ( ! toplevel && td->aggregate->fields ) { 497 ret = td->clone(); 498 } // if 499 break; 500 case TypeData::Enum: 501 if ( ! toplevel && td->enumeration->constants ) { 502 ret = td->clone(); 503 } // if 504 break; 505 case TypeData::AggregateInst: 506 if ( td->aggInst->aggregate ) { 507 ret = typeextractAggregate( td->aggInst->aggregate, false ); 508 } // if 509 break; 510 default: 511 if ( td->base ) { 512 ret = typeextractAggregate( td->base, false ); 513 } // if 514 } // switch 515 return ret; 516 } // typeextractAggregate 517 518 Type::Qualifiers buildQualifiers( const TypeData * td ) { 556 519 Type::Qualifiers q; 557 for ( std::list< DeclarationNode::Qualifier >::const_iterator i = qualifiers.begin(); i != qualifiers.end(); ++i ) { 558 switch ( *i ) { 559 case DeclarationNode::Const: 560 q.isConst = true; 561 break; 562 case DeclarationNode::Volatile: 563 q.isVolatile = true; 564 break; 565 case DeclarationNode::Restrict: 566 q.isRestrict = true; 567 break; 568 case DeclarationNode::Lvalue: 569 q.isLvalue = true; 570 break; 571 case DeclarationNode::Atomic: 572 q.isAtomic = true; 573 break; 574 } // switch 575 } // for 520 q.isConst = td->qualifiers[ DeclarationNode::Const ]; 521 q.isVolatile = td->qualifiers[ DeclarationNode::Volatile ]; 522 q.isRestrict = td->qualifiers[ DeclarationNode::Restrict ]; 523 q.isLvalue = td->qualifiers[ DeclarationNode::Lvalue ]; 524 q.isAtomic = td->qualifiers[ DeclarationNode::Atomic ];; 576 525 return q; 577 } 578 579 Type * TypeData::buildBasicType() const{526 } // buildQualifiers 527 528 Type * buildBasicType( const TypeData * td ) { 580 529 static const BasicType::Kind kindMap[] = { BasicType::Char, BasicType::SignedInt, BasicType::Float, BasicType::Double, 581 530 BasicType::Char /* void */, BasicType::Bool, BasicType::DoubleComplex, … … 586 535 BasicType::Kind ret; 587 536 588 for ( std::list< DeclarationNode::BasicType >::const_iterator i = basic->typeSpec.begin(); i !=basic->typeSpec.end(); ++i ) {537 for ( std::list< DeclarationNode::BasicType >::const_iterator i = td->basic->typeSpec.begin(); i != td->basic->typeSpec.end(); ++i ) { 589 538 if ( ! init ) { 590 539 init = true; 591 540 if ( *i == DeclarationNode::Void ) { 592 if ( basic->typeSpec.size() != 1 || !basic->modifiers.empty() ) {593 throw SemanticError( "invalid type specifier \"void\" in type: ", t his);541 if ( td->basic->typeSpec.size() != 1 || ! td->basic->modifiers.empty() ) { 542 throw SemanticError( "invalid type specifier \"void\" in type: ", td ); 594 543 } else { 595 return new VoidType( buildQualifiers( ) );544 return new VoidType( buildQualifiers( td ) ); 596 545 } // if 597 546 } else { … … 602 551 case DeclarationNode::Float: 603 552 if ( sawDouble ) { 604 throw SemanticError( "invalid type specifier \"float\" in type: ", t his);553 throw SemanticError( "invalid type specifier \"float\" in type: ", td ); 605 554 } else { 606 555 switch ( ret ) { … … 612 561 break; 613 562 default: 614 throw SemanticError( "invalid type specifier \"float\" in type: ", t his);563 throw SemanticError( "invalid type specifier \"float\" in type: ", td ); 615 564 } // switch 616 565 } // if … … 618 567 case DeclarationNode::Double: 619 568 if ( sawDouble ) { 620 throw SemanticError( "duplicate type specifier \"double\" in type: ", t his);569 throw SemanticError( "duplicate type specifier \"double\" in type: ", td ); 621 570 } else { 622 571 switch ( ret ) { … … 625 574 break; 626 575 default: 627 throw SemanticError( "invalid type specifier \"double\" in type: ", t his);576 throw SemanticError( "invalid type specifier \"double\" in type: ", td ); 628 577 } // switch 629 578 } // if … … 638 587 break; 639 588 default: 640 throw SemanticError( "invalid type specifier \"_Complex\" in type: ", t his);589 throw SemanticError( "invalid type specifier \"_Complex\" in type: ", td ); 641 590 } // switch 642 591 break; … … 650 599 break; 651 600 default: 652 throw SemanticError( "invalid type specifier \"_Imaginary\" in type: ", t his);601 throw SemanticError( "invalid type specifier \"_Imaginary\" in type: ", td ); 653 602 } // switch 654 603 break; 655 604 default: 656 throw SemanticError( std::string( "invalid type specifier \"" ) + DeclarationNode::basicTypeName[ *i ] + "\" in type: ", t his);605 throw SemanticError( std::string( "invalid type specifier \"" ) + DeclarationNode::basicTypeName[ *i ] + "\" in type: ", td ); 657 606 } // switch 658 607 } // if … … 662 611 } // for 663 612 664 for ( std::list< DeclarationNode::Modifier >::const_iterator i = basic->modifiers.begin(); i !=basic->modifiers.end(); ++i ) {613 for ( std::list< DeclarationNode::Modifier >::const_iterator i = td->basic->modifiers.begin(); i != td->basic->modifiers.end(); ++i ) { 665 614 switch ( *i ) { 666 615 case DeclarationNode::Long: … … 692 641 break; 693 642 default: 694 throw SemanticError( "invalid type modifier \"long\" in type: ", t his);643 throw SemanticError( "invalid type modifier \"long\" in type: ", td ); 695 644 } // switch 696 645 } // if … … 709 658 break; 710 659 default: 711 throw SemanticError( "invalid type modifier \"short\" in type: ", t his);660 throw SemanticError( "invalid type modifier \"short\" in type: ", td ); 712 661 } // switch 713 662 } // if … … 718 667 ret = BasicType::SignedInt; 719 668 } else if ( sawSigned ) { 720 throw SemanticError( "duplicate type modifer \"signed\" in type: ", t his);669 throw SemanticError( "duplicate type modifer \"signed\" in type: ", td ); 721 670 } else { 722 671 switch ( ret ) { … … 734 683 break; 735 684 default: 736 throw SemanticError( "invalid type modifer \"signed\" in type: ", t his);685 throw SemanticError( "invalid type modifer \"signed\" in type: ", td ); 737 686 } // switch 738 687 } // if … … 743 692 ret = BasicType::UnsignedInt; 744 693 } else if ( sawSigned ) { 745 throw SemanticError( "invalid type modifer \"unsigned\" in type: ", t his);694 throw SemanticError( "invalid type modifer \"unsigned\" in type: ", td ); 746 695 } else { 747 696 switch ( ret ) { … … 762 711 break; 763 712 default: 764 throw SemanticError( "invalid type modifer \"unsigned\" in type: ", t his);713 throw SemanticError( "invalid type modifer \"unsigned\" in type: ", td ); 765 714 } // switch 766 715 } // if … … 773 722 } // for 774 723 775 BasicType * bt;724 BasicType * bt; 776 725 if ( ! init ) { 777 bt = new BasicType( buildQualifiers( ), BasicType::SignedInt );726 bt = new BasicType( buildQualifiers( td ), BasicType::SignedInt ); 778 727 } else { 779 bt = new BasicType( buildQualifiers( ), ret );728 bt = new BasicType( buildQualifiers( td ), ret ); 780 729 } // if 781 buildForall( forall, bt->get_forall() );730 buildForall( td->forall, bt->get_forall() ); 782 731 return bt; 783 } 784 785 786 PointerType *TypeData::buildPointer() const { 787 PointerType *pt; 788 if ( base ) { 789 pt = new PointerType( buildQualifiers(), base->build() ); 732 } // buildBasicType 733 734 PointerType * buildPointer( const TypeData * td ) { 735 PointerType * pt; 736 if ( td->base ) { 737 pt = new PointerType( buildQualifiers( td ), typebuild( td->base ) ); 790 738 } else { 791 pt = new PointerType( buildQualifiers( ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );739 pt = new PointerType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 792 740 } // if 793 buildForall( forall, pt->get_forall() );741 buildForall( td->forall, pt->get_forall() ); 794 742 return pt; 795 } 796 797 ArrayType * TypeData::buildArray() const{798 ArrayType * at;799 if ( base ) {800 at = new ArrayType( buildQualifiers( ), base->build(), maybeBuild< Expression >(array->dimension ),801 array->isVarLen,array->isStatic );743 } // buildPointer 744 745 ArrayType * buildArray( const TypeData * td ) { 746 ArrayType * at; 747 if ( td->base ) { 748 at = new ArrayType( buildQualifiers( td ), typebuild( td->base ), maybeBuild< Expression >( td->array->dimension ), 749 td->array->isVarLen, td->array->isStatic ); 802 750 } else { 803 at = new ArrayType( buildQualifiers( ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ),804 maybeBuild< Expression >( array->dimension ), array->isVarLen,array->isStatic );751 at = new ArrayType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 752 maybeBuild< Expression >( td->array->dimension ), td->array->isVarLen, td->array->isStatic ); 805 753 } // if 806 buildForall( forall, at->get_forall() );754 buildForall( td->forall, at->get_forall() ); 807 755 return at; 808 } 809 810 FunctionType *TypeData::buildFunction() const { 811 assert( kind == Function ); 812 bool hasEllipsis = function->params ? function->params->get_hasEllipsis() : true; 813 if ( ! function->params ) hasEllipsis = ! function->newStyle; 814 FunctionType *ft = new FunctionType( buildQualifiers(), hasEllipsis ); 815 buildList( function->params, ft->get_parameters() ); 816 buildForall( forall, ft->get_forall() ); 817 if ( base ) { 818 switch ( base->kind ) { 819 case Tuple: 820 buildList( base->tuple->members, ft->get_returnVals() ); 756 } // buildPointer 757 758 AggregateDecl * buildAggregate( const TypeData * td ) { 759 assert( td->kind == TypeData::Aggregate ); 760 AggregateDecl * at; 761 switch ( td->aggregate->kind ) { 762 case DeclarationNode::Struct: 763 at = new StructDecl( td->aggregate->name ); 764 buildForall( td->aggregate->params, at->get_parameters() ); 765 break; 766 case DeclarationNode::Union: 767 at = new UnionDecl( td->aggregate->name ); 768 buildForall( td->aggregate->params, at->get_parameters() ); 769 break; 770 case DeclarationNode::Trait: 771 at = new TraitDecl( td->aggregate->name ); 772 buildList( td->aggregate->params, at->get_parameters() ); 773 break; 774 default: 775 assert( false ); 776 } // switch 777 778 buildList( td->aggregate->fields, at->get_members() ); 779 at-&