More Interrogate C++11 support changes:
* Parse variadic templates * Add (incomplete) type_traits support * Parse anonymous class template params * Parse volatile/lvalue/rvalue methods * Don't generate destructor for indestructible types * Add xmmintrin.h header * Allow invoking extensions with references
This commit is contained in:
parent
7259425b7c
commit
22f0b50851
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "cppArrayType.h"
|
||||
#include "cppExpression.h"
|
||||
#include "cppPointerType.h"
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -63,6 +64,14 @@ is_tbd() const {
|
|||
return _element_type->is_tbd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPArrayType::
|
||||
is_standard_layout() const {
|
||||
return _element_type->is_standard_layout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
|
|
@ -76,7 +85,7 @@ is_trivial() const {
|
|||
*/
|
||||
bool CPPArrayType::
|
||||
is_default_constructible() const {
|
||||
return _element_type->is_default_constructible();
|
||||
return _bounds != NULL && _element_type->is_default_constructible();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
virtual CPPType *resolve_type(CPPScope *current_scope,
|
||||
CPPScope *global_scope);
|
||||
virtual bool is_tbd() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -54,120 +54,138 @@ extern int cppyydebug;
|
|||
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_PLUS = 284,
|
||||
UNARY_STAR = 285,
|
||||
UNARY_REF = 286,
|
||||
POINTSAT = 287,
|
||||
SCOPE = 288,
|
||||
PLUSPLUS = 289,
|
||||
MINUSMINUS = 290,
|
||||
TIMESEQUAL = 291,
|
||||
DIVIDEEQUAL = 292,
|
||||
MODEQUAL = 293,
|
||||
PLUSEQUAL = 294,
|
||||
MINUSEQUAL = 295,
|
||||
OREQUAL = 296,
|
||||
ANDEQUAL = 297,
|
||||
XOREQUAL = 298,
|
||||
LSHIFTEQUAL = 299,
|
||||
RSHIFTEQUAL = 300,
|
||||
KW_ALIGNAS = 301,
|
||||
KW_ALIGNOF = 302,
|
||||
KW_AUTO = 303,
|
||||
KW_BEGIN_PUBLISH = 304,
|
||||
KW_BLOCKING = 305,
|
||||
KW_BOOL = 306,
|
||||
KW_CATCH = 307,
|
||||
KW_CHAR = 308,
|
||||
KW_CHAR16_T = 309,
|
||||
KW_CHAR32_T = 310,
|
||||
KW_CLASS = 311,
|
||||
KW_CONST = 312,
|
||||
KW_CONSTEXPR = 313,
|
||||
KW_CONST_CAST = 314,
|
||||
KW_DECLTYPE = 315,
|
||||
KW_DEFAULT = 316,
|
||||
KW_DELETE = 317,
|
||||
KW_DOUBLE = 318,
|
||||
KW_DYNAMIC_CAST = 319,
|
||||
KW_ELSE = 320,
|
||||
KW_END_PUBLISH = 321,
|
||||
KW_ENUM = 322,
|
||||
KW_EXTENSION = 323,
|
||||
KW_EXTERN = 324,
|
||||
KW_EXPLICIT = 325,
|
||||
KW_PUBLISHED = 326,
|
||||
KW_FALSE = 327,
|
||||
KW_FINAL = 328,
|
||||
KW_FLOAT = 329,
|
||||
KW_FRIEND = 330,
|
||||
KW_FOR = 331,
|
||||
KW_GOTO = 332,
|
||||
KW_IF = 333,
|
||||
KW_INLINE = 334,
|
||||
KW_INT = 335,
|
||||
KW_LONG = 336,
|
||||
KW_MAKE_MAP_PROPERTY = 337,
|
||||
KW_MAKE_PROPERTY = 338,
|
||||
KW_MAKE_PROPERTY2 = 339,
|
||||
KW_MAKE_SEQ = 340,
|
||||
KW_MAKE_SEQ_PROPERTY = 341,
|
||||
KW_MUTABLE = 342,
|
||||
KW_NAMESPACE = 343,
|
||||
KW_NEW = 344,
|
||||
KW_NOEXCEPT = 345,
|
||||
KW_NULLPTR = 346,
|
||||
KW_OPERATOR = 347,
|
||||
KW_OVERRIDE = 348,
|
||||
KW_PRIVATE = 349,
|
||||
KW_PROTECTED = 350,
|
||||
KW_PUBLIC = 351,
|
||||
KW_REGISTER = 352,
|
||||
KW_REINTERPRET_CAST = 353,
|
||||
KW_RETURN = 354,
|
||||
KW_SHORT = 355,
|
||||
KW_SIGNED = 356,
|
||||
KW_SIZEOF = 357,
|
||||
KW_STATIC = 358,
|
||||
KW_STATIC_ASSERT = 359,
|
||||
KW_STATIC_CAST = 360,
|
||||
KW_STRUCT = 361,
|
||||
KW_TEMPLATE = 362,
|
||||
KW_THREAD_LOCAL = 363,
|
||||
KW_THROW = 364,
|
||||
KW_TRUE = 365,
|
||||
KW_TRY = 366,
|
||||
KW_TYPEDEF = 367,
|
||||
KW_TYPEID = 368,
|
||||
KW_TYPENAME = 369,
|
||||
KW_UNION = 370,
|
||||
KW_UNSIGNED = 371,
|
||||
KW_USING = 372,
|
||||
KW_VIRTUAL = 373,
|
||||
KW_VOID = 374,
|
||||
KW_VOLATILE = 375,
|
||||
KW_WCHAR_T = 376,
|
||||
KW_WHILE = 377,
|
||||
START_CPP = 378,
|
||||
START_CONST_EXPR = 379,
|
||||
START_TYPE = 380
|
||||
TYPEPACK_IDENTIFIER = 267,
|
||||
SCOPING = 268,
|
||||
TYPEDEFNAME = 269,
|
||||
ELLIPSIS = 270,
|
||||
OROR = 271,
|
||||
ANDAND = 272,
|
||||
EQCOMPARE = 273,
|
||||
NECOMPARE = 274,
|
||||
LECOMPARE = 275,
|
||||
GECOMPARE = 276,
|
||||
LSHIFT = 277,
|
||||
RSHIFT = 278,
|
||||
POINTSAT_STAR = 279,
|
||||
DOT_STAR = 280,
|
||||
UNARY = 281,
|
||||
UNARY_NOT = 282,
|
||||
UNARY_NEGATE = 283,
|
||||
UNARY_MINUS = 284,
|
||||
UNARY_PLUS = 285,
|
||||
UNARY_STAR = 286,
|
||||
UNARY_REF = 287,
|
||||
POINTSAT = 288,
|
||||
SCOPE = 289,
|
||||
PLUSPLUS = 290,
|
||||
MINUSMINUS = 291,
|
||||
TIMESEQUAL = 292,
|
||||
DIVIDEEQUAL = 293,
|
||||
MODEQUAL = 294,
|
||||
PLUSEQUAL = 295,
|
||||
MINUSEQUAL = 296,
|
||||
OREQUAL = 297,
|
||||
ANDEQUAL = 298,
|
||||
XOREQUAL = 299,
|
||||
LSHIFTEQUAL = 300,
|
||||
RSHIFTEQUAL = 301,
|
||||
KW_ALIGNAS = 302,
|
||||
KW_ALIGNOF = 303,
|
||||
KW_AUTO = 304,
|
||||
KW_BEGIN_PUBLISH = 305,
|
||||
KW_BLOCKING = 306,
|
||||
KW_BOOL = 307,
|
||||
KW_CATCH = 308,
|
||||
KW_CHAR = 309,
|
||||
KW_CHAR16_T = 310,
|
||||
KW_CHAR32_T = 311,
|
||||
KW_CLASS = 312,
|
||||
KW_CONST = 313,
|
||||
KW_CONSTEXPR = 314,
|
||||
KW_CONST_CAST = 315,
|
||||
KW_DECLTYPE = 316,
|
||||
KW_DEFAULT = 317,
|
||||
KW_DELETE = 318,
|
||||
KW_DOUBLE = 319,
|
||||
KW_DYNAMIC_CAST = 320,
|
||||
KW_ELSE = 321,
|
||||
KW_END_PUBLISH = 322,
|
||||
KW_ENUM = 323,
|
||||
KW_EXTENSION = 324,
|
||||
KW_EXTERN = 325,
|
||||
KW_EXPLICIT = 326,
|
||||
KW_PUBLISHED = 327,
|
||||
KW_FALSE = 328,
|
||||
KW_FINAL = 329,
|
||||
KW_FLOAT = 330,
|
||||
KW_FRIEND = 331,
|
||||
KW_FOR = 332,
|
||||
KW_GOTO = 333,
|
||||
KW_HAS_VIRTUAL_DESTRUCTOR = 334,
|
||||
KW_IF = 335,
|
||||
KW_INLINE = 336,
|
||||
KW_INT = 337,
|
||||
KW_IS_ABSTRACT = 338,
|
||||
KW_IS_BASE_OF = 339,
|
||||
KW_IS_CLASS = 340,
|
||||
KW_IS_CONSTRUCTIBLE = 341,
|
||||
KW_IS_CONVERTIBLE_TO = 342,
|
||||
KW_IS_DESTRUCTIBLE = 343,
|
||||
KW_IS_EMPTY = 344,
|
||||
KW_IS_ENUM = 345,
|
||||
KW_IS_FINAL = 346,
|
||||
KW_IS_FUNDAMENTAL = 347,
|
||||
KW_IS_POD = 348,
|
||||
KW_IS_POLYMORPHIC = 349,
|
||||
KW_IS_STANDARD_LAYOUT = 350,
|
||||
KW_IS_TRIVIAL = 351,
|
||||
KW_IS_UNION = 352,
|
||||
KW_LONG = 353,
|
||||
KW_MAKE_MAP_PROPERTY = 354,
|
||||
KW_MAKE_PROPERTY = 355,
|
||||
KW_MAKE_PROPERTY2 = 356,
|
||||
KW_MAKE_SEQ = 357,
|
||||
KW_MAKE_SEQ_PROPERTY = 358,
|
||||
KW_MUTABLE = 359,
|
||||
KW_NAMESPACE = 360,
|
||||
KW_NEW = 361,
|
||||
KW_NOEXCEPT = 362,
|
||||
KW_NULLPTR = 363,
|
||||
KW_OPERATOR = 364,
|
||||
KW_OVERRIDE = 365,
|
||||
KW_PRIVATE = 366,
|
||||
KW_PROTECTED = 367,
|
||||
KW_PUBLIC = 368,
|
||||
KW_REGISTER = 369,
|
||||
KW_REINTERPRET_CAST = 370,
|
||||
KW_RETURN = 371,
|
||||
KW_SHORT = 372,
|
||||
KW_SIGNED = 373,
|
||||
KW_SIZEOF = 374,
|
||||
KW_STATIC = 375,
|
||||
KW_STATIC_ASSERT = 376,
|
||||
KW_STATIC_CAST = 377,
|
||||
KW_STRUCT = 378,
|
||||
KW_TEMPLATE = 379,
|
||||
KW_THREAD_LOCAL = 380,
|
||||
KW_THROW = 381,
|
||||
KW_TRUE = 382,
|
||||
KW_TRY = 383,
|
||||
KW_TYPEDEF = 384,
|
||||
KW_TYPEID = 385,
|
||||
KW_TYPENAME = 386,
|
||||
KW_UNDERLYING_TYPE = 387,
|
||||
KW_UNION = 388,
|
||||
KW_UNSIGNED = 389,
|
||||
KW_USING = 390,
|
||||
KW_VIRTUAL = 391,
|
||||
KW_VOID = 392,
|
||||
KW_VOLATILE = 393,
|
||||
KW_WCHAR_T = 394,
|
||||
KW_WHILE = 395,
|
||||
START_CPP = 396,
|
||||
START_CONST_EXPR = 397,
|
||||
START_TYPE = 398
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
|
@ -180,120 +198,138 @@ extern int cppyydebug;
|
|||
#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_PLUS 284
|
||||
#define UNARY_STAR 285
|
||||
#define UNARY_REF 286
|
||||
#define POINTSAT 287
|
||||
#define SCOPE 288
|
||||
#define PLUSPLUS 289
|
||||
#define MINUSMINUS 290
|
||||
#define TIMESEQUAL 291
|
||||
#define DIVIDEEQUAL 292
|
||||
#define MODEQUAL 293
|
||||
#define PLUSEQUAL 294
|
||||
#define MINUSEQUAL 295
|
||||
#define OREQUAL 296
|
||||
#define ANDEQUAL 297
|
||||
#define XOREQUAL 298
|
||||
#define LSHIFTEQUAL 299
|
||||
#define RSHIFTEQUAL 300
|
||||
#define KW_ALIGNAS 301
|
||||
#define KW_ALIGNOF 302
|
||||
#define KW_AUTO 303
|
||||
#define KW_BEGIN_PUBLISH 304
|
||||
#define KW_BLOCKING 305
|
||||
#define KW_BOOL 306
|
||||
#define KW_CATCH 307
|
||||
#define KW_CHAR 308
|
||||
#define KW_CHAR16_T 309
|
||||
#define KW_CHAR32_T 310
|
||||
#define KW_CLASS 311
|
||||
#define KW_CONST 312
|
||||
#define KW_CONSTEXPR 313
|
||||
#define KW_CONST_CAST 314
|
||||
#define KW_DECLTYPE 315
|
||||
#define KW_DEFAULT 316
|
||||
#define KW_DELETE 317
|
||||
#define KW_DOUBLE 318
|
||||
#define KW_DYNAMIC_CAST 319
|
||||
#define KW_ELSE 320
|
||||
#define KW_END_PUBLISH 321
|
||||
#define KW_ENUM 322
|
||||
#define KW_EXTENSION 323
|
||||
#define KW_EXTERN 324
|
||||
#define KW_EXPLICIT 325
|
||||
#define KW_PUBLISHED 326
|
||||
#define KW_FALSE 327
|
||||
#define KW_FINAL 328
|
||||
#define KW_FLOAT 329
|
||||
#define KW_FRIEND 330
|
||||
#define KW_FOR 331
|
||||
#define KW_GOTO 332
|
||||
#define KW_IF 333
|
||||
#define KW_INLINE 334
|
||||
#define KW_INT 335
|
||||
#define KW_LONG 336
|
||||
#define KW_MAKE_MAP_PROPERTY 337
|
||||
#define KW_MAKE_PROPERTY 338
|
||||
#define KW_MAKE_PROPERTY2 339
|
||||
#define KW_MAKE_SEQ 340
|
||||
#define KW_MAKE_SEQ_PROPERTY 341
|
||||
#define KW_MUTABLE 342
|
||||
#define KW_NAMESPACE 343
|
||||
#define KW_NEW 344
|
||||
#define KW_NOEXCEPT 345
|
||||
#define KW_NULLPTR 346
|
||||
#define KW_OPERATOR 347
|
||||
#define KW_OVERRIDE 348
|
||||
#define KW_PRIVATE 349
|
||||
#define KW_PROTECTED 350
|
||||
#define KW_PUBLIC 351
|
||||
#define KW_REGISTER 352
|
||||
#define KW_REINTERPRET_CAST 353
|
||||
#define KW_RETURN 354
|
||||
#define KW_SHORT 355
|
||||
#define KW_SIGNED 356
|
||||
#define KW_SIZEOF 357
|
||||
#define KW_STATIC 358
|
||||
#define KW_STATIC_ASSERT 359
|
||||
#define KW_STATIC_CAST 360
|
||||
#define KW_STRUCT 361
|
||||
#define KW_TEMPLATE 362
|
||||
#define KW_THREAD_LOCAL 363
|
||||
#define KW_THROW 364
|
||||
#define KW_TRUE 365
|
||||
#define KW_TRY 366
|
||||
#define KW_TYPEDEF 367
|
||||
#define KW_TYPEID 368
|
||||
#define KW_TYPENAME 369
|
||||
#define KW_UNION 370
|
||||
#define KW_UNSIGNED 371
|
||||
#define KW_USING 372
|
||||
#define KW_VIRTUAL 373
|
||||
#define KW_VOID 374
|
||||
#define KW_VOLATILE 375
|
||||
#define KW_WCHAR_T 376
|
||||
#define KW_WHILE 377
|
||||
#define START_CPP 378
|
||||
#define START_CONST_EXPR 379
|
||||
#define START_TYPE 380
|
||||
#define TYPEPACK_IDENTIFIER 267
|
||||
#define SCOPING 268
|
||||
#define TYPEDEFNAME 269
|
||||
#define ELLIPSIS 270
|
||||
#define OROR 271
|
||||
#define ANDAND 272
|
||||
#define EQCOMPARE 273
|
||||
#define NECOMPARE 274
|
||||
#define LECOMPARE 275
|
||||
#define GECOMPARE 276
|
||||
#define LSHIFT 277
|
||||
#define RSHIFT 278
|
||||
#define POINTSAT_STAR 279
|
||||
#define DOT_STAR 280
|
||||
#define UNARY 281
|
||||
#define UNARY_NOT 282
|
||||
#define UNARY_NEGATE 283
|
||||
#define UNARY_MINUS 284
|
||||
#define UNARY_PLUS 285
|
||||
#define UNARY_STAR 286
|
||||
#define UNARY_REF 287
|
||||
#define POINTSAT 288
|
||||
#define SCOPE 289
|
||||
#define PLUSPLUS 290
|
||||
#define MINUSMINUS 291
|
||||
#define TIMESEQUAL 292
|
||||
#define DIVIDEEQUAL 293
|
||||
#define MODEQUAL 294
|
||||
#define PLUSEQUAL 295
|
||||
#define MINUSEQUAL 296
|
||||
#define OREQUAL 297
|
||||
#define ANDEQUAL 298
|
||||
#define XOREQUAL 299
|
||||
#define LSHIFTEQUAL 300
|
||||
#define RSHIFTEQUAL 301
|
||||
#define KW_ALIGNAS 302
|
||||
#define KW_ALIGNOF 303
|
||||
#define KW_AUTO 304
|
||||
#define KW_BEGIN_PUBLISH 305
|
||||
#define KW_BLOCKING 306
|
||||
#define KW_BOOL 307
|
||||
#define KW_CATCH 308
|
||||
#define KW_CHAR 309
|
||||
#define KW_CHAR16_T 310
|
||||
#define KW_CHAR32_T 311
|
||||
#define KW_CLASS 312
|
||||
#define KW_CONST 313
|
||||
#define KW_CONSTEXPR 314
|
||||
#define KW_CONST_CAST 315
|
||||
#define KW_DECLTYPE 316
|
||||
#define KW_DEFAULT 317
|
||||
#define KW_DELETE 318
|
||||
#define KW_DOUBLE 319
|
||||
#define KW_DYNAMIC_CAST 320
|
||||
#define KW_ELSE 321
|
||||
#define KW_END_PUBLISH 322
|
||||
#define KW_ENUM 323
|
||||
#define KW_EXTENSION 324
|
||||
#define KW_EXTERN 325
|
||||
#define KW_EXPLICIT 326
|
||||
#define KW_PUBLISHED 327
|
||||
#define KW_FALSE 328
|
||||
#define KW_FINAL 329
|
||||
#define KW_FLOAT 330
|
||||
#define KW_FRIEND 331
|
||||
#define KW_FOR 332
|
||||
#define KW_GOTO 333
|
||||
#define KW_HAS_VIRTUAL_DESTRUCTOR 334
|
||||
#define KW_IF 335
|
||||
#define KW_INLINE 336
|
||||
#define KW_INT 337
|
||||
#define KW_IS_ABSTRACT 338
|
||||
#define KW_IS_BASE_OF 339
|
||||
#define KW_IS_CLASS 340
|
||||
#define KW_IS_CONSTRUCTIBLE 341
|
||||
#define KW_IS_CONVERTIBLE_TO 342
|
||||
#define KW_IS_DESTRUCTIBLE 343
|
||||
#define KW_IS_EMPTY 344
|
||||
#define KW_IS_ENUM 345
|
||||
#define KW_IS_FINAL 346
|
||||
#define KW_IS_FUNDAMENTAL 347
|
||||
#define KW_IS_POD 348
|
||||
#define KW_IS_POLYMORPHIC 349
|
||||
#define KW_IS_STANDARD_LAYOUT 350
|
||||
#define KW_IS_TRIVIAL 351
|
||||
#define KW_IS_UNION 352
|
||||
#define KW_LONG 353
|
||||
#define KW_MAKE_MAP_PROPERTY 354
|
||||
#define KW_MAKE_PROPERTY 355
|
||||
#define KW_MAKE_PROPERTY2 356
|
||||
#define KW_MAKE_SEQ 357
|
||||
#define KW_MAKE_SEQ_PROPERTY 358
|
||||
#define KW_MUTABLE 359
|
||||
#define KW_NAMESPACE 360
|
||||
#define KW_NEW 361
|
||||
#define KW_NOEXCEPT 362
|
||||
#define KW_NULLPTR 363
|
||||
#define KW_OPERATOR 364
|
||||
#define KW_OVERRIDE 365
|
||||
#define KW_PRIVATE 366
|
||||
#define KW_PROTECTED 367
|
||||
#define KW_PUBLIC 368
|
||||
#define KW_REGISTER 369
|
||||
#define KW_REINTERPRET_CAST 370
|
||||
#define KW_RETURN 371
|
||||
#define KW_SHORT 372
|
||||
#define KW_SIGNED 373
|
||||
#define KW_SIZEOF 374
|
||||
#define KW_STATIC 375
|
||||
#define KW_STATIC_ASSERT 376
|
||||
#define KW_STATIC_CAST 377
|
||||
#define KW_STRUCT 378
|
||||
#define KW_TEMPLATE 379
|
||||
#define KW_THREAD_LOCAL 380
|
||||
#define KW_THROW 381
|
||||
#define KW_TRUE 382
|
||||
#define KW_TRY 383
|
||||
#define KW_TYPEDEF 384
|
||||
#define KW_TYPEID 385
|
||||
#define KW_TYPENAME 386
|
||||
#define KW_UNDERLYING_TYPE 387
|
||||
#define KW_UNION 388
|
||||
#define KW_UNSIGNED 389
|
||||
#define KW_USING 390
|
||||
#define KW_VIRTUAL 391
|
||||
#define KW_VOID 392
|
||||
#define KW_VOLATILE 393
|
||||
#define KW_WCHAR_T 394
|
||||
#define KW_WHILE 395
|
||||
#define START_CPP 396
|
||||
#define START_CONST_EXPR 397
|
||||
#define START_TYPE 398
|
||||
|
||||
/* Value type. */
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ pop_struct() {
|
|||
%token <u.integer> CHAR_TOK
|
||||
%token <str> SIMPLE_STRING SIMPLE_IDENTIFIER
|
||||
%token <u.expr> STRING_LITERAL CUSTOM_LITERAL
|
||||
%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER SCOPING
|
||||
%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER TYPEPACK_IDENTIFIER SCOPING
|
||||
%token <u.type> TYPEDEFNAME
|
||||
|
||||
%token ELLIPSIS
|
||||
|
|
@ -280,9 +280,25 @@ pop_struct() {
|
|||
%token KW_FRIEND
|
||||
%token KW_FOR
|
||||
%token KW_GOTO
|
||||
%token KW_HAS_VIRTUAL_DESTRUCTOR
|
||||
%token KW_IF
|
||||
%token KW_INLINE
|
||||
%token KW_INT
|
||||
%token KW_IS_ABSTRACT
|
||||
%token KW_IS_BASE_OF
|
||||
%token KW_IS_CLASS
|
||||
%token KW_IS_CONSTRUCTIBLE
|
||||
%token KW_IS_CONVERTIBLE_TO
|
||||
%token KW_IS_DESTRUCTIBLE
|
||||
%token KW_IS_EMPTY
|
||||
%token KW_IS_ENUM
|
||||
%token KW_IS_FINAL
|
||||
%token KW_IS_FUNDAMENTAL
|
||||
%token KW_IS_POD
|
||||
%token KW_IS_POLYMORPHIC
|
||||
%token KW_IS_STANDARD_LAYOUT
|
||||
%token KW_IS_TRIVIAL
|
||||
%token KW_IS_UNION
|
||||
%token KW_LONG
|
||||
%token KW_MAKE_MAP_PROPERTY
|
||||
%token KW_MAKE_PROPERTY
|
||||
|
|
@ -317,6 +333,7 @@ pop_struct() {
|
|||
%token KW_TYPEDEF
|
||||
%token KW_TYPEID
|
||||
%token KW_TYPENAME
|
||||
%token KW_UNDERLYING_TYPE
|
||||
%token KW_UNION
|
||||
%token KW_UNSIGNED
|
||||
%token KW_USING
|
||||
|
|
@ -354,9 +371,10 @@ pop_struct() {
|
|||
%type <u.instance> formal_parameter
|
||||
%type <u.inst_ident> not_paren_formal_parameter_identifier
|
||||
%type <u.inst_ident> formal_parameter_identifier
|
||||
%type <u.inst_ident> parameter_pack_identifier
|
||||
%type <u.inst_ident> not_paren_empty_instance_identifier
|
||||
%type <u.inst_ident> empty_instance_identifier
|
||||
%type <u.type> type
|
||||
%type <u.type> type type_pack
|
||||
%type <u.decl> type_decl
|
||||
%type <u.decl> var_type_decl
|
||||
%type <u.type> predefined_type
|
||||
|
|
@ -447,6 +465,10 @@ constructor_init:
|
|||
name '(' optional_const_expr_comma ')'
|
||||
{
|
||||
delete $3;
|
||||
}
|
||||
| name '(' optional_const_expr_comma ')' ELLIPSIS
|
||||
{
|
||||
delete $3;
|
||||
}
|
||||
| name '{' optional_const_expr_comma '}'
|
||||
{
|
||||
|
|
@ -1187,26 +1209,38 @@ function_post:
|
|||
{
|
||||
$$ = 0;
|
||||
}
|
||||
| KW_CONST
|
||||
| function_post KW_CONST
|
||||
{
|
||||
$$ = (int)CPPFunctionType::F_const_method;
|
||||
$$ = $1 | (int)CPPFunctionType::F_const_method;
|
||||
}
|
||||
| function_post KW_VOLATILE
|
||||
{
|
||||
$$ = $1 | (int)CPPFunctionType::F_volatile_method;
|
||||
}
|
||||
| function_post KW_NOEXCEPT
|
||||
{
|
||||
$$ = (int)CPPFunctionType::F_noexcept;
|
||||
$$ = $1 | (int)CPPFunctionType::F_noexcept;
|
||||
}
|
||||
| function_post KW_FINAL
|
||||
{
|
||||
$$ = (int)CPPFunctionType::F_final;
|
||||
$$ = $1 | (int)CPPFunctionType::F_final;
|
||||
}
|
||||
| function_post KW_OVERRIDE
|
||||
{
|
||||
$$ = (int)CPPFunctionType::F_override;
|
||||
$$ = $1 | (int)CPPFunctionType::F_override;
|
||||
}
|
||||
| function_post '&'
|
||||
{
|
||||
$$ = $1 | (int)CPPFunctionType::F_lvalue_method;
|
||||
}
|
||||
| function_post ANDAND
|
||||
{
|
||||
$$ = $1 | (int)CPPFunctionType::F_rvalue_method;
|
||||
}
|
||||
| function_post KW_MUTABLE
|
||||
{
|
||||
// Used for lambdas, currently ignored.
|
||||
$$ = 0;
|
||||
$$ = $1;
|
||||
}
|
||||
| function_post KW_THROW '(' ')'
|
||||
{
|
||||
|
|
@ -1215,6 +1249,10 @@ function_post:
|
|||
| function_post KW_THROW '(' name ')'
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| function_post KW_THROW '(' name ELLIPSIS ')'
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
/* | function_post '[' '[' attribute_specifiers ']' ']'
|
||||
{
|
||||
|
|
@ -1418,22 +1456,35 @@ template_nonempty_formal_parameters:
|
|||
}
|
||||
;
|
||||
|
||||
typename_keyword:
|
||||
KW_CLASS
|
||||
| KW_TYPENAME
|
||||
;
|
||||
|
||||
template_formal_parameter:
|
||||
KW_CLASS name
|
||||
typename_keyword
|
||||
{
|
||||
$$ = CPPType::new_type(new CPPClassTemplateParameter((CPPIdentifier *)NULL));
|
||||
}
|
||||
| typename_keyword name
|
||||
{
|
||||
$$ = CPPType::new_type(new CPPClassTemplateParameter($2));
|
||||
}
|
||||
| KW_CLASS name '=' full_type
|
||||
| typename_keyword name '=' full_type
|
||||
{
|
||||
$$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4));
|
||||
}
|
||||
| KW_TYPENAME name
|
||||
| typename_keyword ELLIPSIS
|
||||
{
|
||||
$$ = CPPType::new_type(new CPPClassTemplateParameter($2));
|
||||
CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter((CPPIdentifier *)NULL);
|
||||
ctp->_packed = true;
|
||||
$$ = CPPType::new_type(ctp);
|
||||
}
|
||||
| KW_TYPENAME name '=' full_type
|
||||
| typename_keyword ELLIPSIS name
|
||||
{
|
||||
$$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4));
|
||||
CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($3);
|
||||
ctp->_packed = true;
|
||||
$$ = CPPType::new_type(ctp);
|
||||
}
|
||||
| template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize
|
||||
{
|
||||
|
|
@ -1447,6 +1498,17 @@ template_formal_parameter:
|
|||
CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file);
|
||||
inst->set_initializer($4);
|
||||
$$ = inst;
|
||||
}
|
||||
| template_formal_parameter_type parameter_pack_identifier
|
||||
{
|
||||
CPPInstance *inst = new CPPInstance($1, $2, 0, @2.file);
|
||||
$$ = inst;
|
||||
}
|
||||
| KW_CONST template_formal_parameter_type parameter_pack_identifier
|
||||
{
|
||||
$3->add_modifier(IIT_const);
|
||||
CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file);
|
||||
$$ = inst;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1467,6 +1529,14 @@ template_formal_parameter_type:
|
|||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert($$ != NULL);
|
||||
}
|
||||
| TYPEPACK_IDENTIFIER
|
||||
{
|
||||
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if ($$ == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert($$ != NULL);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1785,6 +1855,23 @@ function_parameter:
|
|||
$4->add_modifier(IIT_const);
|
||||
$$ = new CPPInstance($3, $4, 0, @3.file);
|
||||
$$->set_initializer($5);
|
||||
}
|
||||
| type_pack parameter_pack_identifier maybe_initialize
|
||||
{
|
||||
$$ = new CPPInstance($1, $2, 0, @2.file);
|
||||
$$->set_initializer($3);
|
||||
}
|
||||
| KW_CONST type_pack parameter_pack_identifier maybe_initialize
|
||||
{
|
||||
$3->add_modifier(IIT_const);
|
||||
$$ = new CPPInstance($2, $3, 0, @3.file);
|
||||
$$->set_initializer($4);
|
||||
}
|
||||
| KW_CONST KW_REGISTER type_pack parameter_pack_identifier maybe_initialize
|
||||
{
|
||||
$4->add_modifier(IIT_const);
|
||||
$$ = new CPPInstance($3, $4, 0, @3.file);
|
||||
$$->set_initializer($5);
|
||||
}
|
||||
| KW_REGISTER function_parameter
|
||||
{
|
||||
|
|
@ -1913,10 +2000,79 @@ formal_parameter_identifier:
|
|||
}
|
||||
;
|
||||
|
||||
parameter_pack_identifier:
|
||||
ELLIPSIS
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
|
||||
$$->_packed = true;
|
||||
}
|
||||
| ELLIPSIS name
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier($2);
|
||||
$$->_packed = true;
|
||||
}
|
||||
| KW_CONST parameter_pack_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_const);
|
||||
}
|
||||
| KW_VOLATILE parameter_pack_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_volatile);
|
||||
}
|
||||
| '*' parameter_pack_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_pointer);
|
||||
}
|
||||
| '&' parameter_pack_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_reference);
|
||||
}
|
||||
| ANDAND parameter_pack_identifier %prec UNARY
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_rvalue_reference);
|
||||
}
|
||||
| SCOPING '*' parameter_pack_identifier %prec UNARY
|
||||
{
|
||||
$$ = $3;
|
||||
$$->add_scoped_pointer_modifier($1);
|
||||
}
|
||||
| parameter_pack_identifier '[' optional_const_expr ']'
|
||||
{
|
||||
$$ = $1;
|
||||
$$->add_array_modifier($3);
|
||||
}
|
||||
| '(' parameter_pack_identifier ')' '(' function_parameter_list ')' function_post
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_paren);
|
||||
$$->add_func_modifier($5, $7);
|
||||
}
|
||||
| '(' parameter_pack_identifier ')'
|
||||
{
|
||||
$$ = $2;
|
||||
$$->add_modifier(IIT_paren);
|
||||
}
|
||||
;
|
||||
|
||||
not_paren_empty_instance_identifier:
|
||||
empty
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
|
||||
}
|
||||
| ELLIPSIS
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
|
||||
$$->_packed = true;
|
||||
}
|
||||
| ELLIPSIS name
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier($2);
|
||||
$$->_packed = true;
|
||||
}
|
||||
| KW_CONST not_paren_empty_instance_identifier %prec UNARY
|
||||
{
|
||||
|
|
@ -1959,6 +2115,16 @@ empty_instance_identifier:
|
|||
empty
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
|
||||
}
|
||||
| ELLIPSIS
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
|
||||
$$->_packed = true;
|
||||
}
|
||||
| ELLIPSIS name
|
||||
{
|
||||
$$ = new CPPInstanceIdentifier($2);
|
||||
$$->_packed = true;
|
||||
}
|
||||
| KW_CONST empty_instance_identifier %prec UNARY
|
||||
{
|
||||
|
|
@ -2093,6 +2259,16 @@ type:
|
|||
str << *$3;
|
||||
yyerror("could not determine type of " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
| KW_UNDERLYING_TYPE '(' full_type ')'
|
||||
{
|
||||
CPPEnumType *enum_type = $3->as_enum_type();
|
||||
if (enum_type == NULL) {
|
||||
yyerror("an enumeration type is required", @3);
|
||||
$$ = $3;
|
||||
} else {
|
||||
$$ = enum_type->get_underlying_type();
|
||||
}
|
||||
}
|
||||
| KW_AUTO
|
||||
{
|
||||
|
|
@ -2100,6 +2276,17 @@ type:
|
|||
}
|
||||
;
|
||||
|
||||
type_pack:
|
||||
TYPEPACK_IDENTIFIER
|
||||
{
|
||||
$$ = $1->find_type(current_scope, global_scope, false, current_lexer);
|
||||
if ($$ == NULL) {
|
||||
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
|
||||
}
|
||||
assert($$ != NULL);
|
||||
}
|
||||
;
|
||||
|
||||
type_decl:
|
||||
simple_type
|
||||
{
|
||||
|
|
@ -2187,6 +2374,16 @@ type_decl:
|
|||
str << *$3;
|
||||
yyerror("could not determine type of " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
| KW_UNDERLYING_TYPE '(' full_type ')'
|
||||
{
|
||||
CPPEnumType *enum_type = $3->as_enum_type();
|
||||
if (enum_type == NULL) {
|
||||
yyerror("an enumeration type is required", @3);
|
||||
$$ = $3;
|
||||
} else {
|
||||
$$ = enum_type->get_underlying_type();
|
||||
}
|
||||
}
|
||||
| KW_AUTO
|
||||
{
|
||||
|
|
@ -2251,6 +2448,16 @@ predefined_type:
|
|||
str << *$3;
|
||||
yyerror("could not determine type of " + str.str(), @3);
|
||||
}
|
||||
}
|
||||
| KW_UNDERLYING_TYPE '(' full_type ')'
|
||||
{
|
||||
CPPEnumType *enum_type = $3->as_enum_type();
|
||||
if (enum_type == NULL) {
|
||||
yyerror("an enumeration type is required", @3);
|
||||
$$ = $3;
|
||||
} else {
|
||||
$$ = enum_type->get_underlying_type();
|
||||
}
|
||||
}
|
||||
| KW_AUTO
|
||||
{
|
||||
|
|
@ -2279,6 +2486,15 @@ full_type:
|
|||
{
|
||||
$3->add_modifier(IIT_const);
|
||||
$$ = $3->unroll_type($2);
|
||||
}
|
||||
| type_pack empty_instance_identifier
|
||||
{
|
||||
$$ = $2->unroll_type($1);
|
||||
}
|
||||
| KW_CONST type_pack empty_instance_identifier
|
||||
{
|
||||
$3->add_modifier(IIT_const);
|
||||
$$ = $3->unroll_type($2);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -2693,6 +2909,7 @@ element:
|
|||
| CHAR_TOK
|
||||
| IDENTIFIER
|
||||
| TYPENAME_IDENTIFIER
|
||||
| TYPEPACK_IDENTIFIER
|
||||
| SCOPING
|
||||
| SIMPLE_IDENTIFIER
|
||||
| ELLIPSIS | OROR | ANDAND
|
||||
|
|
@ -2711,10 +2928,11 @@ element:
|
|||
| KW_OPERATOR | KW_OVERRIDE | KW_PRIVATE | KW_PROTECTED
|
||||
| KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_REINTERPRET_CAST
|
||||
| KW_RETURN | KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC
|
||||
| KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT
|
||||
| KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT | KW_TEMPLATE
|
||||
| KW_THREAD_LOCAL | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF
|
||||
| KW_TYPEID | KW_TYPENAME | KW_UNION | KW_UNSIGNED | KW_USING
|
||||
| KW_VIRTUAL | KW_VOID | KW_VOLATILE | KW_WCHAR_T | KW_WHILE
|
||||
| KW_TYPEID | KW_TYPENAME | KW_UNDERLYING_TYPE | KW_UNION
|
||||
| KW_UNSIGNED | KW_USING | KW_VIRTUAL | KW_VOID | KW_VOLATILE
|
||||
| KW_WCHAR_T | KW_WHILE
|
||||
{
|
||||
}
|
||||
| '+' | '-' | '*' | '/' | '&' | '|' | '^' | '!' | '~' | '=' | '%'
|
||||
|
|
@ -2783,6 +3001,10 @@ no_angle_bracket_const_expr:
|
|||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
|
|
@ -3021,6 +3243,10 @@ const_expr:
|
|||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
|
|
@ -3238,6 +3464,74 @@ const_operand:
|
|||
| '[' capture_list ']' '(' function_parameter_list ')' function_post maybe_trailing_return_type '{' code '}'
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
| KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_HAS_VIRTUAL_DESTRUCTOR, $3));
|
||||
}
|
||||
| KW_IS_ABSTRACT '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ABSTRACT, $3));
|
||||
}
|
||||
| KW_IS_BASE_OF '(' full_type ',' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3, $5));
|
||||
}
|
||||
| KW_IS_CLASS '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, $3));
|
||||
}
|
||||
| KW_IS_CONSTRUCTIBLE '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3));
|
||||
}
|
||||
| KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, $3, $5));
|
||||
}
|
||||
| KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_CONVERTIBLE_TO, $3, $5));
|
||||
}
|
||||
| KW_IS_DESTRUCTIBLE '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_DESTRUCTIBLE, $3));
|
||||
}
|
||||
| KW_IS_EMPTY '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_EMPTY, $3));
|
||||
}
|
||||
| KW_IS_ENUM '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_ENUM, $3));
|
||||
}
|
||||
| KW_IS_FINAL '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FINAL, $3));
|
||||
}
|
||||
| KW_IS_FUNDAMENTAL '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_FUNDAMENTAL, $3));
|
||||
}
|
||||
| KW_IS_POD '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POD, $3));
|
||||
}
|
||||
| KW_IS_POLYMORPHIC '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_POLYMORPHIC, $3));
|
||||
}
|
||||
| KW_IS_STANDARD_LAYOUT '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_STANDARD_LAYOUT, $3));
|
||||
}
|
||||
| KW_IS_TRIVIAL '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIAL, $3));
|
||||
}
|
||||
| KW_IS_UNION '(' full_type ')'
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_UNION, $3));
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -3276,6 +3570,10 @@ formal_const_expr:
|
|||
| KW_SIZEOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
|
||||
}
|
||||
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
|
||||
{
|
||||
$$ = new CPPExpression(CPPExpression::sizeof_ellipsis_func($4));
|
||||
}
|
||||
| KW_ALIGNOF '(' full_type ')' %prec UNARY
|
||||
{
|
||||
|
|
@ -3518,6 +3816,12 @@ class_derivation_name:
|
|||
| KW_TYPENAME name
|
||||
{
|
||||
$$ = CPPType::new_type(new CPPTBDType($2));
|
||||
}
|
||||
| name ELLIPSIS
|
||||
{
|
||||
CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter($1);
|
||||
ctp->_packed = true;
|
||||
$$ = CPPType::new_type(ctp);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -3550,6 +3854,10 @@ name:
|
|||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| TYPEPACK_IDENTIFIER
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| KW_FINAL
|
||||
{
|
||||
|
|
@ -3595,6 +3903,10 @@ name_no_final:
|
|||
| TYPENAME_IDENTIFIER
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| TYPEPACK_IDENTIFIER
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| KW_OVERRIDE
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ CPPClassTemplateParameter::
|
|||
CPPClassTemplateParameter(CPPIdentifier *ident, CPPType *default_type) :
|
||||
CPPType(CPPFile()),
|
||||
_ident(ident),
|
||||
_default_type(default_type)
|
||||
_default_type(default_type),
|
||||
_packed(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -41,8 +42,15 @@ is_fully_specified() const {
|
|||
void CPPClassTemplateParameter::
|
||||
output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
|
||||
if (complete) {
|
||||
out << "class ";
|
||||
_ident->output(out, scope);
|
||||
if (_ident != NULL) {
|
||||
out << "class ";
|
||||
_ident->output(out, scope);
|
||||
} else {
|
||||
out << "class";
|
||||
}
|
||||
if (_packed) {
|
||||
out << "...";
|
||||
}
|
||||
if (_default_type) {
|
||||
out << " = ";
|
||||
_default_type->output(out, indent_level, scope, false);
|
||||
|
|
@ -82,6 +90,14 @@ is_equal(const CPPDeclaration *other) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (_packed != ot->_packed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_ident == NULL || ot->_ident == NULL) {
|
||||
return _ident == ot->_ident;
|
||||
}
|
||||
|
||||
return *_ident == *ot->_ident;
|
||||
}
|
||||
|
||||
|
|
@ -99,5 +115,13 @@ is_less(const CPPDeclaration *other) const {
|
|||
return _default_type < ot->_default_type;
|
||||
}
|
||||
|
||||
if (_packed != ot->_packed) {
|
||||
return _packed < ot->_packed;
|
||||
}
|
||||
|
||||
if (_ident == NULL || ot->_ident == NULL) {
|
||||
return _ident < ot->_ident;
|
||||
}
|
||||
|
||||
return *_ident < *ot->_ident;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ public:
|
|||
|
||||
CPPIdentifier *_ident;
|
||||
CPPType *_default_type;
|
||||
bool _packed;
|
||||
|
||||
protected:
|
||||
virtual bool is_equal(const CPPDeclaration *other) const;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,22 @@ is_tbd() const {
|
|||
return _wrapped_around->is_tbd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a fundamental type.
|
||||
*/
|
||||
bool CPPConstType::
|
||||
is_fundamental() const {
|
||||
return _wrapped_around->is_fundamental();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPConstType::
|
||||
is_standard_layout() const {
|
||||
return _wrapped_around->is_standard_layout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
|
|
@ -94,12 +110,20 @@ is_trivial() const {
|
|||
return _wrapped_around->is_trivial();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
*/
|
||||
bool CPPConstType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
return _wrapped_around->is_constructible(given_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
bool CPPConstType::
|
||||
is_default_constructible() const {
|
||||
return false;
|
||||
return _wrapped_around->is_default_constructible();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,6 +134,23 @@ is_copy_constructible() const {
|
|||
return _wrapped_around->is_copy_constructible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPConstType::
|
||||
is_destructible() const {
|
||||
return _wrapped_around->is_destructible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if variables of this type may be implicitly converted to
|
||||
* the other type.
|
||||
*/
|
||||
bool CPPConstType::
|
||||
is_convertible_to(const CPPType *other) const {
|
||||
return _wrapped_around->is_convertible_to(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a little more forgiving than is_equal(): it returns true if the
|
||||
* types appear to be referring to the same thing, even if they may have
|
||||
|
|
|
|||
|
|
@ -36,9 +36,14 @@ public:
|
|||
CPPScope *global_scope);
|
||||
|
||||
virtual bool is_tbd() const;
|
||||
virtual bool is_fundamental() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *type) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_destructible() const;
|
||||
virtual bool is_convertible_to(const CPPType *other) const;
|
||||
virtual bool is_equivalent(const CPPType &other) const;
|
||||
|
||||
virtual void output(ostream &out, int indent_level, CPPScope *scope,
|
||||
|
|
|
|||
|
|
@ -41,8 +41,13 @@ CPPDeclaration(const CPPDeclaration ©) :
|
|||
/**
|
||||
*
|
||||
*/
|
||||
CPPDeclaration::
|
||||
~CPPDeclaration() {
|
||||
CPPDeclaration &CPPDeclaration::
|
||||
operator = (const CPPDeclaration ©) {
|
||||
_vis = copy._vis;
|
||||
_template_scope = copy._template_scope;
|
||||
_file = copy._file;
|
||||
_leading_comment = copy._leading_comment;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -124,6 +129,7 @@ CPPDeclaration *CPPDeclaration::
|
|||
substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) {
|
||||
SubstDecl::const_iterator si = subst.find(this);
|
||||
if (si != subst.end()) {
|
||||
assert((*si).second != NULL);
|
||||
return (*si).second;
|
||||
}
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,9 @@ public:
|
|||
|
||||
CPPDeclaration(const CPPFile &file);
|
||||
CPPDeclaration(const CPPDeclaration ©);
|
||||
virtual ~CPPDeclaration();
|
||||
virtual ~CPPDeclaration() {};
|
||||
|
||||
CPPDeclaration &operator = (const CPPDeclaration ©);
|
||||
|
||||
bool operator == (const CPPDeclaration &other) const;
|
||||
bool operator != (const CPPDeclaration &other) const;
|
||||
|
|
@ -139,6 +141,73 @@ public:
|
|||
virtual CPPMakeProperty *as_make_property();
|
||||
virtual CPPMakeSeq *as_make_seq();
|
||||
|
||||
inline const CPPInstance *as_instance() const {
|
||||
return ((CPPDeclaration *)this)->as_instance();
|
||||
}
|
||||
inline const CPPClassTemplateParameter *as_class_template_parameter() const {
|
||||
return ((CPPDeclaration *)this)->as_class_template_parameter();
|
||||
}
|
||||
inline const CPPTypedefType *as_typedef_type() const {
|
||||
return ((CPPDeclaration *)this)->as_typedef_type();
|
||||
}
|
||||
inline const CPPTypeDeclaration *as_type_declaration() const {
|
||||
return ((CPPDeclaration *)this)->as_type_declaration();
|
||||
}
|
||||
inline const CPPExpression *as_expression() const {
|
||||
return ((CPPDeclaration *)this)->as_expression();
|
||||
}
|
||||
inline const CPPType *as_type() const {
|
||||
return ((CPPDeclaration *)this)->as_type();
|
||||
}
|
||||
inline const CPPNamespace *as_namespace() const {
|
||||
return ((CPPDeclaration *)this)->as_namespace();
|
||||
}
|
||||
inline const CPPUsing *as_using() const {
|
||||
return ((CPPDeclaration *)this)->as_using();
|
||||
}
|
||||
inline const CPPSimpleType *as_simple_type() const {
|
||||
return ((CPPDeclaration *)this)->as_simple_type();
|
||||
}
|
||||
inline const CPPPointerType *as_pointer_type() const {
|
||||
return ((CPPDeclaration *)this)->as_pointer_type();
|
||||
}
|
||||
inline const CPPReferenceType *as_reference_type() const {
|
||||
return ((CPPDeclaration *)this)->as_reference_type();
|
||||
}
|
||||
inline const CPPArrayType *as_array_type() const {
|
||||
return ((CPPDeclaration *)this)->as_array_type();
|
||||
}
|
||||
inline const CPPConstType *as_const_type() const {
|
||||
return ((CPPDeclaration *)this)->as_const_type();
|
||||
}
|
||||
inline const CPPFunctionType *as_function_type() const {
|
||||
return ((CPPDeclaration *)this)->as_function_type();
|
||||
}
|
||||
inline const CPPFunctionGroup *as_function_group() const {
|
||||
return ((CPPDeclaration *)this)->as_function_group();
|
||||
}
|
||||
inline const CPPExtensionType *as_extension_type() const {
|
||||
return ((CPPDeclaration *)this)->as_extension_type();
|
||||
}
|
||||
inline const CPPStructType *as_struct_type() const {
|
||||
return ((CPPDeclaration *)this)->as_struct_type();
|
||||
}
|
||||
inline const CPPEnumType *as_enum_type() const {
|
||||
return ((CPPDeclaration *)this)->as_enum_type();
|
||||
}
|
||||
inline const CPPTBDType *as_tbd_type() const {
|
||||
return ((CPPDeclaration *)this)->as_tbd_type();
|
||||
}
|
||||
inline const CPPTypeProxy *as_type_proxy() const {
|
||||
return ((CPPDeclaration *)this)->as_type_proxy();
|
||||
}
|
||||
inline const CPPMakeProperty *as_make_property() const {
|
||||
return ((CPPDeclaration *)this)->as_make_property();
|
||||
}
|
||||
inline const CPPMakeSeq *as_make_seq() const {
|
||||
return ((CPPDeclaration *)this)->as_make_seq();
|
||||
}
|
||||
|
||||
CPPVisibility _vis;
|
||||
CPPTemplateScope *_template_scope;
|
||||
CPPFile _file;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "cppInstance.h"
|
||||
#include "cppFunctionGroup.h"
|
||||
#include "cppFunctionType.h"
|
||||
#include "cppStructType.h"
|
||||
#include "cppBison.h"
|
||||
#include "pdtoa.h"
|
||||
|
||||
|
|
@ -389,6 +390,19 @@ typeid_op(CPPExpression *op1, CPPType *std_type_info) {
|
|||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an expression that returns a particular type trait.
|
||||
*/
|
||||
CPPExpression CPPExpression::
|
||||
type_trait(int trait, CPPType *type, CPPType *arg) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_type_trait;
|
||||
expr._u._type_trait._trait = trait;
|
||||
expr._u._type_trait._type = type;
|
||||
expr._u._type_trait._arg = arg;
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -401,6 +415,17 @@ sizeof_func(CPPType *type) {
|
|||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPExpression CPPExpression::
|
||||
sizeof_ellipsis_func(CPPIdentifier *ident) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_sizeof_ellipsis;
|
||||
expr._u._ident = ident;
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -492,13 +517,6 @@ get_delete() {
|
|||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPExpression::
|
||||
~CPPExpression() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -579,6 +597,7 @@ evaluate() const {
|
|||
case T_new:
|
||||
case T_default_new:
|
||||
case T_sizeof:
|
||||
case T_sizeof_ellipsis:
|
||||
return Result();
|
||||
|
||||
case T_alignof:
|
||||
|
|
@ -801,6 +820,95 @@ evaluate() const {
|
|||
case T_typeid_expr:
|
||||
return Result();
|
||||
|
||||
case T_type_trait:
|
||||
switch (_u._type_trait._trait) {
|
||||
case KW_HAS_VIRTUAL_DESTRUCTOR:
|
||||
{
|
||||
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
|
||||
return Result(struct_type != NULL && struct_type->has_virtual_destructor());
|
||||
}
|
||||
|
||||
case KW_IS_ABSTRACT:
|
||||
{
|
||||
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
|
||||
return Result(struct_type != NULL && struct_type->is_abstract());
|
||||
}
|
||||
|
||||
case KW_IS_BASE_OF:
|
||||
{
|
||||
CPPStructType *struct_type1 = _u._type_trait._type->as_struct_type();
|
||||
CPPStructType *struct_type2 = _u._type_trait._arg->as_struct_type();
|
||||
return Result(struct_type1 != NULL && struct_type2 != NULL && struct_type1->is_base_of(struct_type2));
|
||||
}
|
||||
|
||||
case KW_IS_CLASS:
|
||||
{
|
||||
CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
|
||||
return Result(ext_type != NULL && (
|
||||
ext_type->_type == CPPExtensionType::T_class ||
|
||||
ext_type->_type == CPPExtensionType::T_struct));
|
||||
}
|
||||
|
||||
case KW_IS_CONSTRUCTIBLE:
|
||||
if (_u._type_trait._arg == NULL) {
|
||||
return Result(_u._type_trait._type->is_default_constructible());
|
||||
} else {
|
||||
return Result(_u._type_trait._type->is_constructible(_u._type_trait._arg));
|
||||
}
|
||||
|
||||
case KW_IS_CONVERTIBLE_TO:
|
||||
assert(_u._type_trait._arg != NULL);
|
||||
return Result(_u._type_trait._type->is_convertible_to(_u._type_trait._arg));
|
||||
|
||||
case KW_IS_DESTRUCTIBLE:
|
||||
return Result(_u._type_trait._type->is_destructible());
|
||||
|
||||
case KW_IS_EMPTY:
|
||||
{
|
||||
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
|
||||
return Result(struct_type != NULL && struct_type->is_empty());
|
||||
}
|
||||
|
||||
case KW_IS_ENUM:
|
||||
return Result(_u._type_trait._type->is_enum());
|
||||
|
||||
case KW_IS_FINAL:
|
||||
{
|
||||
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
|
||||
return Result(struct_type != NULL && struct_type->is_final());
|
||||
}
|
||||
|
||||
case KW_IS_FUNDAMENTAL:
|
||||
return Result(_u._type_trait._type->is_fundamental());
|
||||
|
||||
case KW_IS_POD:
|
||||
return Result(_u._type_trait._type->is_trivial() &&
|
||||
_u._type_trait._type->is_standard_layout());
|
||||
|
||||
case KW_IS_POLYMORPHIC:
|
||||
{
|
||||
CPPStructType *struct_type = _u._type_trait._type->as_struct_type();
|
||||
return Result(struct_type != NULL && struct_type->is_polymorphic());
|
||||
}
|
||||
|
||||
case KW_IS_STANDARD_LAYOUT:
|
||||
return Result(_u._type_trait._type->is_standard_layout());
|
||||
|
||||
case KW_IS_TRIVIAL:
|
||||
return Result(_u._type_trait._type->is_trivial());
|
||||
|
||||
case KW_IS_UNION:
|
||||
{
|
||||
CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
|
||||
return Result(ext_type != NULL &&
|
||||
ext_type->_type == CPPExtensionType::T_union);
|
||||
}
|
||||
|
||||
default:
|
||||
cerr << "**unexpected type trait**\n";
|
||||
abort();
|
||||
}
|
||||
|
||||
default:
|
||||
cerr << "**invalid operand**\n";
|
||||
abort();
|
||||
|
|
@ -916,6 +1024,7 @@ determine_type() const {
|
|||
return CPPType::new_type(new CPPPointerType(_u._typecast._to));
|
||||
|
||||
case T_sizeof:
|
||||
case T_sizeof_ellipsis:
|
||||
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
|
||||
|
|
@ -1057,6 +1166,9 @@ determine_type() const {
|
|||
case T_typeid_expr:
|
||||
return _u._typeid._std_type_info;
|
||||
|
||||
case T_type_trait:
|
||||
return bool_type;
|
||||
|
||||
default:
|
||||
cerr << "**invalid operand**\n";
|
||||
abort();
|
||||
|
|
@ -1113,6 +1225,9 @@ is_fully_specified() const {
|
|||
case T_alignof:
|
||||
return _u._typecast._to->is_fully_specified();
|
||||
|
||||
case T_sizeof_ellipsis:
|
||||
return _u._ident->is_fully_specified();
|
||||
|
||||
case T_trinary_operation:
|
||||
if (!_u._op._op3->is_fully_specified()) {
|
||||
return false;
|
||||
|
|
@ -1141,6 +1256,9 @@ is_fully_specified() const {
|
|||
case T_typeid_expr:
|
||||
return _u._typeid._expr->is_fully_specified();
|
||||
|
||||
case T_type_trait:
|
||||
return _u._type_trait._type->is_fully_specified();
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1276,6 +1394,13 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
|||
any_changed = any_changed || (rep->_u._typeid._expr != _u._typeid._expr);
|
||||
break;
|
||||
|
||||
case T_type_trait:
|
||||
rep->_u._type_trait._type =
|
||||
_u._type_trait._type->substitute_decl(subst, current_scope, global_scope)
|
||||
->as_type();
|
||||
any_changed = any_changed || (rep->_u._type_trait._type != _u._type_trait._type);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1350,6 +1475,9 @@ is_tbd() const {
|
|||
case T_typeid_expr:
|
||||
return _u._typeid._expr->is_tbd();
|
||||
|
||||
case T_type_trait:
|
||||
return _u._type_trait._type->is_tbd();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1541,6 +1669,12 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
out << ")";
|
||||
break;
|
||||
|
||||
case T_sizeof_ellipsis:
|
||||
out << "sizeof...(";
|
||||
_u._ident->output(out, scope);
|
||||
out << ")";
|
||||
break;
|
||||
|
||||
case T_alignof:
|
||||
out << "alignof(";
|
||||
_u._typecast._to->output(out, indent_level, scope, false);
|
||||
|
|
@ -1753,6 +1887,65 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
|||
out << "delete";
|
||||
break;
|
||||
|
||||
case T_type_trait:
|
||||
switch (_u._type_trait._trait) {
|
||||
case KW_HAS_VIRTUAL_DESTRUCTOR:
|
||||
out << "__has_virtual_destructor";
|
||||
break;
|
||||
case KW_IS_ABSTRACT:
|
||||
out << "__is_abstract";
|
||||
break;
|
||||
case KW_IS_BASE_OF:
|
||||
out << "__is_base_of";
|
||||
break;
|
||||
case KW_IS_CLASS:
|
||||
out << "__is_class";
|
||||
break;
|
||||
case KW_IS_CONSTRUCTIBLE:
|
||||
out << "__is_constructible";
|
||||
break;
|
||||
case KW_IS_CONVERTIBLE_TO:
|
||||
out << "__is_convertible_to";
|
||||
break;
|
||||
case KW_IS_DESTRUCTIBLE:
|
||||
out << "__is_destructible";
|
||||
break;
|
||||
case KW_IS_EMPTY:
|
||||
out << "__is_empty";
|
||||
break;
|
||||
case KW_IS_ENUM:
|
||||
out << "__is_enum";
|
||||
break;
|
||||
case KW_IS_FINAL:
|
||||
out << "__is_final";
|
||||
break;
|
||||
case KW_IS_FUNDAMENTAL:
|
||||
out << "__is_fundamental";
|
||||
break;
|
||||
case KW_IS_POD:
|
||||
out << "__is_pod";
|
||||
break;
|
||||
case KW_IS_POLYMORPHIC:
|
||||
out << "__is_polymorphic";
|
||||
break;
|
||||
case KW_IS_STANDARD_LAYOUT:
|
||||
out << "__is_standard_layout";
|
||||
break;
|
||||
case KW_IS_TRIVIAL:
|
||||
out << "__is_trivial";
|
||||
break;
|
||||
case KW_IS_UNION:
|
||||
out << "__is_union";
|
||||
break;
|
||||
default:
|
||||
out << (evaluate().as_boolean() ? "true" : "false");
|
||||
return;
|
||||
}
|
||||
out << '(';
|
||||
_u._type_trait._type->output(out, indent_level, scope, false);
|
||||
out << ')';
|
||||
break;
|
||||
|
||||
default:
|
||||
out << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
|
@ -1864,6 +2057,7 @@ is_equal(const CPPDeclaration *other) const {
|
|||
return _u._fgroup == ot->_u._fgroup;
|
||||
|
||||
case T_unknown_ident:
|
||||
case T_sizeof_ellipsis:
|
||||
return *_u._ident == *ot->_u._ident;
|
||||
|
||||
case T_typecast:
|
||||
|
|
@ -1907,6 +2101,10 @@ is_equal(const CPPDeclaration *other) const {
|
|||
case T_typeid_expr:
|
||||
return _u._typeid._expr == ot->_u._typeid._expr;
|
||||
|
||||
case T_type_trait:
|
||||
return _u._type_trait._trait == ot->_u._type_trait._trait &&
|
||||
_u._type_trait._type == ot->_u._type_trait._type;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
|
@ -1954,6 +2152,7 @@ is_less(const CPPDeclaration *other) const {
|
|||
return *_u._fgroup < *ot->_u._fgroup;
|
||||
|
||||
case T_unknown_ident:
|
||||
case T_sizeof_ellipsis:
|
||||
return *_u._ident < *ot->_u._ident;
|
||||
|
||||
case T_typecast:
|
||||
|
|
@ -2007,6 +2206,12 @@ is_less(const CPPDeclaration *other) const {
|
|||
case T_typeid_expr:
|
||||
return *_u._typeid._expr < *ot->_u._typeid._expr;
|
||||
|
||||
case T_type_trait:
|
||||
if (_u._type_trait._trait != ot->_u._type_trait._trait) {
|
||||
return _u._type_trait._trait < ot->_u._type_trait._trait;
|
||||
}
|
||||
return *_u._type_trait._type < *ot->_u._type_trait._type;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public:
|
|||
T_new,
|
||||
T_default_new,
|
||||
T_sizeof,
|
||||
T_sizeof_ellipsis,
|
||||
T_alignof,
|
||||
T_unary_operation,
|
||||
T_binary_operation,
|
||||
|
|
@ -59,6 +60,7 @@ public:
|
|||
T_raw_literal,
|
||||
T_typeid_type,
|
||||
T_typeid_expr,
|
||||
T_type_trait,
|
||||
|
||||
// These are used when parsing =default and =delete methods.
|
||||
T_default,
|
||||
|
|
@ -81,7 +83,9 @@ public:
|
|||
static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
|
||||
static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info);
|
||||
static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
|
||||
static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = NULL);
|
||||
static CPPExpression sizeof_func(CPPType *type);
|
||||
static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
|
||||
static CPPExpression alignof_func(CPPType *type);
|
||||
|
||||
static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
|
||||
|
|
@ -93,8 +97,6 @@ public:
|
|||
static const CPPExpression &get_default();
|
||||
static const CPPExpression &get_delete();
|
||||
|
||||
~CPPExpression();
|
||||
|
||||
enum ResultType {
|
||||
RT_integer,
|
||||
RT_real,
|
||||
|
|
@ -170,6 +172,11 @@ public:
|
|||
CPPInstance *_operator;
|
||||
CPPExpression *_value;
|
||||
} _literal;
|
||||
struct {
|
||||
int _trait;
|
||||
CPPType *_type;
|
||||
CPPType *_arg;
|
||||
} _type_trait;
|
||||
} _u;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -87,12 +87,32 @@ is_tbd() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPExtensionType::
|
||||
is_standard_layout() const {
|
||||
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
bool CPPExtensionType::
|
||||
is_trivial() const {
|
||||
return (_type == T_enum);
|
||||
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
*/
|
||||
bool CPPExtensionType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
if (_type == T_enum || _type == T_enum_class || _type == T_enum_struct) {
|
||||
const CPPExtensionType *other = ((CPPType *)given_type)->remove_reference()->remove_const()->as_extension_type();
|
||||
return other != NULL && is_equal(other);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -100,7 +120,7 @@ is_trivial() const {
|
|||
*/
|
||||
bool CPPExtensionType::
|
||||
is_default_constructible() const {
|
||||
return (_type == T_enum);
|
||||
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -108,7 +128,7 @@ is_default_constructible() const {
|
|||
*/
|
||||
bool CPPExtensionType::
|
||||
is_copy_constructible() const {
|
||||
return (_type == T_enum);
|
||||
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ public:
|
|||
|
||||
virtual bool is_incomplete() const;
|
||||
virtual bool is_tbd() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *type) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -89,9 +89,11 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
|||
}
|
||||
|
||||
CPPFunctionType *rep = new CPPFunctionType(*this);
|
||||
rep->_return_type =
|
||||
_return_type->substitute_decl(subst, current_scope, global_scope)
|
||||
->as_type();
|
||||
if (_return_type != NULL) {
|
||||
rep->_return_type =
|
||||
_return_type->substitute_decl(subst, current_scope, global_scope)
|
||||
->as_type();
|
||||
}
|
||||
|
||||
rep->_parameters =
|
||||
_parameters->substitute_decl(subst, current_scope, global_scope);
|
||||
|
|
@ -265,6 +267,9 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
|
|||
if (_flags & F_const_method) {
|
||||
out << " const";
|
||||
}
|
||||
if (_flags & F_volatile_method) {
|
||||
out << " volatile";
|
||||
}
|
||||
if (_flags & F_noexcept) {
|
||||
out << " noexcept";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ public:
|
|||
F_trailing_return_type = 0x800,
|
||||
F_final = 0x1000,
|
||||
F_override = 0x2000,
|
||||
F_volatile_method = 0x4000,
|
||||
F_lvalue_method = 0x8000,
|
||||
F_rvalue_method = 0x10000,
|
||||
};
|
||||
|
||||
CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
|
|||
// anyway.
|
||||
}
|
||||
|
||||
if (ii->_packed) {
|
||||
_storage_class |= SC_parameter_pack;
|
||||
}
|
||||
|
||||
delete ii;
|
||||
}
|
||||
|
||||
|
|
@ -353,11 +357,7 @@ check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) {
|
|||
CPPReferenceType *ref_type = param_type->as_reference_type();
|
||||
|
||||
if (ref_type != NULL) {
|
||||
param_type = ref_type->_pointing_at;
|
||||
|
||||
if (param_type->get_subtype() == CPPDeclaration::ST_const) {
|
||||
param_type = param_type->as_const_type()->_wrapped_around;
|
||||
}
|
||||
param_type = ref_type->_pointing_at->remove_cv();
|
||||
|
||||
if (class_name == param_type->get_simple_name()) {
|
||||
if (ref_type->_value_category == CPPReferenceType::VC_rvalue) {
|
||||
|
|
@ -563,6 +563,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
|
|||
if (_ident != NULL) {
|
||||
name = _ident->get_local_name(scope);
|
||||
}
|
||||
if (_storage_class & SC_parameter_pack) {
|
||||
name = "..." + name;
|
||||
}
|
||||
|
||||
if (_type->as_function_type()) {
|
||||
_type->as_function_type()->
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ public:
|
|||
// This isn't really a storage class. It's only used temporarily by the
|
||||
// parser, to make parsing specifier sequences a bit easier.
|
||||
SC_const = 0x20000,
|
||||
|
||||
// Used to indicate that this is a parameter pack.
|
||||
SC_parameter_pack = 0x40000,
|
||||
};
|
||||
|
||||
CPPInstance(CPPType *type, const string &name, int storage_class = 0);
|
||||
|
|
|
|||
|
|
@ -26,12 +26,11 @@
|
|||
*/
|
||||
CPPInstanceIdentifier::Modifier::
|
||||
Modifier(CPPInstanceIdentifierType type) :
|
||||
_type(type)
|
||||
{
|
||||
_func_params = NULL;
|
||||
_func_flags = 0;
|
||||
_scoping = NULL;
|
||||
_expr = NULL;
|
||||
_type(type),
|
||||
_func_params(NULL),
|
||||
_func_flags(0),
|
||||
_scoping(NULL),
|
||||
_expr(NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -83,7 +82,8 @@ initializer_type(CPPParameterList *params) {
|
|||
CPPInstanceIdentifier::
|
||||
CPPInstanceIdentifier(CPPIdentifier *ident) :
|
||||
_ident(ident),
|
||||
_bit_width(-1) {
|
||||
_bit_width(-1),
|
||||
_packed(false) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -88,8 +88,12 @@ public:
|
|||
typedef vector<Modifier> Modifiers;
|
||||
Modifiers _modifiers;
|
||||
|
||||
// If not -1, indicates a bitfield
|
||||
int _bit_width;
|
||||
|
||||
// Indicates a parameter pack
|
||||
bool _packed;
|
||||
|
||||
private:
|
||||
CPPType *
|
||||
r_unroll_type(CPPType *start_type, Modifiers::const_iterator mi);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
#include "cppPointerType.h"
|
||||
#include "cppFunctionType.h"
|
||||
#include "cppIdentifier.h"
|
||||
#include "cppArrayType.h"
|
||||
#include "cppStructType.h"
|
||||
#include "cppSimpleType.h"
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -88,6 +91,14 @@ is_tbd() const {
|
|||
return _pointing_at->is_tbd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPPointerType::
|
||||
is_standard_layout() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
|
|
@ -96,6 +107,60 @@ is_trivial() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
*/
|
||||
bool CPPPointerType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
given_type = ((CPPType *)given_type)->remove_reference()->remove_cv();
|
||||
|
||||
// Can convert from compatible pointer or array type.
|
||||
CPPType *other_target;
|
||||
switch (given_type->get_subtype()) {
|
||||
case ST_array:
|
||||
other_target = given_type->as_array_type()->_element_type;
|
||||
break;
|
||||
|
||||
case ST_pointer:
|
||||
other_target = given_type->as_pointer_type()->_pointing_at;
|
||||
break;
|
||||
|
||||
case ST_simple:
|
||||
// Can initialize from nullptr.
|
||||
return given_type->as_simple_type()->_type == CPPSimpleType::T_nullptr;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't convert const to non-const pointer.
|
||||
if (other_target->is_const() && !_pointing_at->is_const()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Are we pointing to the same type? That's always OK.
|
||||
const CPPType *a = _pointing_at->remove_cv();
|
||||
const CPPType *b = other_target->remove_cv();
|
||||
if (a == b || *a == *b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can initialize void pointer with any pointer.
|
||||
const CPPSimpleType *simple_type = a->as_simple_type();
|
||||
if (simple_type != NULL) {
|
||||
return simple_type->_type == CPPSimpleType::T_void;
|
||||
}
|
||||
|
||||
// Can initialize from derived class pointer.
|
||||
const CPPStructType *a_struct = a->as_struct_type();
|
||||
const CPPStructType *b_struct = b->as_struct_type();
|
||||
if (a_struct != NULL && b_struct != NULL) {
|
||||
return a_struct->is_base_of(b_struct);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ public:
|
|||
CPPScope *global_scope);
|
||||
|
||||
virtual bool is_tbd() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *other) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_equivalent(const CPPType &other) const;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "cppIdentifier.h"
|
||||
#include "cppTemplateScope.h"
|
||||
#include "cppTemplateParameterList.h"
|
||||
#include "cppClassTemplateParameter.h"
|
||||
#include "cppConstType.h"
|
||||
#include "cppFunctionGroup.h"
|
||||
#include "cppFunctionType.h"
|
||||
|
|
@ -416,7 +417,14 @@ get_next_token0() {
|
|||
int token_type = IDENTIFIER;
|
||||
CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope);
|
||||
if (decl != NULL && decl->as_type() != NULL) {
|
||||
token_type = TYPENAME_IDENTIFIER;
|
||||
// We need to see type pack template parameters as a different type of
|
||||
// identifier to resolve a parser ambiguity.
|
||||
CPPClassTemplateParameter *ctp = decl->as_class_template_parameter();
|
||||
if (ctp && ctp->_packed) {
|
||||
token_type = TYPEPACK_IDENTIFIER;
|
||||
} else {
|
||||
token_type = TYPENAME_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
_last_token_loc = loc;
|
||||
|
|
@ -2451,11 +2459,27 @@ check_keyword(const string &name) {
|
|||
if (name == "friend") return KW_FRIEND;
|
||||
if (name == "for") return KW_FOR;
|
||||
if (name == "goto") return KW_GOTO;
|
||||
if (name == "__has_virtual_destructor") return KW_HAS_VIRTUAL_DESTRUCTOR;
|
||||
if (name == "if") return KW_IF;
|
||||
if (name == "inline") return KW_INLINE;
|
||||
if (name == "__inline") return KW_INLINE;
|
||||
if (name == "__inline__") return KW_INLINE;
|
||||
if (name == "int") return KW_INT;
|
||||
if (name == "__is_abstract") return KW_IS_ABSTRACT;
|
||||
if (name == "__is_base_of") return KW_IS_BASE_OF;
|
||||
if (name == "__is_class") return KW_IS_CLASS;
|
||||
if (name == "__is_constructible") return KW_IS_CONSTRUCTIBLE;
|
||||
if (name == "__is_convertible_to") return KW_IS_CONVERTIBLE_TO;
|
||||
if (name == "__is_destructible") return KW_IS_DESTRUCTIBLE;
|
||||
if (name == "__is_empty") return KW_IS_EMPTY;
|
||||
if (name == "__is_enum") return KW_IS_ENUM;
|
||||
if (name == "__is_final") return KW_IS_FINAL;
|
||||
if (name == "__is_fundamental") return KW_IS_FUNDAMENTAL;
|
||||
if (name == "__is_pod") return KW_IS_POD;
|
||||
if (name == "__is_polymorphic") return KW_IS_POLYMORPHIC;
|
||||
if (name == "__is_standard_layout") return KW_IS_STANDARD_LAYOUT;
|
||||
if (name == "__is_trivial") return KW_IS_TRIVIAL;
|
||||
if (name == "__is_union") return KW_IS_UNION;
|
||||
if (name == "long") return KW_LONG;
|
||||
if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY;
|
||||
if (name == "__make_property") return KW_MAKE_PROPERTY;
|
||||
|
|
@ -2490,6 +2514,7 @@ check_keyword(const string &name) {
|
|||
if (name == "typedef") return KW_TYPEDEF;
|
||||
if (name == "typeid") return KW_TYPEID;
|
||||
if (name == "typename") return KW_TYPENAME;
|
||||
if (name == "__underlying_type") return KW_UNDERLYING_TYPE;
|
||||
if (name == "union") return KW_UNION;
|
||||
if (name == "unsigned") return KW_UNSIGNED;
|
||||
if (name == "using") return KW_USING;
|
||||
|
|
@ -2751,7 +2776,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
|
|||
_parsing_template_params = true;
|
||||
|
||||
CPPToken token = internal_get_next_token();
|
||||
if (token._token == '>') {
|
||||
if (token._token == '>' || token._token == 0) {
|
||||
_parsing_template_params = false;
|
||||
} else {
|
||||
_saved_tokens.push_back(token);
|
||||
|
|
@ -2760,36 +2785,53 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) {
|
|||
CPPTemplateParameterList *actual_params = new CPPTemplateParameterList;
|
||||
|
||||
for (pi = formal_params._parameters.begin();
|
||||
pi != formal_params._parameters.end() && _parsing_template_params;
|
||||
++pi) {
|
||||
pi != formal_params._parameters.end() && _parsing_template_params;) {
|
||||
CPPToken token = peek_next_token();
|
||||
YYLTYPE loc = token._lloc;
|
||||
|
||||
CPPDeclaration *decl = (*pi);
|
||||
if (decl->as_type()) {
|
||||
CPPClassTemplateParameter *param = decl->as_class_template_parameter();
|
||||
CPPInstance *inst = decl->as_instance();
|
||||
if (param) {
|
||||
// Parse a typename template parameter.
|
||||
_saved_tokens.push_back(CPPToken(START_TYPE));
|
||||
CPPType *type = ::parse_type(this, current_scope, global_scope);
|
||||
if (type == NULL) {
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number() - 1;
|
||||
warning("Invalid type", loc);
|
||||
warning("invalid type", loc);
|
||||
skip_to_end_nested();
|
||||
type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
|
||||
}
|
||||
actual_params->_parameters.push_back(type);
|
||||
} else {
|
||||
|
||||
// If this is a variadic template, keep reading using this parameter.
|
||||
if (!param->_packed) {
|
||||
++pi;
|
||||
}
|
||||
} else if (inst) {
|
||||
// Parse a constant expression template parameter.
|
||||
_saved_tokens.push_back(CPPToken(START_CONST_EXPR));
|
||||
CPPExpression *expr = parse_const_expr(this, current_scope, global_scope);
|
||||
if (expr == NULL) {
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number() - 1;
|
||||
warning("Invalid expression", loc);
|
||||
warning("invalid expression", loc);
|
||||
skip_to_end_nested();
|
||||
expr = new CPPExpression(0);
|
||||
}
|
||||
actual_params->_parameters.push_back(expr);
|
||||
|
||||
// If this is a variadic template, keep reading using this parameter.
|
||||
if ((inst->_storage_class & CPPInstance::SC_parameter_pack) == 0) {
|
||||
++pi;
|
||||
}
|
||||
} else {
|
||||
loc.last_line = get_line_number();
|
||||
loc.last_column = get_col_number() - 1;
|
||||
warning("invalid template parameter", loc);
|
||||
skip_to_end_nested();
|
||||
++pi;
|
||||
}
|
||||
|
||||
_state = S_nested;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
*/
|
||||
|
||||
#include "cppReferenceType.h"
|
||||
#include "cppTypedefType.h"
|
||||
#include "cppStructType.h"
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -87,6 +89,14 @@ is_tbd() const {
|
|||
return _pointing_at->is_tbd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPReferenceType::
|
||||
is_standard_layout() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
|
|
@ -95,6 +105,67 @@ is_trivial() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
*/
|
||||
bool CPPReferenceType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
const CPPType *a;
|
||||
const CPPType *b;
|
||||
|
||||
CPPReferenceType *ref_type = ((CPPType *)given_type)->as_reference_type();
|
||||
if (ref_type != NULL) {
|
||||
if (ref_type->_value_category == VC_rvalue) {
|
||||
return is_constructible(ref_type->_pointing_at);
|
||||
}
|
||||
|
||||
if (_value_category == VC_rvalue) {
|
||||
// Can never initialize an rvalue ref from an lvalue ref.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_pointing_at->is_const()) {
|
||||
// Cannot initialize a non-const reference using a const one.
|
||||
if (ref_type->_pointing_at->is_const()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
a = _pointing_at->remove_cv();
|
||||
b = ref_type->_pointing_at->remove_cv();
|
||||
|
||||
} else {
|
||||
// Initializing using an rvalue.
|
||||
if (!_pointing_at->is_const()) {
|
||||
// Cannot initialize a non-const reference using a const one.
|
||||
if (given_type->is_const()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cannot initalise a non-const lvalue reference with an rvalue ref.
|
||||
if (_value_category == VC_lvalue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
a = _pointing_at->remove_cv();
|
||||
b = ((CPPType *)given_type)->remove_cv();
|
||||
}
|
||||
|
||||
if (a == b || *a == *b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can initialize from derived class pointer.
|
||||
const CPPStructType *a_struct = a->as_struct_type();
|
||||
const CPPStructType *b_struct = b->as_struct_type();
|
||||
if (a_struct != NULL && b_struct != NULL) {
|
||||
return a_struct->is_base_of(b_struct);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
|
|
@ -111,6 +182,14 @@ is_copy_constructible() const {
|
|||
return (_value_category == VC_lvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPReferenceType::
|
||||
is_destructible() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a little more forgiving than is_equal(): it returns true if the
|
||||
* types appear to be referring to the same thing, even if they may have
|
||||
|
|
|
|||
|
|
@ -42,9 +42,12 @@ public:
|
|||
CPPScope *global_scope);
|
||||
|
||||
virtual bool is_tbd() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *type) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_destructible() const;
|
||||
virtual bool is_equivalent(const CPPType &other) const;
|
||||
|
||||
virtual void output(ostream &out, int indent_level, CPPScope *scope,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include "cppPreprocessor.h"
|
||||
#include "cppTemplateScope.h"
|
||||
#include "cppClassTemplateParameter.h"
|
||||
#include "cppConstType.h"
|
||||
#include "cppFunctionType.h"
|
||||
#include "cppUsing.h"
|
||||
#include "cppBisonDefs.h"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,30 @@ is_tbd() const {
|
|||
return (_type == T_unknown);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is a boolean, floating point or integral type.
|
||||
*/
|
||||
bool CPPSimpleType::
|
||||
is_arithmetic() const {
|
||||
return (_type > T_unknown && _type < T_void);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a fundamental type.
|
||||
*/
|
||||
bool CPPSimpleType::
|
||||
is_fundamental() const {
|
||||
return (_type != T_unknown && _type != T_parameter && _type != T_auto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPSimpleType::
|
||||
is_standard_layout() const {
|
||||
return (_type != T_unknown && _type != T_parameter && _type != T_auto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
|
|
@ -42,6 +66,27 @@ is_trivial() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
*/
|
||||
bool CPPSimpleType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
given_type = ((CPPType *)given_type)->remove_reference()->remove_cv();
|
||||
|
||||
const CPPSimpleType *simple_type = given_type->as_simple_type();
|
||||
if (simple_type == NULL) {
|
||||
return given_type->is_enum() && is_arithmetic();
|
||||
} else if (_type == T_nullptr) {
|
||||
return simple_type->_type == T_nullptr;
|
||||
} else if (_type == T_bool) {
|
||||
return simple_type->is_arithmetic() || simple_type->_type == T_nullptr;
|
||||
} else if (is_arithmetic()) {
|
||||
return simple_type->is_arithmetic();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
|
|
@ -58,6 +103,14 @@ is_copy_constructible() const {
|
|||
return (_type != T_void);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPSimpleType::
|
||||
is_destructible() const {
|
||||
return (_type != T_void);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is a special parameter expression type.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#include "cppType.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a C++ fundamental type.
|
||||
*/
|
||||
class CPPSimpleType : public CPPType {
|
||||
public:
|
||||
|
|
@ -40,12 +40,11 @@ public:
|
|||
// 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: int foo(0); which really means the same thing
|
||||
* as: int foo = 0; but it initially looks like a function prototype.
|
||||
*/
|
||||
// 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: int foo(0); which really means the
|
||||
// same thing as: int foo = 0; but it initially looks like a function
|
||||
// prototype.
|
||||
T_parameter,
|
||||
|
||||
// T_auto is also a special type that corresponds to the "auto" keyword
|
||||
|
|
@ -69,9 +68,14 @@ public:
|
|||
int _flags;
|
||||
|
||||
virtual bool is_tbd() const;
|
||||
bool is_arithmetic() const;
|
||||
virtual bool is_fundamental() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *type) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_destructible() const;
|
||||
virtual bool is_parameter_expr() const;
|
||||
|
||||
virtual string get_preferred_name() const;
|
||||
|
|
|
|||
|
|
@ -126,16 +126,154 @@ is_abstract() const {
|
|||
return !funcs.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this struct declaration is a base class of the other given
|
||||
* class, or the same class.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_base_of(const CPPStructType *other) const {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
Derivation::const_iterator di;
|
||||
for (di = other->_derivation.begin(); di != other->_derivation.end(); ++di) {
|
||||
const CPPStructType *base = (*di)._base->as_struct_type();
|
||||
if (base != NULL && is_base_of(base)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this struct declaration defines no non-static data members
|
||||
* other than bit-fields of size 0, no virtual functions, no virtual base
|
||||
* classes, and no non-empty base classes, and is not a union.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_empty() const {
|
||||
if (_type == T_union) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (check_virtual()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure all base classes are empty and non-virtual.
|
||||
Derivation::const_iterator di;
|
||||
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
|
||||
CPPStructType *base = (*di)._base->as_struct_type();
|
||||
if ((*di)._is_virtual || (base != NULL && !base->is_empty())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there are no non-static data members.
|
||||
CPPScope::Variables::const_iterator vi;
|
||||
for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
|
||||
CPPInstance *instance = (*vi).second;
|
||||
assert(instance != NULL);
|
||||
|
||||
if (instance->_storage_class & CPPInstance::SC_static) {
|
||||
// Static members don't count.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only members with a bit width of 0 are okay.
|
||||
if (instance->_bit_width != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class or any of its base classes have virtual methods.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_polymorphic() const {
|
||||
if (_type == T_union) {
|
||||
return false;
|
||||
}
|
||||
return check_virtual();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_standard_layout() const {
|
||||
assert(_scope != NULL);
|
||||
|
||||
CPPVisibility member_vis = V_unknown;
|
||||
|
||||
// Make sure all data members have the same vis and are standard layout.
|
||||
CPPScope::Variables::const_iterator vi;
|
||||
for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
|
||||
CPPInstance *instance = (*vi).second;
|
||||
assert(instance != NULL);
|
||||
|
||||
if (instance->_storage_class & CPPInstance::SC_static) {
|
||||
// Static members don't count.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Finally, check if the data member itself is standard layout.
|
||||
assert(instance->_type != NULL);
|
||||
if (!instance->_type->is_standard_layout()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (member_vis == V_unknown) {
|
||||
// The first non-static data member may not be a base class.
|
||||
CPPStructType *struct_type = instance->_type->remove_cv()->as_struct_type();
|
||||
if (struct_type != NULL && struct_type->is_base_of(this)) {
|
||||
return false;
|
||||
}
|
||||
member_vis = instance->_vis;
|
||||
|
||||
} else if (member_vis != instance->_vis) {
|
||||
// All members need to have the same access control.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all base classes are standard-layout and non-virtual.
|
||||
Derivation::const_iterator di;
|
||||
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
|
||||
CPPStructType *base = (*di)._base->as_struct_type();
|
||||
if ((*di)._is_virtual) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this class had instance members, all base classes need to be empty.
|
||||
if (member_vis != V_unknown) {
|
||||
if (!base->is_empty()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!base->is_standard_layout()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we have no virtual functions.
|
||||
return !check_virtual();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_trivial() const {
|
||||
// Make sure all base classes are trivial.
|
||||
// Make sure all base classes are trivial and non-virtual.
|
||||
Derivation::const_iterator di;
|
||||
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
|
||||
CPPStructType *base = (*di)._base->as_struct_type();
|
||||
if (base != NULL && !base->is_trivial()) {
|
||||
if ((*di)._is_virtual || (base != NULL && !base->is_trivial())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +304,7 @@ is_trivial() const {
|
|||
}
|
||||
}
|
||||
|
||||
// Now look for functions that are virtual or condestructors.
|
||||
// Now look for functions that are virtual or con/destructors.
|
||||
bool is_default_constructible = true;
|
||||
CPPScope::Functions::const_iterator fi;
|
||||
for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
|
||||
|
|
@ -193,8 +331,8 @@ is_trivial() const {
|
|||
if (ftype->_flags & (CPPFunctionType::F_destructor |
|
||||
CPPFunctionType::F_move_constructor |
|
||||
CPPFunctionType::F_copy_constructor)) {
|
||||
// User-provided destructors and copymove constructors are not trivial
|
||||
// unless they are defaulted (and not virtual).
|
||||
// User-provided destructors and copy/move constructors are not
|
||||
// trivial unless they are defaulted (and not virtual).
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -220,6 +358,62 @@ is_trivial() const {
|
|||
return is_default_constructible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
* This implementation is rudimentary, as it does not attempt to follow all of
|
||||
* the implicit type conversion rules, but it is still useful.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
// Does the type match the copy constructor or move constructor?
|
||||
CPPType *base_type = ((CPPType *)given_type)->remove_reference();
|
||||
if (is_equivalent(*base_type->remove_cv())) {
|
||||
const CPPReferenceType *ref_type = given_type->as_reference_type();
|
||||
if (ref_type == NULL ||
|
||||
ref_type->_value_category == CPPReferenceType::VC_rvalue) {
|
||||
return is_move_constructible(V_public);
|
||||
} else {
|
||||
return is_copy_constructible(V_public);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a different constructor.
|
||||
CPPFunctionGroup *fgroup = get_constructor();
|
||||
if (fgroup != (CPPFunctionGroup *)NULL) {
|
||||
CPPFunctionGroup::Instances::const_iterator ii;
|
||||
for (ii = fgroup->_instances.begin();
|
||||
ii != fgroup->_instances.end();
|
||||
++ii) {
|
||||
CPPInstance *inst = (*ii);
|
||||
assert(inst->_type != (CPPType *)NULL);
|
||||
|
||||
CPPFunctionType *ftype = inst->_type->as_function_type();
|
||||
assert(ftype != (CPPFunctionType *)NULL);
|
||||
|
||||
CPPParameterList *params = ftype->_parameters;
|
||||
if (params->_parameters.size() == 1 && !params->_includes_ellipsis) {
|
||||
CPPType *param_type = params->_parameters[0]->_type->remove_reference();
|
||||
|
||||
if (!param_type->is_const() && base_type->is_const()) {
|
||||
// Can't pass a const object to a function taking a non-const.
|
||||
continue;
|
||||
}
|
||||
|
||||
// It's deleted, anyhow.
|
||||
if ((inst->_storage_class & CPPInstance::SC_deleted) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param_type->is_equivalent(*base_type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
|
|
@ -236,6 +430,14 @@ is_copy_constructible() const {
|
|||
return is_copy_constructible(V_public);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_destructible() const {
|
||||
return is_destructible(V_public);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
|
|
@ -399,6 +601,139 @@ is_copy_constructible(CPPVisibility min_vis) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is move-constructible.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_move_constructible(CPPVisibility min_vis) const {
|
||||
CPPInstance *constructor = get_move_constructor();
|
||||
if (constructor != (CPPInstance *)NULL) {
|
||||
// It has a user-declared move constructor.
|
||||
if (constructor->_vis > min_vis) {
|
||||
// Inaccessible move constructor.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (constructor->_storage_class & CPPInstance::SC_deleted) {
|
||||
// It is deleted.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return is_copy_constructible(min_vis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_destructible(CPPVisibility min_vis) const {
|
||||
// Do we have an explicit destructor?
|
||||
CPPInstance *destructor = get_destructor();
|
||||
if (destructor != (CPPInstance *)NULL) {
|
||||
if (destructor->_vis > min_vis) {
|
||||
// Yes, but it's inaccessible.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (destructor->_storage_class & CPPInstance::SC_deleted) {
|
||||
// Yes, but it's explicitly been deleted.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure all base classes are destructible.
|
||||
Derivation::const_iterator di;
|
||||
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
|
||||
CPPStructType *base = (*di)._base->as_struct_type();
|
||||
if (base != NULL && !base->is_destructible(V_protected)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
assert(_scope != NULL);
|
||||
|
||||
// Make sure all members are destructible.
|
||||
CPPScope::Variables::const_iterator vi;
|
||||
for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
|
||||
CPPInstance *instance = (*vi).second;
|
||||
assert(instance != NULL);
|
||||
|
||||
if (instance->_storage_class & CPPInstance::SC_static) {
|
||||
// Static members don't count.
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the data member is not destructible, no go.
|
||||
assert(instance->_type != NULL);
|
||||
if (!instance->_type->is_destructible()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if variables of this type may be implicitly converted to
|
||||
* the other type.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
is_convertible_to(const CPPType *other) const {
|
||||
if (CPPType::is_convertible_to(other)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all typecast operators to see whether we can cast to a type that is
|
||||
// convertible to the other type.
|
||||
CPPScope::Functions::const_iterator fi;
|
||||
for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
|
||||
CPPFunctionGroup *fgroup = (*fi).second;
|
||||
|
||||
CPPFunctionGroup::Instances::const_iterator ii;
|
||||
for (ii = fgroup->_instances.begin(); ii != fgroup->_instances.end(); ++ii) {
|
||||
CPPInstance *inst = (*ii);
|
||||
|
||||
if (inst->_storage_class & (CPPInstance::SC_deleted | CPPInstance::SC_static | CPPInstance::SC_explicit)) {
|
||||
// Exclude static/deleted/explicit methods.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Also, the instance needs to be publicly visible.
|
||||
if (inst->_vis > V_public) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(inst->_type != (CPPType *)NULL);
|
||||
CPPFunctionType *ftype = inst->_type->as_function_type();
|
||||
assert(ftype != (CPPFunctionType *)NULL);
|
||||
|
||||
if (ftype->_return_type != NULL &&
|
||||
(ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) {
|
||||
// Yes, this is a typecast operator. Test using the return type.
|
||||
if (ftype->_return_type->is_convertible_to(other)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether any of the base classes are convertible.
|
||||
Derivation::const_iterator di;
|
||||
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
|
||||
CPPStructType *base = (*di)._base->as_struct_type();
|
||||
if (base != NULL && (*di)._vis <= V_public && !base->is_convertible_to(other)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures all functions are correctly marked with the "virtual" flag if they
|
||||
* are truly virtual by virtue of inheritance, rather than simply being
|
||||
|
|
@ -420,6 +755,30 @@ check_virtual() const {
|
|||
return !funcs.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class, or any of its base classes, has a virtual
|
||||
* destructor.
|
||||
*/
|
||||
bool CPPStructType::
|
||||
has_virtual_destructor() const {
|
||||
CPPInstance *destructor = get_destructor();
|
||||
if (destructor != NULL) {
|
||||
if (destructor->_storage_class & CPPInstance::SC_virtual) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Derivation::const_iterator di;
|
||||
for (di = _derivation.begin(); di != _derivation.end(); ++di) {
|
||||
CPPStructType *base = (*di)._base->as_struct_type();
|
||||
if (base != NULL && base->has_virtual_destructor()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this declaration is an actual, factual declaration, or
|
||||
* false if some part of the declaration depends on a template parameter which
|
||||
|
|
@ -459,7 +818,7 @@ get_constructor() const {
|
|||
|
||||
/**
|
||||
* Returns the default constructor defined for the struct type, or NULL if
|
||||
* there is none.
|
||||
* there is no user-declared constructor that takes 0 arguments.
|
||||
*/
|
||||
CPPInstance *CPPStructType::
|
||||
get_default_constructor() const {
|
||||
|
|
@ -490,7 +849,7 @@ get_default_constructor() const {
|
|||
|
||||
/**
|
||||
* Returns the copy constructor defined for the struct type, or NULL if no
|
||||
* copy constructor exists.
|
||||
* user-declared copy constructor exists.
|
||||
*/
|
||||
CPPInstance *CPPStructType::
|
||||
get_copy_constructor() const {
|
||||
|
|
@ -519,7 +878,7 @@ get_copy_constructor() const {
|
|||
|
||||
/**
|
||||
* Returns the move constructor defined for the struct type, or NULL if no
|
||||
* move constructor exists.
|
||||
* user-declared move constructor exists.
|
||||
*/
|
||||
CPPInstance *CPPStructType::
|
||||
get_move_constructor() const {
|
||||
|
|
@ -548,7 +907,7 @@ get_move_constructor() const {
|
|||
|
||||
/**
|
||||
* Returns the destructor defined for the struct type, if any, or NULL if no
|
||||
* destructor is found.
|
||||
* user-declared destructor is found.
|
||||
*/
|
||||
CPPInstance *CPPStructType::
|
||||
get_destructor() const {
|
||||
|
|
|
|||
|
|
@ -44,14 +44,26 @@ public:
|
|||
CPPScope *get_scope() const;
|
||||
|
||||
bool is_abstract() const;
|
||||
bool is_base_of(const CPPStructType *other) const;
|
||||
bool is_empty() const;
|
||||
bool is_polymorphic() const;
|
||||
bool check_virtual() const;
|
||||
bool has_virtual_destructor() const;
|
||||
virtual bool is_fully_specified() const;
|
||||
virtual bool is_incomplete() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *arg_type) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_destructible() const;
|
||||
bool is_default_constructible(CPPVisibility min_vis) const;
|
||||
bool is_copy_constructible(CPPVisibility min_vis) const;
|
||||
bool is_move_constructible(CPPVisibility min_vis) const;
|
||||
bool is_destructible(CPPVisibility min_vis) const;
|
||||
virtual bool is_convertible_to(const CPPType *other) const;
|
||||
|
||||
inline bool is_final() const { return _final; }
|
||||
|
||||
CPPFunctionGroup *get_constructor() const;
|
||||
CPPInstance *get_default_constructor() const;
|
||||
|
|
|
|||
|
|
@ -97,8 +97,10 @@ add_template_parameter(CPPDeclaration *param) {
|
|||
CPPClassTemplateParameter *cl = param->as_class_template_parameter();
|
||||
if (cl != NULL) {
|
||||
// Create an implicit typedef for this class parameter.
|
||||
string name = cl->_ident->get_local_name();
|
||||
_types[name] = cl;
|
||||
if (cl->_ident != NULL) {
|
||||
string name = cl->_ident->get_local_name();
|
||||
_types[name] = cl;
|
||||
}
|
||||
}
|
||||
|
||||
CPPInstance *inst = param->as_instance();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
*/
|
||||
|
||||
#include "cppType.h"
|
||||
#include "cppTypedefType.h"
|
||||
#include "cppConstType.h"
|
||||
#include "cppPointerType.h"
|
||||
#include "cppReferenceType.h"
|
||||
#include "cppStructType.h"
|
||||
#include "cppExtensionType.h"
|
||||
#include <algorithm>
|
||||
|
||||
CPPType::Types CPPType::_types;
|
||||
|
|
@ -57,6 +61,22 @@ is_tbd() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a fundamental type.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_fundamental() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_standard_layout() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
|
|
@ -65,6 +85,14 @@ is_trivial() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
|
|
@ -81,6 +109,14 @@ is_copy_constructible() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_destructible() const {
|
||||
return !is_incomplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is a special parameter expression type.
|
||||
*
|
||||
|
|
@ -92,6 +128,136 @@ is_parameter_expr() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is an enum type, or a typedef to an enum type.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_enum() const {
|
||||
const CPPTypedefType *td_type = as_typedef_type();
|
||||
if (td_type != NULL) {
|
||||
return td_type->_type->is_enum();
|
||||
}
|
||||
const CPPExtensionType *ext_type = as_extension_type();
|
||||
if (ext_type != NULL) {
|
||||
return ext_type->_type == CPPExtensionType::T_enum ||
|
||||
ext_type->_type == CPPExtensionType::T_enum_struct ||
|
||||
ext_type->_type == CPPExtensionType::T_enum_class;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a const type, or a typedef to a const type.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_const() const {
|
||||
const CPPTypedefType *td_type = as_typedef_type();
|
||||
if (td_type != NULL) {
|
||||
return td_type->_type->is_const();
|
||||
}
|
||||
return get_subtype() == ST_const;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a reference type, or a typedef to a reference type.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_reference() const {
|
||||
const CPPTypedefType *td_type = as_typedef_type();
|
||||
if (td_type != NULL) {
|
||||
return td_type->_type->is_reference();
|
||||
}
|
||||
return get_subtype() == ST_reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is an unqualified or cv-qualified pointer type, or a
|
||||
* typedef to one.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_pointer() const {
|
||||
const CPPTypedefType *td_type = as_typedef_type();
|
||||
if (td_type != NULL) {
|
||||
return td_type->_type->is_pointer();
|
||||
}
|
||||
const CPPConstType *const_type = as_const_type();
|
||||
if (const_type != NULL) {
|
||||
return const_type->_wrapped_around->is_pointer();
|
||||
}
|
||||
return get_subtype() == ST_pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type with any const qualifier stripped off. Will follow
|
||||
* typedefs, but only if necessary.
|
||||
*/
|
||||
CPPType *CPPType::
|
||||
remove_const() {
|
||||
const CPPTypedefType *td_type = as_typedef_type();
|
||||
if (td_type != NULL) {
|
||||
CPPType *unwrapped = td_type->_type->remove_const();
|
||||
if (unwrapped != td_type->_type) {
|
||||
return unwrapped;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
const CPPConstType *const_type = as_const_type();
|
||||
if (const_type != NULL) {
|
||||
return const_type->_wrapped_around->remove_const();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type with any reference stripped off.
|
||||
*/
|
||||
CPPType *CPPType::
|
||||
remove_reference() {
|
||||
const CPPTypedefType *td_type = as_typedef_type();
|
||||
if (td_type != NULL) {
|
||||
CPPType *unwrapped = td_type->_type->remove_reference();
|
||||
if (unwrapped != td_type->_type) {
|
||||
return unwrapped;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
const CPPReferenceType *ref_type = as_reference_type();
|
||||
if (ref_type != NULL) {
|
||||
return ref_type->_pointing_at;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type with any pointer and cv-qualifiers stripped off.
|
||||
*/
|
||||
CPPType *CPPType::
|
||||
remove_pointer() {
|
||||
switch (get_subtype()) {
|
||||
case ST_typedef:
|
||||
{
|
||||
const CPPTypedefType *td_type = as_typedef_type();
|
||||
CPPType *unwrapped = td_type->_type->remove_pointer();
|
||||
if (unwrapped != td_type->_type) {
|
||||
return unwrapped;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
case ST_pointer:
|
||||
return ((const CPPPointerType *)this)->_pointing_at;
|
||||
|
||||
case ST_const:
|
||||
return ((const CPPConstType *)this)->_wrapped_around->remove_pointer();
|
||||
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type has even been typedef'ed and therefore has a
|
||||
* simple name available to stand for it. Extension types are all implicitly
|
||||
|
|
@ -229,6 +395,14 @@ is_equivalent(const CPPType &other) const {
|
|||
return is_equal(&other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if variables of this type may be implicitly converted to
|
||||
* the other type.
|
||||
*/
|
||||
bool CPPType::
|
||||
is_convertible_to(const CPPType *other) const {
|
||||
return other->is_constructible(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a C++-looking line that defines an instance of the given type, with
|
||||
|
|
|
|||
|
|
@ -45,11 +45,27 @@ public:
|
|||
CPPScope *global_scope);
|
||||
|
||||
virtual bool is_tbd() const;
|
||||
virtual bool is_fundamental() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *type) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_destructible() const;
|
||||
virtual bool is_parameter_expr() const;
|
||||
|
||||
// Convenience methods.
|
||||
bool is_enum() const;
|
||||
bool is_const() const;
|
||||
bool is_reference() const;
|
||||
bool is_pointer() const;
|
||||
|
||||
CPPType *remove_const();
|
||||
inline CPPType *remove_volatile() { return this; }
|
||||
inline CPPType *remove_cv() { return remove_const(); };
|
||||
CPPType *remove_reference();
|
||||
CPPType *remove_pointer();
|
||||
|
||||
bool has_typedef_name() const;
|
||||
string get_typedef_name(CPPScope *scope = NULL) const;
|
||||
|
||||
|
|
@ -61,6 +77,7 @@ public:
|
|||
string get_alt_name(int n) const;
|
||||
|
||||
virtual bool is_incomplete() const;
|
||||
virtual bool is_convertible_to(const CPPType *other) const;
|
||||
virtual bool is_equivalent(const CPPType &other) const;
|
||||
|
||||
void output_instance(ostream &out, const string &name,
|
||||
|
|
|
|||
|
|
@ -157,6 +157,22 @@ is_tbd() const {
|
|||
return _type->is_tbd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a fundamental type.
|
||||
*/
|
||||
bool CPPTypedefType::
|
||||
is_fundamental() const {
|
||||
return _type->is_fundamental();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a standard layout type.
|
||||
*/
|
||||
bool CPPTypedefType::
|
||||
is_standard_layout() const {
|
||||
return _type->is_standard_layout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is considered a Plain Old Data (POD) type.
|
||||
*/
|
||||
|
|
@ -165,6 +181,14 @@ is_trivial() const {
|
|||
return _type->is_trivial();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type can be constructed using the given argument.
|
||||
*/
|
||||
bool CPPTypedefType::
|
||||
is_constructible(const CPPType *given_type) const {
|
||||
return _type->is_constructible(given_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
|
|
@ -181,6 +205,14 @@ is_copy_constructible() const {
|
|||
return _type->is_copy_constructible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPTypedefType::
|
||||
is_destructible() const {
|
||||
return _type->is_destructible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this declaration is an actual, factual declaration, or
|
||||
* false if some part of the declaration depends on a template parameter which
|
||||
|
|
@ -300,6 +332,15 @@ resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if variables of this type may be implicitly converted to
|
||||
* the other type.
|
||||
*/
|
||||
bool CPPTypedefType::
|
||||
is_convertible_to(const CPPType *other) const {
|
||||
return _type->is_convertible_to(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a little more forgiving than is_equal(): it returns true if the
|
||||
* types appear to be referring to the same thing, even if they may have
|
||||
|
|
|
|||
|
|
@ -42,9 +42,13 @@ public:
|
|||
|
||||
virtual bool is_incomplete() const;
|
||||
virtual bool is_tbd() const;
|
||||
virtual bool is_fundamental() const;
|
||||
virtual bool is_standard_layout() const;
|
||||
virtual bool is_trivial() const;
|
||||
virtual bool is_constructible(const CPPType *type) const;
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_destructible() const;
|
||||
|
||||
virtual bool is_fully_specified() const;
|
||||
|
||||
|
|
@ -60,6 +64,7 @@ public:
|
|||
virtual CPPType *resolve_type(CPPScope *current_scope,
|
||||
CPPScope *global_scope);
|
||||
|
||||
virtual bool is_convertible_to(const CPPType *other) const;
|
||||
virtual bool is_equivalent(const CPPType &other) const;
|
||||
|
||||
virtual void output(ostream &out, int indent_level, CPPScope *scope,
|
||||
|
|
|
|||
|
|
@ -2401,7 +2401,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
|||
|
||||
cpptype = TypeManager::resolve_type(cpptype)->as_struct_type();
|
||||
assert(cpptype != (CPPStructType *)NULL);
|
||||
bool has_virt_methods = cpptype->check_virtual();
|
||||
bool has_virt_methods = cpptype->is_polymorphic();
|
||||
|
||||
switch (cpptype->_type) {
|
||||
case CPPExtensionType::T_class:
|
||||
|
|
@ -2501,7 +2501,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
|||
// (For many compilers, this does not require a pointer change.)
|
||||
generate_casts = true;
|
||||
|
||||
} else if (has_virt_methods && (base_type->as_struct_type() == (CPPStructType *)NULL || !base_type->as_struct_type()->check_virtual())) {
|
||||
} else if (has_virt_methods && (base_type->as_struct_type() == (CPPStructType *)NULL || !base_type->as_struct_type()->is_polymorphic())) {
|
||||
// Finally, if this class has virtual methods, but its parent
|
||||
// doesn't, then we have to upcast (because this class will require
|
||||
// space for a virtual function table pointer, while the parent
|
||||
|
|
@ -2651,7 +2651,11 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
|
|||
}
|
||||
}
|
||||
|
||||
if ((itype._flags & InterrogateType::F_inherited_destructor) != 0) {
|
||||
if (!cpptype->is_destructible()) {
|
||||
// There's no way to destruct the type.
|
||||
itype._destructor = 0;
|
||||
|
||||
} else if ((itype._flags & InterrogateType::F_inherited_destructor) != 0) {
|
||||
// If we have inherited our virtual destructor from our base class, go
|
||||
// ahead and assign the same function index.
|
||||
assert(!itype._derivations.empty());
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ invoke_extension(T *ptr) {
|
|||
return ext;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Extension<T>
|
||||
invoke_extension(T &ptr) {
|
||||
Extension<T> ext;
|
||||
ext._this = &ptr;
|
||||
return ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* The const version of the above function.
|
||||
*/
|
||||
|
|
@ -58,4 +66,12 @@ invoke_extension(const T *ptr) {
|
|||
return ext;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const Extension<T>
|
||||
invoke_extension(const T &ptr) {
|
||||
Extension<T> ext;
|
||||
ext._this = (T *) &ptr;
|
||||
return ext;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdtypedefs.h>
|
||||
|
||||
namespace std {
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
static constexpr T value = v;
|
||||
typedef T value_type;
|
||||
constexpr operator value_type() const noexcept { return value; }
|
||||
constexpr value_type operator()() const noexcept { return value; }
|
||||
};
|
||||
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
|
||||
template<class T, class U>
|
||||
struct is_same : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_same<T, T> : std::true_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_void : std::false_type {};
|
||||
|
||||
template<>
|
||||
struct is_void<void> : std::true_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_enum : integral_constant<bool, __is_enum(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_union : integral_constant<bool, __is_union(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_class : integral_constant<bool, __is_class(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_fundamental : integral_constant<bool, __is_fundamental(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_compound : integral_constant<bool, !__is_fundamental(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_trivial : integral_constant<bool, __is_trivial(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_standard_layout : integral_constant<bool, __is_standard_layout(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_pod : integral_constant<bool, __is_pod(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_empty : integral_constant<bool, __is_empty(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_polymorphic : integral_constant<bool, __is_polymorphic(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_abstract : integral_constant<bool, __is_abstract(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_final : integral_constant<bool, __is_final(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_default_constructible : integral_constant<bool, __is_constructible(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_copy_constructible : integral_constant<bool, __is_constructible(T, const T&)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_move_constructible : integral_constant<bool, __is_constructible(T, const T&&)> {};
|
||||
|
||||
template<class T>
|
||||
struct is_destructible : integral_constant<bool, __is_destructible(T)> {};
|
||||
|
||||
template<class T>
|
||||
struct has_virtual_destructor : integral_constant<bool, __has_virtual_destructor(T)> {};
|
||||
|
||||
template<class T >
|
||||
struct alignment_of : std::integral_constant<std::size_t, alignof(T)> {};
|
||||
|
||||
template<class T, class U>
|
||||
struct is_base_of : integral_constant<bool, __is_base_of(T, U)> {};
|
||||
|
||||
template<class T, class U>
|
||||
struct is_convertible : integral_constant<bool, __is_convertible_to(T, U)> {};
|
||||
|
||||
template<class T> struct add_cv { typedef const volatile T type; };
|
||||
template<class T> struct add_const { typedef const T type; };
|
||||
template<class T> struct add_volatile { typedef volatile T type; };
|
||||
|
||||
template<class T> struct add_lvalue_reference { typedef T &type; };
|
||||
template<class T> struct add_rvalue_reference { typedef T &&type; };
|
||||
template<class T> struct add_pointer { typedef T *type; };
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
struct __m128;
|
||||
Loading…
Reference in New Issue