source: src/Parser/ExpressionNode.cc@ 9d79f93

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 9d79f93 was bf4b4cf, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Remove argName from Expression.

If named arguments are ever considered again, they should be added in UntypedExpr (and maybe also ApplicationExpr) to avoid unnecessary fields in every Expression. Like designators on initializers, it should be much easier to work with argument names at the call expression level.

  • Property mode set to 100644
File size: 20.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ExpressionNode.cc --
8//
9// Author : Peter A. Buhr
10// Created On : Sat May 16 13:17:07 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Tue Sep 26 11:23:36 2017
13// Update Count : 780
14//
15
16#include <cassert> // for assert
17#include <stdio.h> // for sscanf, size_t
18#include <climits> // for LLONG_MAX, LONG_MAX, INT_MAX, UINT...
19#include <list> // for list
20#include <sstream> // for basic_istream::operator>>, basic_i...
21#include <string> // for string, operator+, operator==
22
23#include "Common/SemanticError.h" // for SemanticError
24#include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo...
25#include "ParseNode.h" // for ExpressionNode, maybeMoveBuildType
26#include "SynTree/Constant.h" // for Constant
27#include "SynTree/Declaration.h" // for EnumDecl, StructDecl, UnionDecl
28#include "SynTree/Expression.h" // for Expression, ConstantExpr, NameExpr
29#include "SynTree/Statement.h" // for CompoundStmt, Statement
30#include "SynTree/Type.h" // for BasicType, Type, Type::Qualifiers
31#include "parserutility.h" // for notZeroExpr
32
33class Initializer;
34
35using namespace std;
36
37//##############################################################################
38
39// Difficult to separate extra parts of constants during lexing because actions are not allow in the middle of patterns:
40//
41// prefix action constant action suffix
42//
43// Alternatively, breaking a pattern using BEGIN does not work if the following pattern can be empty:
44//
45// constant BEGIN CONT ...
46// <CONT>(...)? BEGIN 0 ... // possible empty suffix
47//
48// because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their
49// type.
50
51extern const Type::Qualifiers noQualifiers; // no qualifiers on constants
52
53static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
54static inline bool checkL( char c ) { return c == 'l' || c == 'L'; }
55static inline bool checkZ( char c ) { return c == 'z' || c == 'Z'; }
56static inline bool checkU( char c ) { return c == 'u' || c == 'U'; }
57static inline bool checkF( char c ) { return c == 'f' || c == 'F'; }
58static inline bool checkD( char c ) { return c == 'd' || c == 'D'; }
59static inline bool checkI( char c ) { return c == 'i' || c == 'I'; }
60static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
61
62static const char * lnthsInt[2][6] = {
63 { "int8_t", "int16_t", "int32_t", "int64_t", "size_t", },
64 { "uint8_t", "uint16_t", "uint32_t", "uint64_t", "size_t", }
65}; // lnthsInt
66
67static inline void checkLNInt( string & str, int & lnth, int & size ) {
68 string::size_type posn = str.find_first_of( "lL" ), start = posn;
69 if ( posn == string::npos ) return;
70 size = 4; // assume largest size
71 posn += 1; // advance to size
72 if ( str[posn] == '8' ) { // 8
73 lnth = 0;
74 } else if ( str[posn] == '1' ) {
75 posn += 1;
76 if ( str[posn] == '6' ) { // 16
77 lnth = 1;
78 } else { // 128
79 posn += 1;
80 lnth = 5;
81 } // if
82 } else {
83 if ( str[posn] == '3' ) { // 32
84 lnth = 2;
85 } else if ( str[posn] == '6' ) { // 64
86 lnth = 3;
87 } else {
88 assertf( false, "internal error, bad integral length %s", str.c_str() );
89 } // if
90 posn += 1;
91 } // if
92 str.erase( start, posn - start + 1 ); // remove length suffix
93} // checkLNInt
94
95static void sepNumeric( string & str, string & units ) {
96 string::size_type posn = str.find_first_of( "`" );
97 if ( posn != string::npos ) {
98 units = "?" + str.substr( posn ); // extract units
99 str.erase( posn ); // remove units
100 } // if
101} // sepNumeric
102
103Expression * build_constantInteger( string & str ) {
104 static const BasicType::Kind kind[2][6] = {
105 // short (h) must be before char (hh)
106 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },
107 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt128, },
108 };
109
110 string units;
111 sepNumeric( str, units ); // separate constant from units
112
113 bool dec = true, Unsigned = false; // decimal, unsigned constant
114 int size; // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
115 int lnth = -1; // literal length
116
117 unsigned long long int v; // converted integral value
118 size_t last = str.length() - 1; // last character of constant
119 Expression * ret;
120
121 // special constants
122 if ( str == "0" ) {
123 ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ) );
124 goto CLEANUP;
125 } // if
126 if ( str == "1" ) {
127 ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ) );
128 goto CLEANUP;
129 } // if
130
131 if ( str[0] == '0' ) { // octal/hex constant ?
132 dec = false;
133 if ( last != 0 && checkX( str[1] ) ) { // hex constant ?
134 sscanf( (char *)str.c_str(), "%llx", &v );
135 //printf( "%llx %llu\n", v, v );
136 } else { // octal constant
137 sscanf( (char *)str.c_str(), "%llo", &v );
138 //printf( "%llo %llu\n", v, v );
139 } // if
140 } else { // decimal constant ?
141 sscanf( (char *)str.c_str(), "%llu", &v );
142 //printf( "%llu %llu\n", v, v );
143 } // if
144
145 if ( v <= INT_MAX ) { // signed int
146 size = 2;
147 } else if ( v <= UINT_MAX && ! dec ) { // unsigned int
148 size = 2;
149 Unsigned = true; // unsigned
150 } else if ( v <= LONG_MAX ) { // signed long int
151 size = 3;
152 } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int
153 size = 3;
154 Unsigned = true; // unsigned long int
155 } else if ( v <= LLONG_MAX ) { // signed long long int
156 size = 4;
157 } else { // unsigned long long int
158 size = 4;
159 Unsigned = true; // unsigned long long int
160 } // if
161
162 // At least one digit in integer constant, so safe to backup while looking for suffix.
163
164 if ( checkU( str[last] ) ) { // suffix 'u' ?
165 Unsigned = true;
166 if ( checkL( str[last - 1] ) ) { // suffix 'l' ?
167 size = 3;
168 if ( checkL( str[last - 2] ) ) { // suffix "ll" ?
169 size = 4;
170 } // if
171 } else if ( checkH( str[last - 1] ) ) { // suffix 'h' ?
172 size = 0;
173 if ( checkH( str[last - 2] ) ) { // suffix "hh" ?
174 size = 1;
175 } // if
176 str.erase( last - size - 1, size + 1 ); // remove 'h'/"hh"
177 } else { // suffix "ln" ?
178 checkLNInt( str, lnth, size );
179 } // if
180 } else if ( checkL( str[ last ] ) ) { // suffix 'l' ?
181 size = 3;
182 if ( checkL( str[last - 1] ) ) { // suffix 'll' ?
183 size = 4;
184 if ( checkU( str[last - 2] ) ) { // suffix 'u' ?
185 Unsigned = true;
186 } // if
187 } else if ( checkU( str[last - 1] ) ) { // suffix 'u' ?
188 Unsigned = true;
189 } // if
190 } else if ( checkH( str[ last ] ) ) { // suffix 'h' ?
191 size = 0;
192 if ( checkH( str[last - 1] ) ) { // suffix "hh" ?
193 size = 1;
194 if ( checkU( str[last - 2] ) ) { // suffix 'u' ?
195 Unsigned = true;
196 } // if
197 } else if ( checkU( str[last - 1] ) ) { // suffix 'u' ?
198 Unsigned = true;
199 } // if
200 str.erase( last - size, size + 1 ); // remove 'h'/"hh"
201 } else if ( checkZ( str[last] ) ) { // suffix 'z' ?
202 lnth = 4;
203 str.erase( last, 1 ); // remove 'z'
204 } else { // suffix "ln" ?
205 checkLNInt( str, lnth, size );
206 } // if
207
208 assert( 0 <= size && size < 6 );
209 ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][size] ), str, v ) );
210 if ( size < 2 ) { // hh or h, less than int ?
211 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
212 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][size] ) );
213 } else if ( lnth != -1 ) { // explicit length ?
214 if ( lnth == 5 ) { // int128 ?
215 size = 5;
216 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][size] ) );
217 } else {
218 ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][lnth], false ) );
219 } // if
220 } // if
221 CLEANUP:
222 if ( units.length() != 0 ) {
223 ret = new UntypedExpr( new NameExpr( units ), { ret } );
224 } // if
225
226 delete &str; // created by lex
227 return ret;
228} // build_constantInteger
229
230
231static inline void checkLNFloat( string & str, int & lnth, int & size ) {
232 string::size_type posn = str.find_first_of( "lL" ), start = posn;
233 if ( posn == string::npos ) return;
234 size = 2; // assume largest size
235 lnth = 0;
236 posn += 1; // advance to size
237 if ( str[posn] == '3' ) { // 32
238 size = 0;
239 } else if ( str[posn] == '6' ) { // 64
240 size = 1;
241 } else if ( str[posn] == '8' || str[posn] == '1' ) { // 80, 128
242 size = 2;
243 if ( str[posn] == '1' ) posn += 1;
244 } else {
245 assertf( false, "internal error, bad floating point length %s", str.c_str() );
246 } // if
247 posn += 1;
248 str.erase( start, posn - start + 1 ); // remove length suffix
249} // checkLNFloat
250
251
252Expression * build_constantFloat( string & str ) {
253 static const BasicType::Kind kind[2][3] = {
254 { BasicType::Float, BasicType::Double, BasicType::LongDouble },
255 { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex },
256 };
257
258 string units;
259 sepNumeric( str, units ); // separate constant from units
260
261 bool complx = false; // real, complex
262 int size = 1; // 0 => float, 1 => double, 2 => long double
263 int lnth = -1; // literal length
264 // floating-point constant has minimum of 2 characters: 1. or .1
265 size_t last = str.length() - 1;
266 double v;
267
268 sscanf( str.c_str(), "%lg", &v );
269
270 if ( checkI( str[last] ) ) { // imaginary ?
271 complx = true;
272 last -= 1; // backup one character
273 } // if
274
275 if ( checkF( str[last] ) ) { // float ?
276 size = 0;
277 } else if ( checkD( str[last] ) ) { // double ?
278 size = 1;
279 } else if ( checkL( str[last] ) ) { // long double ?
280 size = 2;
281 } else {
282 size = 1; // double (default)
283 checkLNFloat( str, lnth, size );
284 } // if
285 if ( ! complx && checkI( str[last - 1] ) ) { // imaginary ?
286 complx = true;
287 } // if
288
289 assert( 0 <= size && size < 3 );
290 Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][size] ), str, v ) );
291 if ( lnth != -1 ) { // explicit length ?
292 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][size] ) );
293 } // if
294 if ( units.length() != 0 ) {
295 ret = new UntypedExpr( new NameExpr( units ), { ret } );
296 } // if
297
298 delete &str; // created by lex
299 return ret;
300} // build_constantFloat
301
302static void sepString( string & str, string & units, char delimit ) {
303 string::size_type posn = str.find_last_of( delimit ) + 1;
304 if ( posn != str.length() ) {
305 units = "?" + str.substr( posn ); // extract units
306 str.erase( posn ); // remove units
307 } // if
308} // sepString
309
310Expression * build_constantChar( string & str ) {
311 string units; // units
312 sepString( str, units, '\'' ); // separate constant from units
313
314 Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) );
315 if ( units.length() != 0 ) {
316 ret = new UntypedExpr( new NameExpr( units ), { ret } );
317 } // if
318
319 delete &str; // created by lex
320 return ret;
321} // build_constantChar
322
323Expression * build_constantStr( string & str ) {
324 string units; // units
325 sepString( str, units, '"' ); // separate constant from units
326
327 Type * strtype;
328 switch ( str[0] ) { // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1
329 case 'u':
330 if ( str[1] == '8' ) goto Default; // utf-8 characters => array of char
331 // lookup type of associated typedef
332 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char16_t", false );
333 break;
334 case 'U':
335 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char32_t", false );
336 break;
337 case 'L':
338 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "wchar_t", false );
339 break;
340 Default: // char default string type
341 default:
342 strtype = new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char );
343 } // switch
344 ArrayType * at = new ArrayType( noQualifiers, strtype,
345 new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
346 false, false );
347 Expression * ret = new ConstantExpr( Constant( at, str, (unsigned long long int)0 ) ); // constant 0 is ignored for pure string value
348 if ( units.length() != 0 ) {
349 ret = new UntypedExpr( new NameExpr( units ), { ret } );
350 } // if
351
352 delete &str; // created by lex
353 return ret;
354} // build_constantStr
355
356Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) {
357 if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) throw SemanticError( "invalid tuple index " + str );
358 Expression * ret = build_constantInteger( *new string( str.substr(1) ) );
359 delete &str;
360 return ret;
361} // build_field_name_FLOATING_FRACTIONconstant
362
363Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) {
364 if ( str[str.size()-1] != '.' ) throw SemanticError( "invalid tuple index " + str );
365 Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) );
366 delete &str;
367 return ret;
368} // build_field_name_FLOATING_DECIMALconstant
369
370Expression * build_field_name_FLOATINGconstant( const string & str ) {
371 // str is of the form A.B -> separate at the . and return member expression
372 int a, b;
373 char dot;
374 stringstream ss( str );
375 ss >> a >> dot >> b;
376 UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) );
377 delete &str;
378 return ret;
379} // build_field_name_FLOATINGconstant
380
381Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) {
382 if ( fracts ) {
383 if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) {
384 memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) );
385 return memberExpr;
386 } else {
387 return new UntypedMemberExpr( fracts, fieldName );
388 } // if
389 } // if
390 return fieldName;
391} // make_field_name_fraction_constants
392
393Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) {
394 return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) );
395} // build_field_name_fraction_constants
396
397NameExpr * build_varref( const string * name ) {
398 NameExpr * expr = new NameExpr( *name );
399 delete name;
400 return expr;
401} // build_varref
402
403// TODO: get rid of this and OperKinds and reuse code from OperatorTable
404static const char * OperName[] = { // must harmonize with OperKinds
405 // diadic
406 "SizeOf", "AlignOf", "OffsetOf", "?+?", "?-?", "?\\?", "?*?", "?/?", "?%?", "||", "&&",
407 "?|?", "?&?", "?^?", "Cast", "?<<?", "?>>?", "?<?", "?>?", "?<=?", "?>=?", "?==?", "?!=?",
408 "?=?", "?@=?", "?\\=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?",
409 "?[?]", "...",
410 // monadic
411 "+?", "-?", "AddressOf", "*?", "!?", "~?", "++?", "?++", "--?", "?--",
412}; // OperName
413
414Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {
415 Type * targetType = maybeMoveBuildType( decl_node );
416 if ( dynamic_cast< VoidType * >( targetType ) ) {
417 delete targetType;
418 return new CastExpr( maybeMoveBuild< Expression >(expr_node) );
419 } else {
420 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType );
421 } // if
422} // build_cast
423
424Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {
425 return new VirtualCastExpr( maybeMoveBuild< Expression >( expr_node ), maybeMoveBuildType( decl_node ) );
426} // build_virtual_cast
427
428Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) {
429 return new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) );
430} // build_fieldSel
431
432Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) {
433 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
434 deref->location = expr_node->location;
435 deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) );
436 UntypedMemberExpr * ret = new UntypedMemberExpr( member, deref );
437 return ret;
438} // build_pfieldSel
439
440Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) {
441 Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() );
442 delete member;
443 return ret;
444} // build_offsetOf
445
446Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ) {
447 return new LogicalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), notZeroExpr( maybeMoveBuild< Expression >(expr_node2) ), kind );
448} // build_and_or
449
450Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ) {
451 list< Expression * > args;
452 args.push_back( maybeMoveBuild< Expression >(expr_node) );
453 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
454} // build_unary_val
455
456Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
457 list< Expression * > args;
458 args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.
459 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
460} // build_unary_ptr
461
462Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
463 list< Expression * > args;
464 args.push_back( maybeMoveBuild< Expression >(expr_node1) );
465 args.push_back( maybeMoveBuild< Expression >(expr_node2) );
466 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
467} // build_binary_val
468
469Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
470 list< Expression * > args;
471 args.push_back( maybeMoveBuild< Expression >(expr_node1) );
472 args.push_back( maybeMoveBuild< Expression >(expr_node2) );
473 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
474} // build_binary_ptr
475
476Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ) {
477 return new ConditionalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), maybeMoveBuild< Expression >(expr_node2), maybeMoveBuild< Expression >(expr_node3) );
478} // build_cond
479
480Expression * build_tuple( ExpressionNode * expr_node ) {
481 list< Expression * > exprs;
482 buildMoveList( expr_node, exprs );
483 return new UntypedTupleExpr( exprs );;
484} // build_tuple
485
486Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) {
487 list< Expression * > args;
488 buildMoveList( expr_node, args );
489 return new UntypedExpr( maybeMoveBuild< Expression >(function), args );
490} // build_func
491
492Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ) {
493 Declaration * newDecl = maybeBuild< Declaration >(decl_node); // compound literal type
494 if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type
495 return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild< Initializer >(kids) );
496 // these types do not have associated type information
497 } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl ) ) {
498 if ( newDeclStructDecl->has_body() ) {
499 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild< Initializer >(kids) );
500 } else {
501 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
502 } // if
503 } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl ) ) {
504 if ( newDeclUnionDecl->has_body() ) {
505 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild< Initializer >(kids) );
506 } else {
507 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
508 } // if
509 } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl ) ) {
510 if ( newDeclEnumDecl->has_body() ) {
511 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild< Initializer >(kids) );
512 } else {
513 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
514 } // if
515 } else {
516 assert( false );
517 } // if
518} // build_compoundLiteral
519
520// Local Variables: //
521// tab-width: 4 //
522// mode: c++ //
523// compile-command: "make install" //
524// End: //
Note: See TracBrowser for help on using the repository browser.