source: src/Parser/ExpressionNode.cpp@ 20c2ade

Last change on this file since 20c2ade was 20c2ade, checked in by Andrew Beach <ajbeach@…>, 15 months ago

Parse string literals to get their length, taking into account escape sequences. Getting this from the lexer would avoid redundent work, but that is not set up. This corrects some typeof evaluations which lead to incorrect sizeof expressions.

  • Property mode set to 100644
File size: 30.9 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.cpp --
8//
9// Author : Peter A. Buhr
10// Created On : Sat May 16 13:17:07 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Aug 23 10:22:00 2024
13// Update Count : 1088
14//
15
16#include "ExpressionNode.hpp"
17
18#include <cassert> // for assert
19#include <stdio.h> // for sscanf, size_t
20#include <climits> // for LLONG_MAX, LONG_MAX, INT_MAX, UINT...
21#include <list> // for list
22#include <sstream> // for basic_istream::operator>>, basic_i...
23#include <string> // for string, operator+, operator==
24
25#include "AST/BasicKind.hpp" // for BasicKind
26#include "AST/Expr.hpp" // for NameExpr
27#include "AST/Type.hpp" // for Type, LengthFlag, DimentionFlag
28#include "Common/SemanticError.hpp"// for SemanticError
29#include "Common/Utility.hpp" // for maybeMoveBuild, maybeBuild, CodeLo...
30#include "DeclarationNode.hpp" // for DeclarationNode
31#include "InitializerNode.hpp" // for InitializerNode
32#include "TypeData.hpp" // for addType, build_basic_type, build_c...
33#include "ParserUtility.hpp" // for notZeroExpr
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
51// static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
52// static inline bool checkZ( char c ) { return c == 'z' || c == 'Z'; }
53// static inline bool checkU( char c ) { return c == 'u' || c == 'U'; }
54static inline bool checkF( char c ) { return c == 'f' || c == 'F'; }
55static inline bool checkD( char c ) { return c == 'd' || c == 'D'; }
56static inline bool checkF80( char c ) { return c == 'w' || c == 'W'; }
57static inline bool checkF128( char c ) { return c == 'q' || c == 'Q'; }
58static inline bool checkL( char c ) { return c == 'l' || c == 'L'; }
59static inline bool checkI( char c ) { return c == 'i' || c == 'I'; }
60static inline bool checkB( char c ) { return c == 'b' || c == 'B'; }
61static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
62// static inline bool checkN( char c ) { return c == 'n' || c == 'N'; }
63
64void lnthSuffix( string & str, int & type, int & ltype ) {
65 // 'u' can appear before or after length suffix
66 string::size_type posn = str.find_last_of( "lL" );
67
68 if ( posn == string::npos ) return; // no suffix
69 size_t end = str.length() - 1;
70 if ( posn == end ) { type = 3; return; } // no length after 'l' => long
71
72 string::size_type next = posn + 1; // advance to length
73 if ( str[next] == '3' ) { // 32
74 type = ltype = 2;
75 } else if ( str[next] == '6' ) { // 64
76 type = ltype = 3;
77 } else if ( str[next] == '8' ) { // 8
78 type = ltype = 1;
79 } else if ( str[next] == '1' ) {
80 if ( str[next + 1] == '6' ) { // 16
81 type = ltype = 0;
82 } else { // 128
83 type = 5; ltype = 6;
84 } // if
85 } // if
86
87 char fix = '\0';
88 if ( str[end] == 'u' || str[end] == 'U' ) fix = str[end]; // ends with 'uU' ?
89 str.erase( posn ); // remove length suffix and possibly uU
90 if ( type == 5 ) { // L128 does not need uU
91 end = str.length() - 1;
92 if ( str[end] == 'u' || str[end] == 'U' ) str.erase( end ); // ends with 'uU' ? remove
93 } else if ( fix != '\0' ) str += fix; // put 'uU' back if removed
94} // lnthSuffix
95
96void valueToType( unsigned long long int & v, bool dec, int & type, bool & Unsigned ) {
97 // use value to determine type
98 if ( v <= INT_MAX ) { // signed int
99 type = 2;
100 } else if ( v <= UINT_MAX && ! dec ) { // unsigned int
101 type = 2;
102 Unsigned = true; // unsigned
103 } else if ( v <= LONG_MAX ) { // signed long int
104 type = 3;
105 } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int
106 type = 3;
107 Unsigned = true; // unsigned long int
108 } else if ( v <= LLONG_MAX ) { // signed long long int
109 type = 4;
110 } else { // unsigned long long int
111 type = 4;
112 Unsigned = true; // unsigned long long int
113 } // if
114} // valueToType
115
116static void scanbin( string & str, unsigned long long int & v ) {
117 v = 0;
118 size_t last = str.length() - 1; // last subscript of constant
119 for ( unsigned int i = 2;; ) { // ignore prefix
120 if ( str[i] == '1' ) v |= 1;
121 i += 1;
122 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
123 v <<= 1;
124 } // for
125} // scanbin
126
127ast::Expr * build_constantInteger(
128 const CodeLocation & location, string & str ) {
129 static const ast::BasicKind kind[2][6] = {
130 // short (h) must be before char (hh) because shorter type has the longer suffix
131 { ast::BasicKind::ShortSignedInt, ast::BasicKind::SignedChar, ast::BasicKind::SignedInt, ast::BasicKind::LongSignedInt, ast::BasicKind::LongLongSignedInt, /* BasicKind::SignedInt128 */ ast::BasicKind::LongLongSignedInt, },
132 { ast::BasicKind::ShortUnsignedInt, ast::BasicKind::UnsignedChar, ast::BasicKind::UnsignedInt, ast::BasicKind::LongUnsignedInt, ast::BasicKind::LongLongUnsignedInt, /* BasicKind::UnsignedInt128 */ ast::BasicKind::LongLongUnsignedInt, },
133 };
134
135 static const char * lnthsInt[2][6] = {
136 { "int16_t", "int8_t", "int32_t", "int64_t", "size_t", "uintptr_t", },
137 { "uint16_t", "uint8_t", "uint32_t", "uint64_t", "size_t", "uintptr_t", },
138 }; // lnthsInt
139
140 string str2( "0x0" );
141 unsigned long long int v, v2 = 0; // converted integral value
142 ast::Expr * ret, * ret2;
143
144 int type = -1; // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
145 int ltype = -1; // 0 => 16 bits, 1 => 8 bits, 2 => 32 bits, 3 => 64 bits, 4 => size_t, 5 => intptr, 6 => pointer
146 bool dec = true, Unsigned = false; // decimal, unsigned constant
147
148 // special constants
149 if ( str == "0" ) {
150 ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0 );
151 goto CLEANUP;
152 } // if
153 if ( str == "1" ) {
154 ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1 );
155 goto CLEANUP;
156 } // if
157
158 // 'u' can appear before or after length suffix
159 if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
160
161 if ( isdigit( str[str.length() - 1] ) ) { // no suffix ?
162 lnthSuffix( str, type, ltype ); // could have length suffix
163 } else {
164 // At least one digit in integer constant, so safe to backup while looking for suffix.
165 // This declaration and the comma expressions in the conditions mimic
166 // the declare and check pattern allowed in later compiler versions.
167 // (Only some early compilers/C++ standards do not support it.)
168 string::size_type posn;
169 // pointer value
170 if ( posn = str.find_last_of( "pP" ), posn != string::npos ) {
171 ltype = 5; str.erase( posn, 1 );
172 // size_t
173 } else if ( posn = str.find_last_of( "zZ" ), posn != string::npos ) {
174 Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 );
175 // signed char
176 } else if ( posn = str.rfind( "hh" ), posn != string::npos ) {
177 type = 1; str.erase( posn, 2 );
178 // signed char
179 } else if ( posn = str.rfind( "HH" ), posn != string::npos ) {
180 type = 1; str.erase( posn, 2 );
181 // short
182 } else if ( posn = str.find_last_of( "hH" ), posn != string::npos ) {
183 type = 0; str.erase( posn, 1 );
184 // int (natural number)
185 } else if ( posn = str.find_last_of( "nN" ), posn != string::npos ) {
186 type = 2; str.erase( posn, 1 );
187 } else if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) {
188 type = 4;
189 } else {
190 lnthSuffix( str, type, ltype );
191 } // if
192 } // if
193
194 // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
195
196#if ! defined(__SIZEOF_INT128__)
197 if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target \"%s\"", str.c_str() );
198#endif // ! __SIZEOF_INT128__
199
200 if ( str[0] == '0' ) { // radix character ?
201 dec = false;
202 if ( checkX( str[1] ) ) { // hex constant ?
203 if ( type < 5 ) { // not L128 ?
204 sscanf( (char *)str.c_str(), "%llx", &v );
205#if defined(__SIZEOF_INT128__)
206 } else { // hex int128 constant
207 unsigned int len = str.length();
208 if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large \"%s\"", str.c_str() );
209 // hex digits < 2^64
210 if ( len > (2 + 16) ) {
211 str2 = "0x" + str.substr( len - 16 );
212 sscanf( (char *)str2.c_str(), "%llx", &v2 );
213 str = str.substr( 0, len - 16 );
214 } // if
215 sscanf( (char *)str.c_str(), "%llx", &v );
216#endif // __SIZEOF_INT128__
217 } // if
218 //printf( "%llx %llu\n", v, v );
219 } else if ( checkB( str[1] ) ) { // binary constant ?
220#if defined(__SIZEOF_INT128__)
221 unsigned int len = str.length();
222 if ( type == 5 && len > 2 + 64 ) {
223 if ( len > 2 + 64 + 64 ) SemanticError( yylloc, "128-bit binary constant to large \"%s\".", str.c_str() );
224 str2 = "0b" + str.substr( len - 64 );
225 str = str.substr( 0, len - 64 );
226 scanbin( str2, v2 );
227 } // if
228#endif // __SIZEOF_INT128__
229 scanbin( str, v );
230 //printf( "%#llx %llu\n", v, v );
231 } else { // octal constant
232 if ( type < 5 ) { // not L128 ?
233 sscanf( (char *)str.c_str(), "%llo", &v );
234#if defined(__SIZEOF_INT128__)
235 } else { // octal int128 constant
236 unsigned int len = str.length();
237 if ( len > 1 + 43 || (len == 1 + 43 && str[0] > '3') ) SemanticError( yylloc, "128-bit octal constant to large \"%s\"", str.c_str() );
238 char buf[32];
239 if ( len <= 1 + 21 ) { // value < 21 octal digitis
240 sscanf( (char *)str.c_str(), "%llo", &v );
241 } else {
242 sscanf( &str[len - 21], "%llo", &v );
243 __int128 val = v; // accumulate bits
244 str[len - 21] ='\0'; // shorten string
245 sscanf( &str[len == 43 ? 1 : 0], "%llo", &v );
246 val |= (__int128)v << 63; // store bits
247 if ( len == 1 + 43 ) { // most significant 2 bits ?
248 str[2] = '\0'; // shorten string
249 sscanf( &str[1], "%llo", &v ); // process most significant 2 bits
250 val |= (__int128)v << 126; // store bits
251 } // if
252 v = val >> 64; v2 = (uint64_t)val; // replace octal constant with 2 hex constants
253 sprintf( buf, "%#llx", v2 );
254 str2 = buf;
255 } // if
256 sprintf( buf, "%#llx", v );
257 str = buf;
258#endif // __SIZEOF_INT128__
259 } // if
260 //printf( "%#llo %llu\n", v, v );
261 } // if
262 } else { // decimal constant ?
263 if ( type < 5 ) { // not L128 ?
264 sscanf( (char *)str.c_str(), "%llu", &v );
265#if defined(__SIZEOF_INT128__)
266 } else { // decimal int128 constant
267 #define P10_UINT64 10'000'000'000'000'000'000ULL // 19 zeroes
268 unsigned int len = str.length();
269 if ( str.length() == 39 && str > (Unsigned ? "340282366920938463463374607431768211455" : "170141183460469231731687303715884105727") )
270 SemanticError( yylloc, "128-bit decimal constant to large \"%s\".", str.c_str() );
271 char buf[32];
272 if ( len <= 19 ) { // value < 19 decimal digitis
273 sscanf( (char *)str.c_str(), "%llu", &v );
274 } else {
275 sscanf( &str[len - 19], "%llu", &v );
276 __int128 val = v; // accumulate bits
277 str[len - 19] ='\0'; // shorten string
278 sscanf( &str[len == 39 ? 1 : 0], "%llu", &v );
279 val += (__int128)v * (__int128)P10_UINT64; // store bits
280 if ( len == 39 ) { // most significant 2 bits ?
281 str[1] = '\0'; // shorten string
282 sscanf( &str[0], "%llu", &v ); // process most significant 2 bits
283 val += (__int128)v * (__int128)P10_UINT64 * (__int128)P10_UINT64; // store bits
284 } // if
285 v = val >> 64; v2 = (uint64_t)val; // replace decimal constant with 2 hex constants
286 sprintf( buf, "%#llx", v2 );
287 str2 = buf;
288 } // if
289 sprintf( buf, "%#llx", v );
290 str = buf;
291#endif // __SIZEOF_INT128__
292 } // if
293 //printf( "%llu\n", v );
294 } // if
295
296 if ( type == -1 ) { // no suffix => determine type from value size
297 valueToType( v, dec, type, Unsigned );
298 } // if
299 /* printf( "%s %llo %s %llo\n", str.c_str(), v, str2.c_str(), v2 ); */
300
301 //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
302 assert( 0 <= type && type <= 6 );
303
304 // Constant type is correct for overload resolving.
305 ret = new ast::ConstantExpr( location,
306 new ast::BasicType( kind[Unsigned][type] ), str, v );
307 if ( Unsigned && type < 2 ) { // hh or h, less than int ?
308 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
309 ret = new ast::CastExpr( location,
310 ret,
311 new ast::BasicType( kind[Unsigned][type] ),
312 ast::ExplicitCast );
313 } else if ( ltype != -1 ) { // explicit length ?
314 if ( ltype == 6 ) { // int128, (int128)constant
315 ret2 = new ast::ConstantExpr( location,
316 new ast::BasicType( ast::BasicKind::LongLongSignedInt ),
317 str2,
318 v2 );
319 ret = build_compoundLiteral( location,
320 DeclarationNode::newFromTypeData(
321 addType(
322 build_basic_type( TypeData::Int128 ),
323 build_signedness( TypeData::Unsigned ) ) ),
324 new InitializerNode(
325 (new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true )
326 );
327 } else { // explicit length, (length_type)constant
328 ret = new ast::CastExpr( location,
329 ret,
330 new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ),
331 ast::ExplicitCast );
332 if ( ltype == 5 ) { // pointer, intptr( (uintptr_t)constant )
333 ret = build_func( location,
334 new ExpressionNode(
335 build_varref( location, new string( "intptr" ) ) ),
336 new ExpressionNode( ret ) );
337 } // if
338 } // if
339 } // if
340
341 CLEANUP: ;
342 delete &str; // created by lex
343 return ret;
344} // build_constantInteger
345
346
347static inline void checkFnxFloat( string & str, size_t last, bool & explnth, int & type ) {
348 string::size_type posn;
349 // floating-point constant has minimum of 2 characters, 1. or .1, so safe to look ahead
350 if ( str[1] == 'x' ) { // hex ?
351 posn = str.find_last_of( "pP" ); // back for exponent (must have)
352 posn = str.find_first_of( "fF", posn + 1 ); // forward for size (fF allowed in hex constant)
353 } else {
354 posn = str.find_last_of( "fF" ); // back for size (fF not allowed)
355 } // if
356 if ( posn == string::npos ) return;
357 explnth = true;
358 posn += 1; // advance to size
359 if ( str[posn] == '3' ) { // 32
360 if ( str[last] != 'x' ) type = 6;
361 else type = 7;
362 } else if ( str[posn] == '6' ) { // 64
363 if ( str[last] != 'x' ) type = 8;
364 else type = 9;
365 } else if ( str[posn] == '8' ) { // 80
366 type = 3;
367 } else if ( str[posn] == '1' ) { // 16/128
368 if ( str[posn + 1] == '6' ) { // 16
369 type = 5;
370 } else { // 128
371 if ( str[last] != 'x' ) type = 10;
372 else type = 11;
373 } // if
374 } else {
375 assertf( false, "internal error, bad floating point length %s", str.c_str() );
376 } // if
377} // checkFnxFloat
378
379
380ast::Expr * build_constantFloat(
381 const CodeLocation & location, string & str ) {
382 static const ast::BasicKind kind[2][12] = {
383 { ast::BasicKind::Float, ast::BasicKind::Double, ast::BasicKind::LongDouble, ast::BasicKind::uuFloat80, ast::BasicKind::uuFloat128, ast::BasicKind::uFloat16, ast::BasicKind::uFloat32, ast::BasicKind::uFloat32x, ast::BasicKind::uFloat64, ast::BasicKind::uFloat64x, ast::BasicKind::uFloat128, ast::BasicKind::uFloat128x },
384 { ast::BasicKind::FloatComplex, ast::BasicKind::DoubleComplex, ast::BasicKind::LongDoubleComplex, ast::BasicKind::NUMBER_OF_BASIC_TYPES, ast::BasicKind::NUMBER_OF_BASIC_TYPES, ast::BasicKind::uFloat16Complex, ast::BasicKind::uFloat32Complex, ast::BasicKind::uFloat32xComplex, ast::BasicKind::uFloat64Complex, ast::BasicKind::uFloat64xComplex, ast::BasicKind::uFloat128Complex, ast::BasicKind::uFloat128xComplex },
385 };
386
387 // floating-point constant has minimum of 2 characters 1. or .1
388 size_t last = str.length() - 1;
389 double v;
390 int type; // 0 => float, 1 => double, 3 => long double, ...
391 bool complx = false; // real, complex
392 bool explnth = false; // explicit literal length
393
394 sscanf( str.c_str(), "%lg", &v );
395
396 if ( checkI( str[last] ) ) { // imaginary ?
397 complx = true;
398 last -= 1; // backup one character
399 } // if
400
401 if ( checkF( str[last] ) ) { // float ?
402 type = 0;
403 } else if ( checkD( str[last] ) ) { // double ?
404 type = 1;
405 } else if ( checkL( str[last] ) ) { // long double ?
406 type = 2;
407 } else if ( checkF80( str[last] ) ) { // __float80 ?
408 type = 3;
409 } else if ( checkF128( str[last] ) ) { // __float128 ?
410 type = 4;
411 } else {
412 type = 1; // double (default if no suffix)
413 checkFnxFloat( str, last, explnth, type );
414 } // if
415
416 if ( ! complx && checkI( str[last - 1] ) ) { // imaginary ?
417 complx = true;
418 } // if
419
420 assert( 0 <= type && type < 12 );
421 ast::Expr * ret = new ast::ConstantExpr( location,
422 new ast::BasicType( kind[complx][type] ),
423 str,
424 v );
425 // explicit length ?
426 if ( explnth ) {
427 ret = new ast::CastExpr( location,
428 ret,
429 new ast::BasicType( kind[complx][type] ),
430 ast::ExplicitCast );
431 } // if
432
433 delete &str; // created by lex
434 return ret;
435} // build_constantFloat
436
437static void sepString( string & str, string & units, char delimit ) {
438 string::size_type posn = str.find_last_of( delimit ) + 1;
439 if ( posn != str.length() ) {
440 units = "?" + str.substr( posn ); // extract units
441 str.erase( posn ); // remove units
442 } // if
443} // sepString
444
445ast::Expr * build_constantChar( const CodeLocation & location, string & str ) {
446 string units; // units
447 sepString( str, units, '\'' ); // separate constant from units
448
449 ast::Expr * ret = new ast::ConstantExpr( location,
450 new ast::BasicType( ast::BasicKind::Char ),
451 str,
452 (unsigned long long int)(unsigned char)str[1] );
453 if ( units.length() != 0 ) {
454 ret = new ast::UntypedExpr( location,
455 new ast::NameExpr( location, units ),
456 { ret } );
457 } // if
458
459 delete &str; // created by lex
460 return ret;
461} // build_constantChar
462
463static bool isoctal( char ch ) {
464 return ('0' <= ch && ch <= '7');
465}
466
467static bool ishexadecimal( char ch ) {
468 return (('0' <= ch && ch <= '9')
469 || ('a' <= ch && ch <= 'f')
470 || ('A' <= ch && ch <= 'F'));
471}
472
473// A "sequence" is the series of characters in a character/string literal
474// that becomes a single character value in the runtime value.
475static size_t sequenceLength( const std::string & str, size_t pos ) {
476 // Most "sequences" are just a single character, filter those out:
477 if ( '\\' != str[pos] ) return 1;
478 switch ( str[pos + 1] ) {
479 // Simple Escape Sequence (\_ where _ is one of the following):
480 case '\'': case '\"': case '?': case '\\':
481 case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
482 // GCC Escape Sequence (as simple, just some different letters):
483 case 'e':
484 return 2;
485 // Numeric Escape Sequence (\___ where _ is 1-3 octal digits):
486 case '0': case '1': case '2': case '3':
487 case '4': case '5': case '6': case '7':
488 return ( !isoctal( str[pos + 2] ) ) ? 2 :
489 ( !isoctal( str[pos + 3] ) ) ? 3 : 4;
490 // Numeric Escape Sequence (\x_ where _ is 1 or more hexadecimal digits):
491 case 'x': {
492 size_t length = 2;
493 while ( ishexadecimal( str[pos + length] ) ) ++length;
494 return length;
495 }
496 // Uniersal Character Name (\u____ where _ is 4 decimal digits):
497 case 'u':
498 return 6;
499 // Uniersal Character Name (\U________ where _ is 8 decimal digits):
500 case 'U':
501 return 10;
502 default:
503 assertf( false, "Unknown escape sequence (start %c).", str[pos] );
504 return 1;
505 }
506}
507
508ast::Expr * build_constantStr(
509 const CodeLocation & location,
510 string & str ) {
511 assert( str.length() > 0 );
512 string units; // units
513 sepString( str, units, '"' ); // separate constant from units
514
515 ast::Type * strtype;
516 switch ( str[0] ) { // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1
517 case 'u':
518 if ( str[1] == '8' ) goto Default; // utf-8 characters => array of char
519 // lookup type of associated typedef
520 strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype );
521 break;
522 case 'U':
523 strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype );
524 break;
525 case 'L':
526 strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype );
527 break;
528 Default: // char default string type
529 default:
530 strtype = new ast::BasicType( ast::BasicKind::Char );
531 } // switch
532
533 // The dimension value of the type is equal to the number of "sequences"
534 // not including the openning and closing quotes in the literal plus 1
535 // for the implicit null terminator.
536 size_t dimension = 1;
537 for ( size_t pos = 1 ; pos < str.size() - 1 ;
538 pos += sequenceLength( str, pos ) ) {
539 dimension += 1;
540 }
541
542 ast::ArrayType * at = new ast::ArrayType(
543 strtype,
544 ast::ConstantExpr::from_ulong( location, dimension ),
545 ast::FixedLen,
546 ast::DynamicDim );
547 ast::Expr * ret = new ast::ConstantExpr( location, at, str, std::nullopt );
548 if ( units.length() != 0 ) {
549 ret = new ast::UntypedExpr( location,
550 new ast::NameExpr( location, units ),
551 { ret } );
552 } // if
553
554 delete &str; // created by lex
555 return ret;
556} // build_constantStr
557
558ast::Expr * build_field_name_FLOATING_FRACTIONconstant(
559 const CodeLocation & location, const string & str ) {
560 if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index \"%s\".", str.c_str() );
561 ast::Expr * ret = build_constantInteger( location,
562 *new string( str.substr(1) ) );
563 delete &str;
564 return ret;
565} // build_field_name_FLOATING_FRACTIONconstant
566
567ast::Expr * build_field_name_FLOATING_DECIMALconstant(
568 const CodeLocation & location, const string & str ) {
569 if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index \"%s\".", str.c_str() );
570 ast::Expr * ret = build_constantInteger(
571 location, *new string( str.substr( 0, str.size()-1 ) ) );
572 delete &str;
573 return ret;
574} // build_field_name_FLOATING_DECIMALconstant
575
576ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location,
577 const string & str ) {
578 // str is of the form A.B -> separate at the . and return member expression
579 int a, b;
580 char dot;
581 stringstream ss( str );
582 ss >> a >> dot >> b;
583 auto ret = new ast::UntypedMemberExpr( location,
584 ast::ConstantExpr::from_int( location, b ),
585 ast::ConstantExpr::from_int( location, a )
586 );
587 delete &str;
588 return ret;
589} // build_field_name_FLOATINGconstant
590
591ast::Expr * make_field_name_fraction_constants( const CodeLocation & location,
592 ast::Expr * fieldName,
593 ast::Expr * fracts ) {
594 if ( nullptr == fracts ) {
595 return fieldName;
596 } else if ( auto memberExpr = dynamic_cast<ast::UntypedMemberExpr *>( fracts ) ) {
597 memberExpr->member = make_field_name_fraction_constants( location,
598 fieldName,
599 ast::mutate( memberExpr->aggregate.get() ) );
600 return memberExpr;
601 } else {
602 return new ast::UntypedMemberExpr( location, fracts, fieldName );
603 } // if
604} // make_field_name_fraction_constants
605
606ast::Expr * build_field_name_fraction_constants( const CodeLocation & location,
607 ast::Expr * fieldName,
608 ExpressionNode * fracts ) {
609 return make_field_name_fraction_constants( location, fieldName, maybeMoveBuild( fracts ) );
610} // build_field_name_fraction_constants
611
612ast::NameExpr * build_varref( const CodeLocation & location,
613 const string * name ) {
614 ast::NameExpr * expr = new ast::NameExpr( location, *name );
615 delete name;
616 return expr;
617} // build_varref
618
619ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
620 const DeclarationNode * decl_node,
621 const ast::NameExpr * name ) {
622 ast::Decl * newDecl = maybeBuild( decl_node );
623 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
624 if ( const ast::Type * t = newDeclWithType->get_type() ) {
625 if ( auto typeInst = dynamic_cast<const ast::TypeInstType *>( t ) ) {
626 newDecl = new ast::EnumDecl( location, typeInst->name );
627 }
628 }
629 }
630 return new ast::QualifiedNameExpr( location, newDecl, name->name );
631}
632
633ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
634 const ast::EnumDecl * decl,
635 const ast::NameExpr * name ) {
636 return new ast::QualifiedNameExpr( location, decl, name->name );
637}
638
639ast::DimensionExpr * build_dimensionref( const CodeLocation & location,
640 const string * name ) {
641 ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name );
642 delete name;
643 return expr;
644} // build_varref
645
646// TODO: get rid of this and OperKinds and reuse code from OperatorTable
647static const char * OperName[] = { // must harmonize with OperKinds
648 // diadic
649 "SizeOf", "AlignOf", "OffsetOf", "?+?", "?-?", "?\\?", "?*?", "?/?", "?%?", "||", "&&",
650 "?|?", "?&?", "?^?", "Cast", "?<<?", "?>>?", "?<?", "?>?", "?<=?", "?>=?", "?==?", "?!=?",
651 "?=?", "?@=?", "?\\=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?",
652 "?[?]", "...",
653 // monadic
654 "+?", "-?", "AddressOf", "*?", "!?", "~?", "++?", "?++", "--?", "?--",
655}; // OperName
656
657ast::Expr * build_cast( const CodeLocation & location,
658 DeclarationNode * decl_node,
659 ExpressionNode * expr_node,
660 ast::CastExpr::CastKind kind ) {
661 ast::Type * targetType = maybeMoveBuildType( decl_node );
662 if ( dynamic_cast<ast::VoidType *>( targetType ) ) {
663 delete targetType;
664 return new ast::CastExpr( location,
665 maybeMoveBuild( expr_node ),
666 ast::ExplicitCast, kind );
667 } else {
668 return new ast::CastExpr( location,
669 maybeMoveBuild( expr_node ),
670 targetType,
671 ast::ExplicitCast, kind );
672 } // if
673} // build_cast
674
675ast::Expr * build_keyword_cast( const CodeLocation & location,
676 ast::AggregateDecl::Aggregate target,
677 ExpressionNode * expr_node ) {
678 return new ast::KeywordCastExpr( location,
679 maybeMoveBuild( expr_node ),
680 target
681 );
682}
683
684ast::Expr * build_virtual_cast( const CodeLocation & location,
685 DeclarationNode * decl_node,
686 ExpressionNode * expr_node ) {
687 return new ast::VirtualCastExpr( location,
688 maybeMoveBuild( expr_node ),
689 maybeMoveBuildType( decl_node )
690 );
691} // build_virtual_cast
692
693ast::Expr * build_fieldSel( const CodeLocation & location,
694 ExpressionNode * expr_node,
695 ast::Expr * member ) {
696 return new ast::UntypedMemberExpr( location,
697 member,
698 maybeMoveBuild( expr_node )
699 );
700} // build_fieldSel
701
702ast::Expr * build_pfieldSel( const CodeLocation & location,
703 ExpressionNode * expr_node,
704 ast::Expr * member ) {
705 auto deref = new ast::UntypedExpr( location,
706 new ast::NameExpr( location, "*?" )
707 );
708 deref->location = expr_node->location;
709 deref->args.push_back( maybeMoveBuild( expr_node ) );
710 auto ret = new ast::UntypedMemberExpr( location, member, deref );
711 return ret;
712} // build_pfieldSel
713
714ast::Expr * build_offsetOf( const CodeLocation & location,
715 DeclarationNode * decl_node,
716 ast::NameExpr * member ) {
717 ast::Expr * ret = new ast::UntypedOffsetofExpr( location,
718 maybeMoveBuildType( decl_node ),
719 member->name
720 );
721 ret->result = new ast::BasicType( ast::BasicKind::LongUnsignedInt );
722 delete member;
723 return ret;
724} // build_offsetOf
725
726ast::Expr * build_and_or( const CodeLocation & location,
727 ExpressionNode * expr_node1,
728 ExpressionNode * expr_node2,
729 ast::LogicalFlag flag ) {
730 return new ast::LogicalExpr( location,
731 maybeMoveBuild( expr_node1 ),
732 maybeMoveBuild( expr_node2 ),
733 flag
734 );
735} // build_and_or
736
737ast::Expr * build_unary_val( const CodeLocation & location,
738 OperKinds op,
739 ExpressionNode * expr_node ) {
740 std::vector<ast::ptr<ast::Expr>> args;
741 args.push_back( maybeMoveBuild( expr_node ) );
742 return new ast::UntypedExpr( location,
743 new ast::NameExpr( location, OperName[ (int)op ] ),
744 std::move( args )
745 );
746} // build_unary_val
747
748ast::Expr * build_binary_val( const CodeLocation & location,
749 OperKinds op,
750 ExpressionNode * expr_node1,
751 ExpressionNode * expr_node2 ) {
752 std::vector<ast::ptr<ast::Expr>> args;
753 args.push_back( maybeMoveBuild( expr_node1 ) );
754 args.push_back( maybeMoveBuild( expr_node2 ) );
755 return new ast::UntypedExpr( location,
756 new ast::NameExpr( location, OperName[ (int)op ] ),
757 std::move( args )
758 );
759} // build_binary_val
760
761ast::Expr * build_cond( const CodeLocation & location,
762 ExpressionNode * expr_node1,
763 ExpressionNode * expr_node2,
764 ExpressionNode * expr_node3 ) {
765 return new ast::ConditionalExpr( location,
766 maybeMoveBuild( expr_node1 ),
767 maybeMoveBuild( expr_node2 ),
768 maybeMoveBuild( expr_node3 )
769 );
770} // build_cond
771
772ast::Expr * build_tuple( const CodeLocation & location,
773 ExpressionNode * expr_node ) {
774 std::vector<ast::ptr<ast::Expr>> exprs;
775 buildMoveList( expr_node, exprs );
776 return new ast::UntypedTupleExpr( location, std::move( exprs ) );
777} // build_tuple
778
779ast::Expr * build_func( const CodeLocation & location,
780 ExpressionNode * function,
781 ExpressionNode * expr_node ) {
782 std::vector<ast::ptr<ast::Expr>> args;
783 buildMoveList( expr_node, args );
784 return new ast::UntypedExpr( location,
785 maybeMoveBuild( function ),
786 std::move( args )
787 );
788} // build_func
789
790ast::Expr * build_compoundLiteral( const CodeLocation & location,
791 DeclarationNode * decl_node,
792 InitializerNode * kids ) {
793 // compound literal type
794 ast::Decl * newDecl = maybeBuild( decl_node );
795 // non-sue compound-literal type
796 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
797 return new ast::CompoundLiteralExpr( location,
798 newDeclWithType->get_type(),
799 maybeMoveBuild( kids ) );
800 // these types do not have associated type information
801 } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) {
802 if ( newDeclStructDecl->body ) {
803 return new ast::CompoundLiteralExpr( location,
804 new ast::StructInstType( newDeclStructDecl ),
805 maybeMoveBuild( kids ) );
806 } else {
807 return new ast::CompoundLiteralExpr( location,
808 new ast::StructInstType( newDeclStructDecl->name ),
809 maybeMoveBuild( kids ) );
810 } // if
811 } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl ) ) {
812 if ( newDeclUnionDecl->body ) {
813 return new ast::CompoundLiteralExpr( location,
814 new ast::UnionInstType( newDeclUnionDecl ),
815 maybeMoveBuild( kids ) );
816 } else {
817 return new ast::CompoundLiteralExpr( location,
818 new ast::UnionInstType( newDeclUnionDecl->name ),
819 maybeMoveBuild( kids ) );
820 } // if
821 } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl ) ) {
822 if ( newDeclEnumDecl->body ) {
823 return new ast::CompoundLiteralExpr( location,
824 new ast::EnumInstType( newDeclEnumDecl ),
825 maybeMoveBuild( kids ) );
826 } else {
827 return new ast::CompoundLiteralExpr( location,
828 new ast::EnumInstType( newDeclEnumDecl->name ),
829 maybeMoveBuild( kids ) );
830 } // if
831 } else {
832 assert( false );
833 } // if
834} // build_compoundLiteral
835
836ast::Expr * build_va_arg( const CodeLocation & location,
837 ExpressionNode * function, DeclarationNode * declaration ) {
838 return build_func( location,
839 new ExpressionNode(
840 build_varref( location, new std::string( "__builtin_va_arg" ) ) ),
841 function->set_last( new ExpressionNode( new ast::TypeExpr( location,
842 maybeMoveBuildType( declaration ) ) ) )
843 );
844}
845
846// Local Variables: //
847// tab-width: 4 //
848// End: //
Note: See TracBrowser for help on using the repository browser.