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:
rdb 2016-11-03 12:13:06 +01:00
parent 7259425b7c
commit 22f0b50851
40 changed files with 7175 additions and 4693 deletions

View File

@ -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();
}
/**

View File

@ -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

View File

@ -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. */

View File

@ -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
{

View File

@ -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;
}

View File

@ -37,6 +37,7 @@ public:
CPPIdentifier *_ident;
CPPType *_default_type;
bool _packed;
protected:
virtual bool is_equal(const CPPDeclaration *other) const;

View File

@ -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

View File

@ -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,

View File

@ -41,8 +41,13 @@ CPPDeclaration(const CPPDeclaration &copy) :
/**
*
*/
CPPDeclaration::
~CPPDeclaration() {
CPPDeclaration &CPPDeclaration::
operator = (const CPPDeclaration &copy) {
_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;

View File

@ -89,7 +89,9 @@ public:
CPPDeclaration(const CPPFile &file);
CPPDeclaration(const CPPDeclaration &copy);
virtual ~CPPDeclaration();
virtual ~CPPDeclaration() {};
CPPDeclaration &operator = (const CPPDeclaration &copy);
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;

View 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 << " **)";
}

View File

@ -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:

View File

@ -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);
}
/**

View File

@ -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;

View File

@ -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";
}

View File

@ -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,

View File

@ -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()->

View File

@ -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);

View File

@ -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) {
}
/**

View File

@ -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);

View File

@ -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.
*/

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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"

View File

@ -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.
*

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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());

View File

@ -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

View File

@ -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; };
}

View File

@ -0,0 +1 @@
struct __m128;