mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
Support C++11/14 features: nullptr, decltype, unicode literals, custom literals, alignof
This commit is contained in:
parent
a43d6a45c1
commit
b65ad853fe
File diff suppressed because it is too large
Load Diff
@ -49,216 +49,234 @@ extern int cppyydebug;
|
||||
REAL = 258,
|
||||
INTEGER = 259,
|
||||
CHAR_TOK = 260,
|
||||
STRING = 261,
|
||||
SIMPLE_STRING = 261,
|
||||
SIMPLE_IDENTIFIER = 262,
|
||||
IDENTIFIER = 263,
|
||||
TYPENAME_IDENTIFIER = 264,
|
||||
SCOPING = 265,
|
||||
TYPEDEFNAME = 266,
|
||||
ELLIPSIS = 267,
|
||||
OROR = 268,
|
||||
ANDAND = 269,
|
||||
EQCOMPARE = 270,
|
||||
NECOMPARE = 271,
|
||||
LECOMPARE = 272,
|
||||
GECOMPARE = 273,
|
||||
LSHIFT = 274,
|
||||
RSHIFT = 275,
|
||||
POINTSAT_STAR = 276,
|
||||
DOT_STAR = 277,
|
||||
UNARY = 278,
|
||||
UNARY_NOT = 279,
|
||||
UNARY_NEGATE = 280,
|
||||
UNARY_MINUS = 281,
|
||||
UNARY_STAR = 282,
|
||||
UNARY_REF = 283,
|
||||
POINTSAT = 284,
|
||||
SCOPE = 285,
|
||||
PLUSPLUS = 286,
|
||||
MINUSMINUS = 287,
|
||||
TIMESEQUAL = 288,
|
||||
DIVIDEEQUAL = 289,
|
||||
MODEQUAL = 290,
|
||||
PLUSEQUAL = 291,
|
||||
MINUSEQUAL = 292,
|
||||
OREQUAL = 293,
|
||||
ANDEQUAL = 294,
|
||||
XOREQUAL = 295,
|
||||
LSHIFTEQUAL = 296,
|
||||
RSHIFTEQUAL = 297,
|
||||
KW_BEGIN_PUBLISH = 298,
|
||||
KW_BLOCKING = 299,
|
||||
KW_BOOL = 300,
|
||||
KW_CATCH = 301,
|
||||
KW_CHAR = 302,
|
||||
KW_CHAR16_T = 303,
|
||||
KW_CHAR32_T = 304,
|
||||
KW_CLASS = 305,
|
||||
KW_CONST = 306,
|
||||
KW_DELETE = 307,
|
||||
KW_DOUBLE = 308,
|
||||
KW_DYNAMIC_CAST = 309,
|
||||
KW_ELSE = 310,
|
||||
KW_END_PUBLISH = 311,
|
||||
KW_ENUM = 312,
|
||||
KW_EXTENSION = 313,
|
||||
KW_EXTERN = 314,
|
||||
KW_EXPLICIT = 315,
|
||||
KW_PUBLISHED = 316,
|
||||
KW_FALSE = 317,
|
||||
KW_FLOAT = 318,
|
||||
KW_FRIEND = 319,
|
||||
KW_FOR = 320,
|
||||
KW_GOTO = 321,
|
||||
KW_IF = 322,
|
||||
KW_INLINE = 323,
|
||||
KW_INT = 324,
|
||||
KW_LONG = 325,
|
||||
KW_LONGLONG = 326,
|
||||
KW_MAKE_PROPERTY = 327,
|
||||
KW_MAKE_SEQ = 328,
|
||||
KW_MUTABLE = 329,
|
||||
KW_NAMESPACE = 330,
|
||||
KW_NEW = 331,
|
||||
KW_NOEXCEPT = 332,
|
||||
KW_OPERATOR = 333,
|
||||
KW_PRIVATE = 334,
|
||||
KW_PROTECTED = 335,
|
||||
KW_PUBLIC = 336,
|
||||
KW_REGISTER = 337,
|
||||
KW_RETURN = 338,
|
||||
KW_SHORT = 339,
|
||||
KW_SIGNED = 340,
|
||||
KW_SIZEOF = 341,
|
||||
KW_STATIC = 342,
|
||||
KW_STATIC_ASSERT = 343,
|
||||
KW_STATIC_CAST = 344,
|
||||
KW_STRUCT = 345,
|
||||
KW_TEMPLATE = 346,
|
||||
KW_THROW = 347,
|
||||
KW_TRUE = 348,
|
||||
KW_TRY = 349,
|
||||
KW_TYPEDEF = 350,
|
||||
KW_TYPENAME = 351,
|
||||
KW_UNION = 352,
|
||||
KW_UNSIGNED = 353,
|
||||
KW_USING = 354,
|
||||
KW_VIRTUAL = 355,
|
||||
KW_VOID = 356,
|
||||
KW_VOLATILE = 357,
|
||||
KW_WCHAR_T = 358,
|
||||
KW_WHILE = 359,
|
||||
START_CPP = 360,
|
||||
START_CONST_EXPR = 361,
|
||||
START_TYPE = 362
|
||||
STRING_LITERAL = 263,
|
||||
CUSTOM_LITERAL = 264,
|
||||
IDENTIFIER = 265,
|
||||
TYPENAME_IDENTIFIER = 266,
|
||||
SCOPING = 267,
|
||||
TYPEDEFNAME = 268,
|
||||
ELLIPSIS = 269,
|
||||
OROR = 270,
|
||||
ANDAND = 271,
|
||||
EQCOMPARE = 272,
|
||||
NECOMPARE = 273,
|
||||
LECOMPARE = 274,
|
||||
GECOMPARE = 275,
|
||||
LSHIFT = 276,
|
||||
RSHIFT = 277,
|
||||
POINTSAT_STAR = 278,
|
||||
DOT_STAR = 279,
|
||||
UNARY = 280,
|
||||
UNARY_NOT = 281,
|
||||
UNARY_NEGATE = 282,
|
||||
UNARY_MINUS = 283,
|
||||
UNARY_STAR = 284,
|
||||
UNARY_REF = 285,
|
||||
POINTSAT = 286,
|
||||
SCOPE = 287,
|
||||
PLUSPLUS = 288,
|
||||
MINUSMINUS = 289,
|
||||
TIMESEQUAL = 290,
|
||||
DIVIDEEQUAL = 291,
|
||||
MODEQUAL = 292,
|
||||
PLUSEQUAL = 293,
|
||||
MINUSEQUAL = 294,
|
||||
OREQUAL = 295,
|
||||
ANDEQUAL = 296,
|
||||
XOREQUAL = 297,
|
||||
LSHIFTEQUAL = 298,
|
||||
RSHIFTEQUAL = 299,
|
||||
KW_ALIGNAS = 300,
|
||||
KW_ALIGNOF = 301,
|
||||
KW_AUTO = 302,
|
||||
KW_BEGIN_PUBLISH = 303,
|
||||
KW_BLOCKING = 304,
|
||||
KW_BOOL = 305,
|
||||
KW_CATCH = 306,
|
||||
KW_CHAR = 307,
|
||||
KW_CHAR16_T = 308,
|
||||
KW_CHAR32_T = 309,
|
||||
KW_CLASS = 310,
|
||||
KW_CONST = 311,
|
||||
KW_CONSTEXPR = 312,
|
||||
KW_DECLTYPE = 313,
|
||||
KW_DEFAULT = 314,
|
||||
KW_DELETE = 315,
|
||||
KW_DOUBLE = 316,
|
||||
KW_DYNAMIC_CAST = 317,
|
||||
KW_ELSE = 318,
|
||||
KW_END_PUBLISH = 319,
|
||||
KW_ENUM = 320,
|
||||
KW_EXTENSION = 321,
|
||||
KW_EXTERN = 322,
|
||||
KW_EXPLICIT = 323,
|
||||
KW_PUBLISHED = 324,
|
||||
KW_FALSE = 325,
|
||||
KW_FLOAT = 326,
|
||||
KW_FRIEND = 327,
|
||||
KW_FOR = 328,
|
||||
KW_GOTO = 329,
|
||||
KW_IF = 330,
|
||||
KW_INLINE = 331,
|
||||
KW_INT = 332,
|
||||
KW_LONG = 333,
|
||||
KW_LONGLONG = 334,
|
||||
KW_MAKE_PROPERTY = 335,
|
||||
KW_MAKE_SEQ = 336,
|
||||
KW_MUTABLE = 337,
|
||||
KW_NAMESPACE = 338,
|
||||
KW_NEW = 339,
|
||||
KW_NOEXCEPT = 340,
|
||||
KW_NULLPTR = 341,
|
||||
KW_OPERATOR = 342,
|
||||
KW_PRIVATE = 343,
|
||||
KW_PROTECTED = 344,
|
||||
KW_PUBLIC = 345,
|
||||
KW_REGISTER = 346,
|
||||
KW_RETURN = 347,
|
||||
KW_SHORT = 348,
|
||||
KW_SIGNED = 349,
|
||||
KW_SIZEOF = 350,
|
||||
KW_STATIC = 351,
|
||||
KW_STATIC_ASSERT = 352,
|
||||
KW_STATIC_CAST = 353,
|
||||
KW_STRUCT = 354,
|
||||
KW_TEMPLATE = 355,
|
||||
KW_THROW = 356,
|
||||
KW_TRUE = 357,
|
||||
KW_TRY = 358,
|
||||
KW_TYPEDEF = 359,
|
||||
KW_TYPENAME = 360,
|
||||
KW_UNION = 361,
|
||||
KW_UNSIGNED = 362,
|
||||
KW_USING = 363,
|
||||
KW_VIRTUAL = 364,
|
||||
KW_VOID = 365,
|
||||
KW_VOLATILE = 366,
|
||||
KW_WCHAR_T = 367,
|
||||
KW_WHILE = 368,
|
||||
START_CPP = 369,
|
||||
START_CONST_EXPR = 370,
|
||||
START_TYPE = 371
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define REAL 258
|
||||
#define INTEGER 259
|
||||
#define CHAR_TOK 260
|
||||
#define STRING 261
|
||||
#define SIMPLE_STRING 261
|
||||
#define SIMPLE_IDENTIFIER 262
|
||||
#define IDENTIFIER 263
|
||||
#define TYPENAME_IDENTIFIER 264
|
||||
#define SCOPING 265
|
||||
#define TYPEDEFNAME 266
|
||||
#define ELLIPSIS 267
|
||||
#define OROR 268
|
||||
#define ANDAND 269
|
||||
#define EQCOMPARE 270
|
||||
#define NECOMPARE 271
|
||||
#define LECOMPARE 272
|
||||
#define GECOMPARE 273
|
||||
#define LSHIFT 274
|
||||
#define RSHIFT 275
|
||||
#define POINTSAT_STAR 276
|
||||
#define DOT_STAR 277
|
||||
#define UNARY 278
|
||||
#define UNARY_NOT 279
|
||||
#define UNARY_NEGATE 280
|
||||
#define UNARY_MINUS 281
|
||||
#define UNARY_STAR 282
|
||||
#define UNARY_REF 283
|
||||
#define POINTSAT 284
|
||||
#define SCOPE 285
|
||||
#define PLUSPLUS 286
|
||||
#define MINUSMINUS 287
|
||||
#define TIMESEQUAL 288
|
||||
#define DIVIDEEQUAL 289
|
||||
#define MODEQUAL 290
|
||||
#define PLUSEQUAL 291
|
||||
#define MINUSEQUAL 292
|
||||
#define OREQUAL 293
|
||||
#define ANDEQUAL 294
|
||||
#define XOREQUAL 295
|
||||
#define LSHIFTEQUAL 296
|
||||
#define RSHIFTEQUAL 297
|
||||
#define KW_BEGIN_PUBLISH 298
|
||||
#define KW_BLOCKING 299
|
||||
#define KW_BOOL 300
|
||||
#define KW_CATCH 301
|
||||
#define KW_CHAR 302
|
||||
#define KW_CHAR16_T 303
|
||||
#define KW_CHAR32_T 304
|
||||
#define KW_CLASS 305
|
||||
#define KW_CONST 306
|
||||
#define KW_DELETE 307
|
||||
#define KW_DOUBLE 308
|
||||
#define KW_DYNAMIC_CAST 309
|
||||
#define KW_ELSE 310
|
||||
#define KW_END_PUBLISH 311
|
||||
#define KW_ENUM 312
|
||||
#define KW_EXTENSION 313
|
||||
#define KW_EXTERN 314
|
||||
#define KW_EXPLICIT 315
|
||||
#define KW_PUBLISHED 316
|
||||
#define KW_FALSE 317
|
||||
#define KW_FLOAT 318
|
||||
#define KW_FRIEND 319
|
||||
#define KW_FOR 320
|
||||
#define KW_GOTO 321
|
||||
#define KW_IF 322
|
||||
#define KW_INLINE 323
|
||||
#define KW_INT 324
|
||||
#define KW_LONG 325
|
||||
#define KW_LONGLONG 326
|
||||
#define KW_MAKE_PROPERTY 327
|
||||
#define KW_MAKE_SEQ 328
|
||||
#define KW_MUTABLE 329
|
||||
#define KW_NAMESPACE 330
|
||||
#define KW_NEW 331
|
||||
#define KW_NOEXCEPT 332
|
||||
#define KW_OPERATOR 333
|
||||
#define KW_PRIVATE 334
|
||||
#define KW_PROTECTED 335
|
||||
#define KW_PUBLIC 336
|
||||
#define KW_REGISTER 337
|
||||
#define KW_RETURN 338
|
||||
#define KW_SHORT 339
|
||||
#define KW_SIGNED 340
|
||||
#define KW_SIZEOF 341
|
||||
#define KW_STATIC 342
|
||||
#define KW_STATIC_ASSERT 343
|
||||
#define KW_STATIC_CAST 344
|
||||
#define KW_STRUCT 345
|
||||
#define KW_TEMPLATE 346
|
||||
#define KW_THROW 347
|
||||
#define KW_TRUE 348
|
||||
#define KW_TRY 349
|
||||
#define KW_TYPEDEF 350
|
||||
#define KW_TYPENAME 351
|
||||
#define KW_UNION 352
|
||||
#define KW_UNSIGNED 353
|
||||
#define KW_USING 354
|
||||
#define KW_VIRTUAL 355
|
||||
#define KW_VOID 356
|
||||
#define KW_VOLATILE 357
|
||||
#define KW_WCHAR_T 358
|
||||
#define KW_WHILE 359
|
||||
#define START_CPP 360
|
||||
#define START_CONST_EXPR 361
|
||||
#define START_TYPE 362
|
||||
#define STRING_LITERAL 263
|
||||
#define CUSTOM_LITERAL 264
|
||||
#define IDENTIFIER 265
|
||||
#define TYPENAME_IDENTIFIER 266
|
||||
#define SCOPING 267
|
||||
#define TYPEDEFNAME 268
|
||||
#define ELLIPSIS 269
|
||||
#define OROR 270
|
||||
#define ANDAND 271
|
||||
#define EQCOMPARE 272
|
||||
#define NECOMPARE 273
|
||||
#define LECOMPARE 274
|
||||
#define GECOMPARE 275
|
||||
#define LSHIFT 276
|
||||
#define RSHIFT 277
|
||||
#define POINTSAT_STAR 278
|
||||
#define DOT_STAR 279
|
||||
#define UNARY 280
|
||||
#define UNARY_NOT 281
|
||||
#define UNARY_NEGATE 282
|
||||
#define UNARY_MINUS 283
|
||||
#define UNARY_STAR 284
|
||||
#define UNARY_REF 285
|
||||
#define POINTSAT 286
|
||||
#define SCOPE 287
|
||||
#define PLUSPLUS 288
|
||||
#define MINUSMINUS 289
|
||||
#define TIMESEQUAL 290
|
||||
#define DIVIDEEQUAL 291
|
||||
#define MODEQUAL 292
|
||||
#define PLUSEQUAL 293
|
||||
#define MINUSEQUAL 294
|
||||
#define OREQUAL 295
|
||||
#define ANDEQUAL 296
|
||||
#define XOREQUAL 297
|
||||
#define LSHIFTEQUAL 298
|
||||
#define RSHIFTEQUAL 299
|
||||
#define KW_ALIGNAS 300
|
||||
#define KW_ALIGNOF 301
|
||||
#define KW_AUTO 302
|
||||
#define KW_BEGIN_PUBLISH 303
|
||||
#define KW_BLOCKING 304
|
||||
#define KW_BOOL 305
|
||||
#define KW_CATCH 306
|
||||
#define KW_CHAR 307
|
||||
#define KW_CHAR16_T 308
|
||||
#define KW_CHAR32_T 309
|
||||
#define KW_CLASS 310
|
||||
#define KW_CONST 311
|
||||
#define KW_CONSTEXPR 312
|
||||
#define KW_DECLTYPE 313
|
||||
#define KW_DEFAULT 314
|
||||
#define KW_DELETE 315
|
||||
#define KW_DOUBLE 316
|
||||
#define KW_DYNAMIC_CAST 317
|
||||
#define KW_ELSE 318
|
||||
#define KW_END_PUBLISH 319
|
||||
#define KW_ENUM 320
|
||||
#define KW_EXTENSION 321
|
||||
#define KW_EXTERN 322
|
||||
#define KW_EXPLICIT 323
|
||||
#define KW_PUBLISHED 324
|
||||
#define KW_FALSE 325
|
||||
#define KW_FLOAT 326
|
||||
#define KW_FRIEND 327
|
||||
#define KW_FOR 328
|
||||
#define KW_GOTO 329
|
||||
#define KW_IF 330
|
||||
#define KW_INLINE 331
|
||||
#define KW_INT 332
|
||||
#define KW_LONG 333
|
||||
#define KW_LONGLONG 334
|
||||
#define KW_MAKE_PROPERTY 335
|
||||
#define KW_MAKE_SEQ 336
|
||||
#define KW_MUTABLE 337
|
||||
#define KW_NAMESPACE 338
|
||||
#define KW_NEW 339
|
||||
#define KW_NOEXCEPT 340
|
||||
#define KW_NULLPTR 341
|
||||
#define KW_OPERATOR 342
|
||||
#define KW_PRIVATE 343
|
||||
#define KW_PROTECTED 344
|
||||
#define KW_PUBLIC 345
|
||||
#define KW_REGISTER 346
|
||||
#define KW_RETURN 347
|
||||
#define KW_SHORT 348
|
||||
#define KW_SIGNED 349
|
||||
#define KW_SIZEOF 350
|
||||
#define KW_STATIC 351
|
||||
#define KW_STATIC_ASSERT 352
|
||||
#define KW_STATIC_CAST 353
|
||||
#define KW_STRUCT 354
|
||||
#define KW_TEMPLATE 355
|
||||
#define KW_THROW 356
|
||||
#define KW_TRUE 357
|
||||
#define KW_TRY 358
|
||||
#define KW_TYPEDEF 359
|
||||
#define KW_TYPENAME 360
|
||||
#define KW_UNION 361
|
||||
#define KW_UNSIGNED 362
|
||||
#define KW_USING 363
|
||||
#define KW_VIRTUAL 364
|
||||
#define KW_VOID 365
|
||||
#define KW_VOLATILE 366
|
||||
#define KW_WCHAR_T 367
|
||||
#define KW_WHILE 368
|
||||
#define START_CPP 369
|
||||
#define START_CONST_EXPR 370
|
||||
#define START_TYPE 371
|
||||
|
||||
|
||||
|
||||
|
@ -209,7 +209,8 @@ pop_struct() {
|
||||
%token <u.real> REAL
|
||||
%token <u.integer> INTEGER
|
||||
%token <u.integer> CHAR_TOK
|
||||
%token <str> STRING SIMPLE_IDENTIFIER
|
||||
%token <str> SIMPLE_STRING SIMPLE_IDENTIFIER
|
||||
%token <u.expr> STRING_LITERAL CUSTOM_LITERAL
|
||||
%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER SCOPING
|
||||
%token <u.type> TYPEDEFNAME
|
||||
|
||||
@ -245,6 +246,9 @@ pop_struct() {
|
||||
%token LSHIFTEQUAL
|
||||
%token RSHIFTEQUAL
|
||||
|
||||
%token KW_ALIGNAS
|
||||
%token KW_ALIGNOF
|
||||
%token KW_AUTO
|
||||
%token KW_BEGIN_PUBLISH
|
||||
%token KW_BLOCKING
|
||||
%token KW_BOOL
|
||||
@ -254,6 +258,9 @@ pop_struct() {
|
||||
%token KW_CHAR32_T
|
||||
%token KW_CLASS
|
||||
%token KW_CONST
|
||||
%token KW_CONSTEXPR
|
||||
%token KW_DECLTYPE
|
||||
%token KW_DEFAULT
|
||||
%token KW_DELETE
|
||||
%token KW_DOUBLE
|
||||
%token KW_DYNAMIC_CAST
|
||||
@ -280,6 +287,7 @@ pop_struct() {
|
||||
%token KW_NAMESPACE
|
||||
%token KW_NEW
|
||||
%token KW_NOEXCEPT
|
||||
%token KW_NULLPTR
|
||||
%token KW_OPERATOR
|
||||
%token KW_PRIVATE
|
||||
%token KW_PROTECTED
|
||||
@ -348,7 +356,7 @@ pop_struct() {
|
||||
%type <u.type> enum_element_type
|
||||
/*%type <u.type> typedefname*/
|
||||
%type <u.identifier> name
|
||||
%type <str> string
|
||||
%type <u.expr> string_literal
|
||||
|
||||
/* We need to treat KW_OPERATOR as a scopable keyword. */
|
||||
%type <u.identifier> KW_OPERATOR
|
||||
@ -526,13 +534,15 @@ declaration:
|
||||
CPPMakeSeq *make_seq = new CPPMakeSeq($3->get_simple_name(), $5->get_simple_name(), $7->get_simple_name(), @1.file);
|
||||
current_scope->add_declaration(make_seq, global_scope, current_lexer, @1);
|
||||
}
|
||||
| KW_STATIC_ASSERT '(' const_expr ',' string ')'
|
||||
| KW_STATIC_ASSERT '(' const_expr ',' string_literal ')'
|
||||
{
|
||||
CPPExpression::Result result = $3->evaluate();
|
||||
if (result._type == CPPExpression::RT_error) {
|
||||
yywarning("static_assert requires a constant expression", @3);
|
||||
} else if (!result.as_boolean()) {
|
||||
yywarning("static_assert failed: " + $5, @3);
|
||||
stringstream str;
|
||||
str << *$5;
|
||||
yywarning("static_assert failed: " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
| KW_STATIC_ASSERT '(' const_expr ')'
|
||||
@ -571,7 +581,7 @@ storage_class:
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_extern;
|
||||
}
|
||||
| storage_class KW_EXTERN string
|
||||
| storage_class KW_EXTERN SIMPLE_STRING
|
||||
{
|
||||
$$ = $1 | (int)CPPInstance::SC_extern;
|
||||
if ($3 == "C") {
|
||||
@ -1266,6 +1276,21 @@ instance_identifier:
|
||||
ident->_names.push_back("operator "+$2);
|
||||
}
|
||||
|
||||
$$ = new CPPInstanceIdentifier(ident);
|
||||
}
|
||||
| KW_OPERATOR SIMPLE_STRING IDENTIFIER
|
||||
{
|
||||
// A C++11 literal operator.
|
||||
if (!$2.empty()) {
|
||||
yyerror("expected empty string", @2);
|
||||
}
|
||||
CPPIdentifier *ident = $1;
|
||||
if (ident == NULL) {
|
||||
ident = new CPPIdentifier("operator \"\" "+$3->get_simple_name(), @3);
|
||||
} else {
|
||||
ident->_names.push_back("operator \"\" "+$3->get_simple_name());
|
||||
}
|
||||
|
||||
$$ = new CPPInstanceIdentifier(ident);
|
||||
}
|
||||
| KW_CONST instance_identifier %prec UNARY
|
||||
@ -1691,6 +1716,15 @@ type:
|
||||
}
|
||||
$$ = et;
|
||||
}
|
||||
}
|
||||
| KW_DECLTYPE '(' const_expr ')'
|
||||
{
|
||||
$$ = $3->determine_type();
|
||||
if ($$ == (CPPType *)NULL) {
|
||||
stringstream str;
|
||||
str << *$3;
|
||||
yyerror("could not determine type of " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@ -1772,6 +1806,15 @@ type_decl:
|
||||
}
|
||||
$$ = et;
|
||||
}
|
||||
}
|
||||
| KW_DECLTYPE '(' const_expr ')'
|
||||
{
|
||||
$$ = $3->determine_type();
|
||||
if ($$ == (CPPType *)NULL) {
|
||||
stringstream str;
|
||||
str << *$3;
|
||||
yyerror("could not determine type of " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@ -2212,48 +2255,34 @@ code_block:
|
||||
|
||||
element:
|
||||
REAL
|
||||
{
|
||||
}
|
||||
| INTEGER
|
||||
{
|
||||
}
|
||||
| STRING
|
||||
{
|
||||
}
|
||||
| SIMPLE_STRING
|
||||
| STRING_LITERAL
|
||||
| CUSTOM_LITERAL
|
||||
| CHAR_TOK
|
||||
{
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
}
|
||||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
}
|
||||
| SCOPING
|
||||
{
|
||||
}
|
||||
| SIMPLE_IDENTIFIER
|
||||
{
|
||||
}
|
||||
| ELLIPSIS | OROR | ANDAND
|
||||
| EQCOMPARE | NECOMPARE | LECOMPARE | GECOMPARE
|
||||
| LSHIFT | RSHIFT | POINTSAT_STAR | DOT_STAR | POINTSAT
|
||||
| SCOPE | PLUSPLUS | MINUSMINUS
|
||||
| TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
|
||||
| OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
|
||||
| KW_BOOL | KW_CATCH | KW_CHAR | KW_CHAR16_T | KW_CHAR32_T
|
||||
| KW_WCHAR_T | KW_CLASS | KW_CONST
|
||||
| KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_CATCH
|
||||
| KW_CHAR | KW_CHAR16_T | KW_CHAR32_T
|
||||
| KW_CLASS | KW_CONST | KW_CONSTEXPR | KW_DECLTYPE | KW_DEFAULT
|
||||
| KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST | KW_ELSE | KW_ENUM
|
||||
| KW_EXTERN | KW_EXPLICIT | KW_FALSE
|
||||
| KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO
|
||||
| KW_IF | KW_INLINE | KW_INT
|
||||
| KW_LONG | KW_MUTABLE | KW_NEW | KW_PRIVATE | KW_PROTECTED
|
||||
| KW_IF | KW_INLINE | KW_INT | KW_LONG | KW_MUTABLE
|
||||
| KW_NEW | KW_NULLPTR | KW_OPERATOR | KW_PRIVATE | KW_PROTECTED
|
||||
| KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_RETURN
|
||||
| KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_CAST
|
||||
| KW_STRUCT | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF | KW_TYPENAME
|
||||
| KW_UNION | KW_UNSIGNED | KW_VIRTUAL | KW_VOID | KW_VOLATILE
|
||||
| KW_WHILE
|
||||
| KW_OPERATOR
|
||||
| KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_ASSERT
|
||||
| KW_STATIC_CAST | KW_STRUCT | KW_THROW | KW_TRUE | KW_TRY
|
||||
| KW_TYPEDEF | KW_TYPENAME | KW_UNION | KW_UNSIGNED | KW_VIRTUAL
|
||||
| KW_VOID | KW_VOLATILE | KW_WCHAR_T | KW_WHILE
|
||||
{
|
||||
}
|
||||
| '+' | '-' | '*' | '/' | '&' | '|' | '^' | '!' | '~' | '=' | '%'
|
||||
@ -2314,6 +2343,10 @@ no_angle_bracket_const_expr:
|
||||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::alignof_func($3));
|
||||
}
|
||||
| '!' no_angle_bracket_const_expr %prec UNARY
|
||||
{
|
||||
@ -2325,15 +2358,7 @@ no_angle_bracket_const_expr:
|
||||
}
|
||||
| '-' no_angle_bracket_const_expr %prec UNARY
|
||||
{
|
||||
if ($2->_type == CPPExpression::T_integer) {
|
||||
$$ = $2;
|
||||
$$->_u._integer = -$$->_u._integer;
|
||||
} else if ($2->_type == CPPExpression::T_real) {
|
||||
$$ = $2;
|
||||
$$->_u._real = -$$->_u._real;
|
||||
} else {
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
| '*' no_angle_bracket_const_expr %prec UNARY
|
||||
{
|
||||
@ -2544,6 +2569,10 @@ const_expr:
|
||||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::alignof_func($3));
|
||||
}
|
||||
| KW_NEW predefined_type %prec UNARY
|
||||
{
|
||||
@ -2563,15 +2592,7 @@ const_expr:
|
||||
}
|
||||
| '-' const_expr %prec UNARY
|
||||
{
|
||||
if ($2->_type == CPPExpression::T_integer) {
|
||||
$$ = $2;
|
||||
$$->_u._integer = -$$->_u._integer;
|
||||
} else if ($2->_type == CPPExpression::T_real) {
|
||||
$$ = $2;
|
||||
$$->_u._real = -$$->_u._real;
|
||||
} else {
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
| '*' const_expr %prec UNARY
|
||||
{
|
||||
@ -2704,13 +2725,21 @@ const_operand:
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
}
|
||||
| string
|
||||
| string_literal
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
$$ = $1;
|
||||
}
|
||||
| CUSTOM_LITERAL
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new CPPExpression($1, current_scope, global_scope, current_lexer);
|
||||
}
|
||||
| KW_NULLPTR
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::get_nullptr());
|
||||
}
|
||||
;
|
||||
|
||||
@ -2741,6 +2770,10 @@ formal_const_expr:
|
||||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::alignof_func($3));
|
||||
}
|
||||
| KW_NEW predefined_type %prec UNARY
|
||||
{
|
||||
@ -2760,15 +2793,7 @@ formal_const_expr:
|
||||
}
|
||||
| '-' const_expr %prec UNARY
|
||||
{
|
||||
if ($2->_type == CPPExpression::T_integer) {
|
||||
$$ = $2;
|
||||
$$->_u._integer = -$$->_u._integer;
|
||||
} else if ($2->_type == CPPExpression::T_real) {
|
||||
$$ = $2;
|
||||
$$->_u._real = -$$->_u._real;
|
||||
} else {
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
$$ = new CPPExpression(UNARY_MINUS, $2);
|
||||
}
|
||||
| '&' const_expr %prec UNARY
|
||||
{
|
||||
@ -2897,9 +2922,17 @@ formal_const_operand:
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
}
|
||||
| string
|
||||
| string_literal
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
$$ = $1;
|
||||
}
|
||||
| CUSTOM_LITERAL
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| KW_NULLPTR
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::get_nullptr());
|
||||
}
|
||||
;
|
||||
|
||||
@ -2956,14 +2989,29 @@ name:
|
||||
}
|
||||
;
|
||||
|
||||
string:
|
||||
STRING
|
||||
string_literal:
|
||||
SIMPLE_STRING
|
||||
{
|
||||
$$ = new CPPExpression($1);
|
||||
}
|
||||
| STRING_LITERAL
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| string STRING
|
||||
| string_literal SIMPLE_STRING
|
||||
{
|
||||
$$ = $1 + $2;
|
||||
// The right string takes on the literal type of the left.
|
||||
$$ = $1;
|
||||
$$->_str += $2;
|
||||
}
|
||||
| string_literal STRING_LITERAL
|
||||
{
|
||||
// We have to check that the two literal types match up.
|
||||
$$ = $1;
|
||||
if ($2->_type != CPPExpression::T_string && $2->_type != $1->_type) {
|
||||
yywarning("cannot concatenate two string literals of different types", @$);
|
||||
}
|
||||
$$->_str += $2->_str;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -68,8 +68,8 @@ class cppyystype {
|
||||
public:
|
||||
string str;
|
||||
union {
|
||||
int integer;
|
||||
double real;
|
||||
unsigned long long integer;
|
||||
long double real;
|
||||
CPPScope *scope;
|
||||
CPPDeclaration *decl;
|
||||
CPPInstance *instance;
|
||||
|
@ -201,6 +201,19 @@ output(ostream &out) const {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression::
|
||||
CPPExpression(unsigned long long value) :
|
||||
CPPDeclaration(CPPFile())
|
||||
{
|
||||
_type = T_integer;
|
||||
_u._integer = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Constructor
|
||||
// Access: Public
|
||||
@ -220,7 +233,7 @@ CPPExpression(int value) :
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression::
|
||||
CPPExpression(double value) :
|
||||
CPPExpression(long double value) :
|
||||
CPPDeclaration(CPPFile())
|
||||
{
|
||||
_type = T_real;
|
||||
@ -397,6 +410,89 @@ sizeof_func(CPPType *type) {
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named alignof_func constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
alignof_func(CPPType *type) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_alignof;
|
||||
expr._u._typecast._to = type;
|
||||
expr._u._typecast._op1 = NULL;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
literal(unsigned long long value, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_literal;
|
||||
expr._u._literal._value = new CPPExpression(value);
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
literal(long double value, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_literal;
|
||||
expr._u._literal._value = new CPPExpression(value);
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
literal(CPPExpression *value, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_literal;
|
||||
expr._u._literal._value = value;
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::named raw_literal constructor
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPExpression CPPExpression::
|
||||
raw_literal(const string &raw, CPPInstance *lit_op) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_raw_literal;
|
||||
expr._str = raw;
|
||||
expr._u._literal._value = (CPPExpression *)NULL;
|
||||
expr._u._literal._operator = lit_op;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::get_nullptr
|
||||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const CPPExpression &CPPExpression::
|
||||
get_nullptr() {
|
||||
static CPPExpression expr(0);
|
||||
expr._type = T_nullptr;
|
||||
return expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPExpression::Destructor
|
||||
// Access: Public
|
||||
@ -416,13 +512,20 @@ evaluate() const {
|
||||
Result r1, r2;
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return Result((void *)0);
|
||||
|
||||
case T_integer:
|
||||
return Result(_u._integer);
|
||||
return Result((int)_u._integer);
|
||||
|
||||
case T_real:
|
||||
return Result(_u._real);
|
||||
return Result((double)_u._real);
|
||||
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return Result();
|
||||
|
||||
case T_variable:
|
||||
@ -468,6 +571,17 @@ evaluate() const {
|
||||
case T_sizeof:
|
||||
return Result();
|
||||
|
||||
case T_alignof:
|
||||
if (_u._typecast._to != NULL) {
|
||||
// Check if the type is defined with an alignas. TODO: this should
|
||||
// probably be moved to a virtual getter on CPPType.
|
||||
CPPExtensionType *etype = _u._typecast._to->as_extension_type();
|
||||
if (etype != NULL && etype->_alignment != NULL) {
|
||||
return etype->_alignment->evaluate();
|
||||
}
|
||||
}
|
||||
return Result();
|
||||
|
||||
case T_binary_operation:
|
||||
assert(_u._op._op2 != NULL);
|
||||
r2 = _u._op._op2->evaluate();
|
||||
@ -652,6 +766,10 @@ evaluate() const {
|
||||
abort();
|
||||
}
|
||||
|
||||
case T_literal:
|
||||
case T_raw_literal:
|
||||
return Result();
|
||||
|
||||
default:
|
||||
cerr << "**invalid operand**\n";
|
||||
abort();
|
||||
@ -671,25 +789,51 @@ determine_type() const {
|
||||
CPPType *t1 = (CPPType *)NULL;
|
||||
CPPType *t2 = (CPPType *)NULL;
|
||||
|
||||
CPPType *int_type =
|
||||
static CPPType *nullptr_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_nullptr));
|
||||
|
||||
static CPPType *int_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int));
|
||||
|
||||
CPPType *bool_type =
|
||||
static CPPType *unsigned_long_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
|
||||
CPPSimpleType::F_unsigned |
|
||||
CPPSimpleType::F_long));
|
||||
|
||||
static CPPType *bool_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool));
|
||||
|
||||
CPPType *float_type =
|
||||
static CPPType *float_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double));
|
||||
|
||||
CPPType *char_type =
|
||||
static CPPType *char_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char));
|
||||
|
||||
CPPType *const_char_type =
|
||||
CPPType::new_type(new CPPConstType(char_type));
|
||||
static CPPType *wchar_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t));
|
||||
|
||||
CPPType *char_star_type =
|
||||
CPPType::new_type(new CPPPointerType(const_char_type));
|
||||
static CPPType *char16_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t));
|
||||
|
||||
static CPPType *char32_type =
|
||||
CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t));
|
||||
|
||||
static CPPType *char_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(char_type))));
|
||||
|
||||
static CPPType *wchar_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(wchar_type))));
|
||||
|
||||
static CPPType *char16_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(char16_type))));
|
||||
|
||||
static CPPType *char32_str_type = CPPType::new_type(
|
||||
new CPPPointerType(CPPType::new_type(new CPPConstType(char32_type))));
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return nullptr_type;
|
||||
|
||||
case T_integer:
|
||||
return int_type;
|
||||
|
||||
@ -697,7 +841,19 @@ determine_type() const {
|
||||
return float_type;
|
||||
|
||||
case T_string:
|
||||
return char_star_type;
|
||||
return char_str_type;
|
||||
|
||||
case T_wstring:
|
||||
return wchar_str_type;
|
||||
|
||||
case T_u8string:
|
||||
return char_str_type;
|
||||
|
||||
case T_u16string:
|
||||
return char16_str_type;
|
||||
|
||||
case T_u32string:
|
||||
return char32_str_type;
|
||||
|
||||
case T_variable:
|
||||
return _u._variable->_type;
|
||||
@ -725,7 +881,11 @@ determine_type() const {
|
||||
return CPPType::new_type(new CPPPointerType(_u._typecast._to));
|
||||
|
||||
case T_sizeof:
|
||||
return int_type;
|
||||
case T_alignof:
|
||||
// Note: this should actually be size_t, but that is defined as a
|
||||
// typedef in parser-inc. We could try to resolve it, but that's
|
||||
// hacky. Eh, it's probably not worth the effort to get this right.
|
||||
return unsigned_long_type;
|
||||
|
||||
case T_binary_operation:
|
||||
case T_trinary_operation:
|
||||
@ -819,6 +979,18 @@ determine_type() const {
|
||||
abort();
|
||||
}
|
||||
|
||||
case T_literal:
|
||||
case T_raw_literal:
|
||||
if (_u._literal._operator != NULL) {
|
||||
CPPType *type = _u._literal._operator->_type;
|
||||
|
||||
CPPFunctionType *ftype = type->as_function_type();
|
||||
if (ftype != (CPPFunctionType *)NULL) {
|
||||
return ftype->_return_type;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
cerr << "**invalid operand**\n";
|
||||
abort();
|
||||
@ -842,9 +1014,14 @@ is_fully_specified() const {
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
case T_integer:
|
||||
case T_real:
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return false;
|
||||
|
||||
case T_variable:
|
||||
@ -865,6 +1042,7 @@ is_fully_specified() const {
|
||||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to->is_fully_specified();
|
||||
|
||||
case T_trinary_operation:
|
||||
@ -882,6 +1060,13 @@ is_fully_specified() const {
|
||||
case T_unary_operation:
|
||||
return _u._op._op1->is_fully_specified();
|
||||
|
||||
case T_literal:
|
||||
return _u._literal._value->is_fully_specified() &&
|
||||
_u._literal._operator->is_fully_specified();
|
||||
|
||||
case T_raw_literal:
|
||||
return _u._literal._value->is_fully_specified();
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
@ -972,6 +1157,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
||||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
rep->_u._typecast._to =
|
||||
_u._typecast._to->substitute_decl(subst, current_scope, global_scope)
|
||||
->as_type();
|
||||
@ -1042,6 +1228,7 @@ is_tbd() const {
|
||||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to->is_tbd();
|
||||
|
||||
case T_trinary_operation:
|
||||
@ -1075,6 +1262,10 @@ is_tbd() const {
|
||||
void CPPExpression::
|
||||
output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
out << "nullptr";
|
||||
break;
|
||||
|
||||
case T_integer:
|
||||
out << _u._integer;
|
||||
break;
|
||||
@ -1090,8 +1281,29 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
||||
break;
|
||||
|
||||
case T_string:
|
||||
out << '"';
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
{
|
||||
switch (_type) {
|
||||
case T_wstring:
|
||||
out << 'L';
|
||||
break;
|
||||
case T_u8string:
|
||||
out << "u8";
|
||||
break;
|
||||
case T_u16string:
|
||||
out << "u";
|
||||
break;
|
||||
case T_u32string:
|
||||
out << "U";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// We don't really care about preserving the encoding for now.
|
||||
out << '"';
|
||||
string::const_iterator si;
|
||||
for (si = _str.begin(); si != _str.end(); ++si) {
|
||||
switch (*si) {
|
||||
@ -1193,6 +1405,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
||||
out << ")";
|
||||
break;
|
||||
|
||||
case T_alignof:
|
||||
out << "alignof(";
|
||||
_u._typecast._to->output(out, indent_level, scope, false);
|
||||
out << ")";
|
||||
break;
|
||||
|
||||
case T_unary_operation:
|
||||
switch (_u._op._operator) {
|
||||
case UNARY_NOT:
|
||||
@ -1208,9 +1426,8 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
||||
break;
|
||||
|
||||
case UNARY_MINUS:
|
||||
out << "(- ";
|
||||
out << '-';
|
||||
_u._op._op1->output(out, indent_level, scope, false);
|
||||
out << ")";
|
||||
break;
|
||||
|
||||
case UNARY_STAR:
|
||||
@ -1362,6 +1579,24 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
||||
out << ")";
|
||||
break;
|
||||
|
||||
case T_literal:
|
||||
_u._literal._value->output(out, indent_level, scope, false);
|
||||
if (_u._literal._operator != NULL) {
|
||||
string name = _u._literal._operator->get_simple_name();
|
||||
assert(name.substr(0, 12) == "operator \"\" ");
|
||||
out << name.substr(12);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_raw_literal:
|
||||
out << _str;
|
||||
if (_u._literal._operator != NULL) {
|
||||
string name = _u._literal._operator->get_simple_name();
|
||||
assert(name.substr(0, 12) == "operator \"\" ");
|
||||
out << name.substr(12);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
out << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
@ -1456,6 +1691,9 @@ is_equal(const CPPDeclaration *other) const {
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return true;
|
||||
|
||||
case T_integer:
|
||||
return _u._integer == ot->_u._integer;
|
||||
|
||||
@ -1463,6 +1701,10 @@ is_equal(const CPPDeclaration *other) const {
|
||||
return _u._real == ot->_u._real;
|
||||
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return _str == ot->_str;
|
||||
|
||||
case T_variable:
|
||||
@ -1483,6 +1725,7 @@ is_equal(const CPPDeclaration *other) const {
|
||||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to == ot->_u._typecast._to;
|
||||
|
||||
case T_unary_operation:
|
||||
@ -1496,6 +1739,14 @@ is_equal(const CPPDeclaration *other) const {
|
||||
return *_u._op._op1 == *ot->_u._op._op1 &&
|
||||
*_u._op._op2 == *ot->_u._op._op2;
|
||||
|
||||
case T_literal:
|
||||
return *_u._literal._value == *ot->_u._literal._value &&
|
||||
_u._literal._operator == ot->_u._literal._operator;
|
||||
|
||||
case T_raw_literal:
|
||||
return _str == ot->_str &&
|
||||
_u._literal._operator == ot->_u._literal._operator;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
@ -1520,6 +1771,9 @@ is_less(const CPPDeclaration *other) const {
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case T_nullptr:
|
||||
return false;
|
||||
|
||||
case T_integer:
|
||||
return _u._integer < ot->_u._integer;
|
||||
|
||||
@ -1527,6 +1781,10 @@ is_less(const CPPDeclaration *other) const {
|
||||
return _u._real < ot->_u._real;
|
||||
|
||||
case T_string:
|
||||
case T_wstring:
|
||||
case T_u8string:
|
||||
case T_u16string:
|
||||
case T_u32string:
|
||||
return _str < ot->_str;
|
||||
|
||||
case T_variable:
|
||||
@ -1549,6 +1807,7 @@ is_less(const CPPDeclaration *other) const {
|
||||
case T_default_construct:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_alignof:
|
||||
return _u._typecast._to < ot->_u._typecast._to;
|
||||
|
||||
case T_trinary_operation:
|
||||
@ -1566,6 +1825,18 @@ is_less(const CPPDeclaration *other) const {
|
||||
case T_unary_operation:
|
||||
return *_u._op._op1 < *ot->_u._op._op1;
|
||||
|
||||
case T_literal:
|
||||
if (_u._literal._operator != ot->_u._literal._operator) {
|
||||
return _u._literal._operator < ot->_u._literal._operator;
|
||||
}
|
||||
return *_u._literal._value < *ot->_u._literal._value;
|
||||
|
||||
case T_raw_literal:
|
||||
if (_u._literal._operator != ot->_u._literal._operator) {
|
||||
return _u._literal._operator < ot->_u._literal._operator;
|
||||
}
|
||||
return _str < ot->_str;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
@ -30,9 +30,10 @@ class CPPFunctionGroup;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class CPPExpression : public CPPDeclaration {
|
||||
public:
|
||||
CPPExpression(unsigned long long value);
|
||||
CPPExpression(int value);
|
||||
CPPExpression(const string &value);
|
||||
CPPExpression(double value);
|
||||
CPPExpression(long double value);
|
||||
CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
|
||||
CPPScope *global_scope, CPPPreprocessor *error_sink = NULL);
|
||||
CPPExpression(int unary_operator, CPPExpression *op1);
|
||||
@ -43,6 +44,14 @@ public:
|
||||
static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
|
||||
static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
|
||||
static CPPExpression sizeof_func(CPPType *type);
|
||||
static CPPExpression alignof_func(CPPType *type);
|
||||
|
||||
static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
|
||||
static CPPExpression literal(long double value, CPPInstance *lit_op);
|
||||
static CPPExpression literal(CPPExpression *value, CPPInstance *lit_op);
|
||||
static CPPExpression raw_literal(const string &raw, CPPInstance *lit_op);
|
||||
|
||||
static const CPPExpression &get_nullptr();
|
||||
|
||||
~CPPExpression();
|
||||
|
||||
@ -92,9 +101,14 @@ public:
|
||||
|
||||
|
||||
enum Type {
|
||||
T_nullptr,
|
||||
T_integer,
|
||||
T_real,
|
||||
T_string,
|
||||
T_wstring,
|
||||
T_u8string,
|
||||
T_u16string,
|
||||
T_u32string,
|
||||
T_variable,
|
||||
T_function,
|
||||
T_unknown_ident,
|
||||
@ -104,16 +118,19 @@ public:
|
||||
T_new,
|
||||
T_default_new,
|
||||
T_sizeof,
|
||||
T_alignof,
|
||||
T_unary_operation,
|
||||
T_binary_operation,
|
||||
T_trinary_operation,
|
||||
T_literal,
|
||||
T_raw_literal,
|
||||
};
|
||||
|
||||
Type _type;
|
||||
string _str;
|
||||
union {
|
||||
int _integer;
|
||||
double _real;
|
||||
unsigned long long _integer;
|
||||
long double _real;
|
||||
CPPInstance *_variable;
|
||||
CPPFunctionGroup *_fgroup;
|
||||
CPPIdentifier *_ident;
|
||||
@ -131,6 +148,11 @@ public:
|
||||
CPPExpression *_op2;
|
||||
CPPExpression *_op3;
|
||||
} _op;
|
||||
class {
|
||||
public:
|
||||
CPPInstance *_operator;
|
||||
CPPExpression *_value;
|
||||
} _literal;
|
||||
} _u;
|
||||
|
||||
protected:
|
||||
@ -146,5 +168,3 @@ operator << (ostream &out, const CPPExpression::Result &result) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -29,7 +29,8 @@ CPPExtensionType(CPPExtensionType::Type type,
|
||||
CPPIdentifier *ident, CPPScope *current_scope,
|
||||
const CPPFile &file) :
|
||||
CPPType(file),
|
||||
_type(type), _ident(ident)
|
||||
_type(type), _ident(ident),
|
||||
_alignment(NULL)
|
||||
{
|
||||
if (_ident != NULL) {
|
||||
_ident->_native_scope = current_scope;
|
||||
|
@ -65,9 +65,9 @@ public:
|
||||
|
||||
virtual CPPExtensionType *as_extension_type();
|
||||
|
||||
|
||||
Type _type;
|
||||
CPPIdentifier *_ident;
|
||||
CPPExpression *_alignment;
|
||||
};
|
||||
|
||||
ostream &operator << (ostream &out, CPPExtensionType::Type type);
|
||||
|
@ -38,7 +38,8 @@ CPPInstance(CPPType *type, const string &name, int storage_class) :
|
||||
CPPDeclaration(CPPFile()),
|
||||
_type(type),
|
||||
_ident(new CPPIdentifier(name)),
|
||||
_storage_class(storage_class)
|
||||
_storage_class(storage_class),
|
||||
_alignment(NULL)
|
||||
{
|
||||
_initializer = NULL;
|
||||
}
|
||||
@ -53,7 +54,8 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
|
||||
CPPDeclaration(CPPFile()),
|
||||
_type(type),
|
||||
_ident(ident),
|
||||
_storage_class(storage_class)
|
||||
_storage_class(storage_class),
|
||||
_alignment(NULL)
|
||||
{
|
||||
_initializer = NULL;
|
||||
}
|
||||
@ -69,7 +71,8 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
|
||||
CPPInstance::
|
||||
CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
|
||||
const CPPFile &file) :
|
||||
CPPDeclaration(file)
|
||||
CPPDeclaration(file),
|
||||
_alignment(NULL)
|
||||
{
|
||||
_type = ii->unroll_type(type);
|
||||
_ident = ii->_ident;
|
||||
@ -102,7 +105,8 @@ CPPInstance(const CPPInstance ©) :
|
||||
_type(copy._type),
|
||||
_ident(copy._ident),
|
||||
_initializer(copy._initializer),
|
||||
_storage_class(copy._storage_class)
|
||||
_storage_class(copy._storage_class),
|
||||
_alignment(copy._alignment)
|
||||
{
|
||||
assert(_type != NULL);
|
||||
}
|
||||
@ -153,6 +157,9 @@ operator == (const CPPInstance &other) const {
|
||||
if (_storage_class != other._storage_class) {
|
||||
return false;
|
||||
}
|
||||
if (_alignment != other._alignment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We *do* care about the identifier. We need to differentiate
|
||||
// types of function variables, among possibly other things, based
|
||||
@ -199,6 +206,9 @@ operator < (const CPPInstance &other) const {
|
||||
if (_storage_class != other._storage_class) {
|
||||
return _storage_class < other._storage_class;
|
||||
}
|
||||
if (_alignment != other._alignment) {
|
||||
return _alignment < other._alignment;
|
||||
}
|
||||
|
||||
// We *do* care about the identifier. We need to differentiate
|
||||
// types of function variables, among possibly other things, based
|
||||
@ -252,6 +262,29 @@ set_initializer(CPPExpression *initializer) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPInstance::set_alignment
|
||||
// Access: Public
|
||||
// Description: Sets the number of bytes to align this instance to.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CPPInstance::
|
||||
set_alignment(int align) {
|
||||
_alignment = new CPPExpression(align);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPInstance::set_alignment
|
||||
// Access: Public
|
||||
// Description: Sets the expression that is used to determine the
|
||||
// required alignment for the variable. This should
|
||||
// be a constant expression, but we don't presently
|
||||
// verify that it is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CPPInstance::
|
||||
set_alignment(CPPExpression *const_expr) {
|
||||
_alignment = const_expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPInstance::is_scoped
|
||||
// Access: Public
|
||||
@ -536,6 +569,11 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
|
||||
get_template_scope()->_parameters.write_formal(out, scope);
|
||||
indent(out, indent_level);
|
||||
}
|
||||
|
||||
if (_alignment != NULL) {
|
||||
out << "alignas(" << *_alignment << ") ";
|
||||
}
|
||||
|
||||
if (_storage_class & SC_static) {
|
||||
out << "static ";
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ public:
|
||||
bool operator < (const CPPInstance &other) const;
|
||||
|
||||
void set_initializer(CPPExpression *initializer);
|
||||
void set_alignment(int align);
|
||||
void set_alignment(CPPExpression *const_expr);
|
||||
|
||||
bool is_scoped() const;
|
||||
CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope,
|
||||
@ -111,6 +113,7 @@ public:
|
||||
CPPExpression *_initializer;
|
||||
|
||||
int _storage_class;
|
||||
CPPExpression *_alignment;
|
||||
|
||||
private:
|
||||
typedef map<const CPPTemplateParameterList *, CPPInstance *, CPPTPLCompare> Instantiations;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "cppBison.h"
|
||||
#include "indent.h"
|
||||
#include "pstrtod.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -404,6 +405,7 @@ get_next_token0() {
|
||||
// keyword. We make a special case for this, because it's
|
||||
// occasionally scoped in normal use.
|
||||
token._lval = result;
|
||||
_last_token_loc = token._lloc;
|
||||
return token;
|
||||
}
|
||||
_saved_tokens.push_back(token);
|
||||
@ -1803,9 +1805,7 @@ get_quoted_char(int c) {
|
||||
result.u.integer = 0;
|
||||
}
|
||||
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
return CPPToken(CHAR_TOK, loc, str, result);
|
||||
return get_literal(CHAR_TOK, loc, str, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1822,9 +1822,7 @@ get_quoted_string(int c) {
|
||||
|
||||
string str = scan_quoted(c);
|
||||
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
return CPPToken(STRING, loc, str);
|
||||
return get_literal(SIMPLE_STRING, loc, str);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1848,25 +1846,51 @@ get_identifier(int c) {
|
||||
name += get();
|
||||
c = peek();
|
||||
}
|
||||
if (c == '\'' || c == '"') {
|
||||
// This is actually a wide-character or wide-string literal or
|
||||
// some such: a string with an alphanumeric prefix. We don't
|
||||
// necessarily try to parse it correctly; for most purposes, we
|
||||
// don't care.
|
||||
get();
|
||||
CPPToken token(0);
|
||||
if (c == '\'') {
|
||||
token = get_quoted_char(c);
|
||||
} else {
|
||||
token = get_quoted_string(c);
|
||||
}
|
||||
token._lloc.first_column = loc.first_column;
|
||||
return token;
|
||||
}
|
||||
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
|
||||
if ((c == '\'' || c == '"') && name != "operator") {
|
||||
// This is actually a wide-character or wide-string literal or
|
||||
// some such. Figure out the correct character type to use.
|
||||
// We had to add in an exception in order to support operator"".
|
||||
|
||||
CPPExpression::Type type;
|
||||
if (name == "L") {
|
||||
type = CPPExpression::T_wstring;
|
||||
} else if (name == "u8") {
|
||||
type = CPPExpression::T_u8string;
|
||||
} else if (name == "u") {
|
||||
type = CPPExpression::T_u16string;
|
||||
} else if (name == "U") {
|
||||
type = CPPExpression::T_u32string;
|
||||
} else {
|
||||
type = CPPExpression::T_string;
|
||||
warning("unrecognized literal prefix " + name, loc);
|
||||
}
|
||||
|
||||
get();
|
||||
string str = scan_quoted(c);
|
||||
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
|
||||
YYSTYPE result;
|
||||
if (c == '\'') {
|
||||
// We don't really care about the type for now.
|
||||
if (!str.empty()) {
|
||||
result.u.integer = (int)str[0];
|
||||
} else {
|
||||
result.u.integer = 0;
|
||||
}
|
||||
return get_literal(CHAR_TOK, loc, str, result);
|
||||
} else {
|
||||
result.u.expr = new CPPExpression(str);
|
||||
result.u.expr->_type = type;
|
||||
return get_literal(STRING_LITERAL, loc, str, result);
|
||||
}
|
||||
}
|
||||
|
||||
_last_c = 0;
|
||||
|
||||
// Is it a manifest?
|
||||
@ -1898,6 +1922,171 @@ get_identifier(int c) {
|
||||
return CPPToken(SIMPLE_IDENTIFIER, loc, name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPPreprocessor::get_literal
|
||||
// Access: Private
|
||||
// Description: Under the assumption that we've just parsed a
|
||||
// string or real constant, parse a following custom
|
||||
// literal, and returns a token for it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPPToken CPPPreprocessor::
|
||||
get_literal(int token, YYLTYPE loc, const string &str, const YYSTYPE &value) {
|
||||
string suffix;
|
||||
|
||||
int c = peek();
|
||||
if (isalpha(c) || c == '_') {
|
||||
// A literal seems to be following directly.
|
||||
while (c != EOF && (isalnum(c) || c == '_')) {
|
||||
suffix += get();
|
||||
c = peek();
|
||||
}
|
||||
}
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
|
||||
if (suffix.empty()) {
|
||||
// There is no suffix.
|
||||
return CPPToken(token, loc, str, value);
|
||||
}
|
||||
|
||||
// Handle built-in literal suffixes.
|
||||
if (token == INTEGER) {
|
||||
if (cmp_nocase(suffix, "u") == 0 ||
|
||||
cmp_nocase(suffix, "l") == 0 ||
|
||||
cmp_nocase(suffix, "ul") == 0 || cmp_nocase(suffix, "lu") == 0 ||
|
||||
cmp_nocase(suffix, "ll") == 0 ||
|
||||
cmp_nocase(suffix, "ull") == 0 || cmp_nocase(suffix, "llu") == 0) {
|
||||
// These are built-in integer suffixes. Right now, we don't try to
|
||||
// distinguish between them.
|
||||
return CPPToken(INTEGER, loc, str, value);
|
||||
}
|
||||
} else if (token == REAL) {
|
||||
if (suffix == "f" || suffix == "F" ||
|
||||
suffix == "l" || suffix == "L") {
|
||||
return CPPToken(REAL, loc, str, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the literal operator for this literal.
|
||||
CPPIdentifier *ident = new CPPIdentifier("operator \"\" " + suffix);
|
||||
CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope, this);
|
||||
|
||||
if (decl == NULL || decl->get_subtype() != CPPDeclaration::ST_function_group) {
|
||||
error("unknown literal suffix " + suffix, loc);
|
||||
return CPPToken(token, loc, str, value);
|
||||
}
|
||||
|
||||
// Find the overload with the appropriate signature.
|
||||
CPPExpression *expr = NULL;
|
||||
CPPInstance *instance = NULL;
|
||||
CPPInstance *raw_instance = NULL;
|
||||
CPPFunctionGroup *fgroup = decl->as_function_group();
|
||||
CPPFunctionGroup::Instances::iterator it;
|
||||
for (it = fgroup->_instances.begin(); it != fgroup->_instances.end(); ++it) {
|
||||
if ((*it)->_type == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPPFunctionType *ftype = (*it)->_type->as_function_type();
|
||||
if (ftype == NULL || ftype->_parameters == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPPParameterList::Parameters ¶ms = ftype->_parameters->_parameters;
|
||||
if (token == STRING_LITERAL || token == SIMPLE_STRING) {
|
||||
// A custom string literal must take a second size_t argument.
|
||||
if (params.size() != 2) continue;
|
||||
} else {
|
||||
if (params.size() != 1) continue;
|
||||
}
|
||||
|
||||
CPPInstance *param = params[0];
|
||||
if (param == NULL || param->_type == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPPType *type = param->_type;
|
||||
while (type->get_subtype() == CPPDeclaration::ST_const) {
|
||||
type = type->as_const_type()->_wrapped_around;
|
||||
}
|
||||
if (type->get_subtype() == CPPDeclaration::ST_simple) {
|
||||
// It's a primitive type. Check that it matches the appropriate token.
|
||||
CPPSimpleType::Type simple = type->as_simple_type()->_type;
|
||||
|
||||
if (token == INTEGER && simple == CPPSimpleType::T_int) {
|
||||
expr = new CPPExpression(value.u.integer);
|
||||
instance = (*it);
|
||||
break;
|
||||
} else if (token == REAL && simple == CPPSimpleType::T_double) {
|
||||
expr = new CPPExpression(value.u.real);
|
||||
instance = (*it);
|
||||
break;
|
||||
} else if (token == CHAR_TOK && (simple == CPPSimpleType::T_char ||
|
||||
simple == CPPSimpleType::T_wchar_t ||
|
||||
simple == CPPSimpleType::T_char16_t ||
|
||||
simple == CPPSimpleType::T_char32_t)) {
|
||||
// We currently don't have the means to check the exact character type.
|
||||
expr = new CPPExpression(value.u.integer);
|
||||
instance = (*it);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (type->get_subtype() == CPPDeclaration::ST_pointer) {
|
||||
// Must be a const pointer. Unwrap it.
|
||||
type = type->as_pointer_type()->_pointing_at;
|
||||
if (type == NULL || type->get_subtype() != CPPDeclaration::ST_const) {
|
||||
continue;
|
||||
}
|
||||
type = type->as_const_type()->_wrapped_around;
|
||||
if (type == NULL || type->get_subtype() != CPPDeclaration::ST_simple) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CPPSimpleType::Type simple = type->as_simple_type()->_type;
|
||||
if (simple == CPPSimpleType::T_char && params.size() == 1) {
|
||||
// This is the raw literal operator. Store it, but don't break;
|
||||
// a non-raw version of the operator might follow, which we'd prefer.
|
||||
raw_instance = (*it);
|
||||
|
||||
} else if (token == SIMPLE_STRING && simple == CPPSimpleType::T_char) {
|
||||
expr = new CPPExpression(str);
|
||||
instance = (*it);
|
||||
break;
|
||||
|
||||
} else if (token == STRING_LITERAL) {
|
||||
// Verify that the character type of the string literal matches
|
||||
// the character type of the parameter.
|
||||
CPPExpression::Type str_type = value.u.expr->_type;
|
||||
if ((str_type == CPPExpression::T_string && simple == CPPSimpleType::T_char) ||
|
||||
(str_type == CPPExpression::T_wstring && simple == CPPSimpleType::T_wchar_t) ||
|
||||
(str_type == CPPExpression::T_u8string && simple == CPPSimpleType::T_char) ||
|
||||
(str_type == CPPExpression::T_u16string && simple == CPPSimpleType::T_char16_t) ||
|
||||
(str_type == CPPExpression::T_u32string && simple == CPPSimpleType::T_char32_t)) {
|
||||
expr = value.u.expr;
|
||||
instance = (*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
YYSTYPE result;
|
||||
if (instance != NULL) {
|
||||
result.u.expr = new CPPExpression(CPPExpression::literal(expr, instance));
|
||||
return CPPToken(CUSTOM_LITERAL, loc, str, result);
|
||||
}
|
||||
|
||||
if ((token == REAL || token == INTEGER) && raw_instance != NULL) {
|
||||
// For numeric constants, we can fall back to a raw literal operator.
|
||||
result.u.expr = new CPPExpression(CPPExpression::raw_literal(str, instance));
|
||||
return CPPToken(CUSTOM_LITERAL, loc, str, result);
|
||||
}
|
||||
|
||||
error(fgroup->_name + " has no suitable overload for literal of this type", loc);
|
||||
result.u.expr = NULL;
|
||||
return CPPToken(CUSTOM_LITERAL, loc, str, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CPPPreprocessor::expand_manifest
|
||||
// Access: Private
|
||||
@ -2196,20 +2385,13 @@ get_number(int c) {
|
||||
c = peek();
|
||||
}
|
||||
|
||||
while (c == 'L' || c == 'U' || c == 'l' || c == 'u') {
|
||||
// We allow (and ignore) an 'L' and/or 'U' following the number.
|
||||
get();
|
||||
c = peek();
|
||||
}
|
||||
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
|
||||
_last_c = 0;
|
||||
|
||||
YYSTYPE result;
|
||||
result.u.integer = strtol(num.c_str(), (char **)NULL, 16);
|
||||
return CPPToken(INTEGER, loc, num, result);
|
||||
|
||||
return get_literal(INTEGER, loc, num, result);
|
||||
}
|
||||
|
||||
while (c != EOF && isdigit(c)) {
|
||||
@ -2229,7 +2411,7 @@ get_number(int c) {
|
||||
}
|
||||
}
|
||||
|
||||
if (decimal_point) {
|
||||
if (decimal_point || c == 'e' || c == 'E') {
|
||||
if (tolower(c) == 'e') {
|
||||
// An exponent is allowed.
|
||||
num += get();
|
||||
@ -2244,28 +2426,17 @@ get_number(int c) {
|
||||
}
|
||||
}
|
||||
|
||||
if (c == 'f') {
|
||||
// We allow (and ignore) an 'f' following the number.
|
||||
get();
|
||||
c = peek();
|
||||
}
|
||||
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
|
||||
YYSTYPE result;
|
||||
result.u.real = pstrtod(num.c_str(), (char **)NULL);
|
||||
return CPPToken(REAL, loc, num, result);
|
||||
|
||||
return get_literal(REAL, loc, num, result);
|
||||
}
|
||||
|
||||
// This is a decimal or octal integer number.
|
||||
|
||||
while (c == 'L' || c == 'U') {
|
||||
// We allow (and ignore) an 'L' and/or 'U' following the number.
|
||||
get();
|
||||
c = peek();
|
||||
}
|
||||
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number();
|
||||
|
||||
@ -2282,7 +2453,7 @@ get_number(int c) {
|
||||
result.u.integer = strtol(num.c_str(), (char **)NULL, 10);
|
||||
}
|
||||
|
||||
return CPPToken(INTEGER, loc, num, result);
|
||||
return get_literal(INTEGER, loc, num, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -2292,6 +2463,11 @@ get_number(int c) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CPPPreprocessor::
|
||||
check_keyword(const string &name) {
|
||||
if (name == "alignas") return KW_ALIGNAS;
|
||||
if (name == "alignof") return KW_ALIGNOF;
|
||||
if (name == "__alignof") return KW_ALIGNOF;
|
||||
if (name == "__alignof__") return KW_ALIGNOF;
|
||||
if (name == "auto") return KW_AUTO;
|
||||
if (name == "__begin_publish") return KW_BEGIN_PUBLISH;
|
||||
if (name == "__blocking") return KW_BLOCKING;
|
||||
if (name == "bool") return KW_BOOL;
|
||||
@ -2303,6 +2479,9 @@ check_keyword(const string &name) {
|
||||
if (name == "const") return KW_CONST;
|
||||
if (name == "__const") return KW_CONST;
|
||||
if (name == "__const__") return KW_CONST;
|
||||
if (name == "constexpr") return KW_CONSTEXPR;
|
||||
if (name == "decltype") return KW_DECLTYPE;
|
||||
if (name == "default") return KW_DEFAULT;
|
||||
if (name == "delete") return KW_DELETE;
|
||||
if (name == "double") return KW_DOUBLE;
|
||||
if (name == "dynamic_cast") return KW_DYNAMIC_CAST;
|
||||
@ -2329,6 +2508,7 @@ check_keyword(const string &name) {
|
||||
if (name == "mutable") return KW_MUTABLE;
|
||||
if (name == "namespace") return KW_NAMESPACE;
|
||||
if (name == "noexcept") return KW_NOEXCEPT;
|
||||
if (name == "nullptr") return KW_NULLPTR;
|
||||
if (name == "new") return KW_NEW;
|
||||
if (name == "operator") return KW_OPERATOR;
|
||||
if (name == "private") return KW_PRIVATE;
|
||||
|
@ -142,6 +142,8 @@ private:
|
||||
CPPToken get_quoted_char(int c);
|
||||
CPPToken get_quoted_string(int c);
|
||||
CPPToken get_identifier(int c);
|
||||
CPPToken get_literal(int token, YYLTYPE loc, const string &str,
|
||||
const YYSTYPE &result = YYSTYPE());
|
||||
CPPToken expand_manifest(const CPPManifest *manifest);
|
||||
void extract_manifest_args(const string &name, int num_args,
|
||||
int va_arg, vector_string &args);
|
||||
|
@ -313,7 +313,7 @@ add_using(CPPUsing *using_decl, CPPScope *global_scope,
|
||||
_using.insert(scope);
|
||||
} else {
|
||||
if (error_sink != NULL) {
|
||||
error_sink->warning("Attempt to use undefined namespace: " + using_decl->_ident->get_fully_scoped_name());
|
||||
error_sink->warning("Attempt to use undefined namespace: " + using_decl->_ident->get_fully_scoped_name(), using_decl->_ident->_loc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -322,7 +322,7 @@ add_using(CPPUsing *using_decl, CPPScope *global_scope,
|
||||
handle_declaration(decl, global_scope, error_sink);
|
||||
} else {
|
||||
if (error_sink != NULL) {
|
||||
error_sink->warning("Attempt to use unknown symbol: " + using_decl->_ident->get_fully_scoped_name());
|
||||
error_sink->warning("Attempt to use unknown symbol: " + using_decl->_ident->get_fully_scoped_name(), using_decl->_ident->_loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,10 @@ output(ostream &out, int, CPPScope *, bool) const {
|
||||
out << "void";
|
||||
break;
|
||||
|
||||
case T_nullptr:
|
||||
out << "decltype(nullptr)";
|
||||
break;
|
||||
|
||||
case T_parameter:
|
||||
out << "parameter";
|
||||
break;
|
||||
|
@ -37,6 +37,11 @@ public:
|
||||
T_double,
|
||||
T_void,
|
||||
|
||||
// We need something to represent the type of nullptr so that we
|
||||
// can return it from decltype(nullptr). Note that this is not
|
||||
// the same as nullptr_t, which is a typedef of decltype(nullptr).
|
||||
T_nullptr,
|
||||
|
||||
// T_parameter is a special type which is assigned to expressions
|
||||
// that are discovered where a formal parameter was expected.
|
||||
// This is a special case for handling cases like this:
|
||||
|
@ -119,8 +119,12 @@ output(ostream &out) const {
|
||||
out << "CHAR_TOK " << _lval.u.integer << " = " << _lval.str;
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
out << "STRING " << _lval.str;
|
||||
case SIMPLE_STRING:
|
||||
out << "SIMPLE_STRING " << _lval.str;
|
||||
break;
|
||||
|
||||
case STRING_LITERAL:
|
||||
out << "STRING_LITERAL " << *_lval.u.expr;
|
||||
break;
|
||||
|
||||
case SIMPLE_IDENTIFIER:
|
||||
|
@ -22,5 +22,9 @@
|
||||
|
||||
#include <stdtypedefs.h>
|
||||
|
||||
#define offsetof(type,member) ((size_t) &(((type*)0)->member))
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -44,5 +44,26 @@ public:
|
||||
|
||||
typedef basic_string<char> string;
|
||||
typedef basic_string<wchar_t> wstring;
|
||||
typedef basic_string<char16_t> u16string;
|
||||
typedef basic_string<char32_t> u32string;
|
||||
|
||||
namespace std {
|
||||
template<class T> struct hash;
|
||||
template<> struct hash<string>;
|
||||
template<> struct hash<u16string>;
|
||||
template<> struct hash<u32string>;
|
||||
template<> struct hash<wstring>;
|
||||
|
||||
namespace string_literals {
|
||||
string operator "" s(const char *str, size_t len);
|
||||
wstring operator "" s(const wchar_t *str, size_t len);
|
||||
u16string operator "" s(const char16_t *str, size_t len);
|
||||
u32string operator "" s(const char32_t *str, size_t len);
|
||||
}
|
||||
|
||||
namespace literals {
|
||||
using namespace string_literals;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user