Interrogate cppparser improvements, C++11/14/17 additions:

* Support trailing return type.
 * Ignore C++14 digit separators.
 * Parse C++14 binary number representations.
 * Support "using"-style type aliases.
 * Support decltype and auto with "new".
 * Remove silly "long float" and "long long float".
 * Support default visibility with class inheritance.
 * Remove -longlong hack since C++11 supports long long natively.
 * Support unary plus operator.
 * Preserve bitfield definitions.
 * Support constructor inits using braces.
 * Support override/final specifiers.
 * Ignore [[attributes]] in certain cases
 * Add support for typeid() in expressions
 * Parse (but ignore) lambda expressions
 * Differentiate between casts, add const_cast/reinterpret_cast
 * Support thread_local variables.
This commit is contained in:
rdb 2016-02-15 21:14:42 +01:00
parent 1f32c1dff0
commit caa03c53dd
24 changed files with 5377 additions and 3743 deletions

File diff suppressed because it is too large Load Diff

View File

@ -72,95 +72,101 @@ extern int cppyydebug;
UNARY_NOT = 281,
UNARY_NEGATE = 282,
UNARY_MINUS = 283,
UNARY_STAR = 284,
UNARY_REF = 285,
POINTSAT = 286,
SCOPE = 287,
PLUSPLUS = 288,
MINUSMINUS = 289,
TIMESEQUAL = 290,
DIVIDEEQUAL = 291,
MODEQUAL = 292,
PLUSEQUAL = 293,
MINUSEQUAL = 294,
OREQUAL = 295,
ANDEQUAL = 296,
XOREQUAL = 297,
LSHIFTEQUAL = 298,
RSHIFTEQUAL = 299,
KW_ALIGNAS = 300,
KW_ALIGNOF = 301,
KW_AUTO = 302,
KW_BEGIN_PUBLISH = 303,
KW_BLOCKING = 304,
KW_BOOL = 305,
KW_CATCH = 306,
KW_CHAR = 307,
KW_CHAR16_T = 308,
KW_CHAR32_T = 309,
KW_CLASS = 310,
KW_CONST = 311,
KW_CONSTEXPR = 312,
KW_DECLTYPE = 313,
KW_DEFAULT = 314,
KW_DELETE = 315,
KW_DOUBLE = 316,
KW_DYNAMIC_CAST = 317,
KW_ELSE = 318,
KW_END_PUBLISH = 319,
KW_ENUM = 320,
KW_EXTENSION = 321,
KW_EXTERN = 322,
KW_EXPLICIT = 323,
KW_PUBLISHED = 324,
KW_FALSE = 325,
KW_FLOAT = 326,
KW_FRIEND = 327,
KW_FOR = 328,
KW_GOTO = 329,
KW_IF = 330,
KW_INLINE = 331,
KW_INT = 332,
KW_LONG = 333,
KW_LONGLONG = 334,
KW_MAKE_PROPERTY = 335,
KW_MAKE_PROPERTY2 = 336,
KW_MAKE_SEQ = 337,
KW_MUTABLE = 338,
KW_NAMESPACE = 339,
KW_NEW = 340,
KW_NOEXCEPT = 341,
KW_NULLPTR = 342,
KW_OPERATOR = 343,
KW_PRIVATE = 344,
KW_PROTECTED = 345,
KW_PUBLIC = 346,
KW_REGISTER = 347,
KW_RETURN = 348,
KW_SHORT = 349,
KW_SIGNED = 350,
KW_SIZEOF = 351,
KW_STATIC = 352,
KW_STATIC_ASSERT = 353,
KW_STATIC_CAST = 354,
KW_STRUCT = 355,
KW_TEMPLATE = 356,
KW_THROW = 357,
KW_TRUE = 358,
KW_TRY = 359,
KW_TYPEDEF = 360,
KW_TYPENAME = 361,
KW_UNION = 362,
KW_UNSIGNED = 363,
KW_USING = 364,
KW_VIRTUAL = 365,
KW_VOID = 366,
KW_VOLATILE = 367,
KW_WCHAR_T = 368,
KW_WHILE = 369,
START_CPP = 370,
START_CONST_EXPR = 371,
START_TYPE = 372
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_PROPERTY = 337,
KW_MAKE_PROPERTY2 = 338,
KW_MAKE_SEQ = 339,
KW_MUTABLE = 340,
KW_NAMESPACE = 341,
KW_NEW = 342,
KW_NOEXCEPT = 343,
KW_NULLPTR = 344,
KW_OPERATOR = 345,
KW_OVERRIDE = 346,
KW_PRIVATE = 347,
KW_PROTECTED = 348,
KW_PUBLIC = 349,
KW_REGISTER = 350,
KW_REINTERPRET_CAST = 351,
KW_RETURN = 352,
KW_SHORT = 353,
KW_SIGNED = 354,
KW_SIZEOF = 355,
KW_STATIC = 356,
KW_STATIC_ASSERT = 357,
KW_STATIC_CAST = 358,
KW_STRUCT = 359,
KW_TEMPLATE = 360,
KW_THREAD_LOCAL = 361,
KW_THROW = 362,
KW_TRUE = 363,
KW_TRY = 364,
KW_TYPEDEF = 365,
KW_TYPEID = 366,
KW_TYPENAME = 367,
KW_UNION = 368,
KW_UNSIGNED = 369,
KW_USING = 370,
KW_VIRTUAL = 371,
KW_VOID = 372,
KW_VOLATILE = 373,
KW_WCHAR_T = 374,
KW_WHILE = 375,
START_CPP = 376,
START_CONST_EXPR = 377,
START_TYPE = 378
};
#endif
/* Tokens. */
@ -190,95 +196,101 @@ extern int cppyydebug;
#define UNARY_NOT 281
#define UNARY_NEGATE 282
#define UNARY_MINUS 283
#define UNARY_STAR 284
#define UNARY_REF 285
#define POINTSAT 286
#define SCOPE 287
#define PLUSPLUS 288
#define MINUSMINUS 289
#define TIMESEQUAL 290
#define DIVIDEEQUAL 291
#define MODEQUAL 292
#define PLUSEQUAL 293
#define MINUSEQUAL 294
#define OREQUAL 295
#define ANDEQUAL 296
#define XOREQUAL 297
#define LSHIFTEQUAL 298
#define RSHIFTEQUAL 299
#define KW_ALIGNAS 300
#define KW_ALIGNOF 301
#define KW_AUTO 302
#define KW_BEGIN_PUBLISH 303
#define KW_BLOCKING 304
#define KW_BOOL 305
#define KW_CATCH 306
#define KW_CHAR 307
#define KW_CHAR16_T 308
#define KW_CHAR32_T 309
#define KW_CLASS 310
#define KW_CONST 311
#define KW_CONSTEXPR 312
#define KW_DECLTYPE 313
#define KW_DEFAULT 314
#define KW_DELETE 315
#define KW_DOUBLE 316
#define KW_DYNAMIC_CAST 317
#define KW_ELSE 318
#define KW_END_PUBLISH 319
#define KW_ENUM 320
#define KW_EXTENSION 321
#define KW_EXTERN 322
#define KW_EXPLICIT 323
#define KW_PUBLISHED 324
#define KW_FALSE 325
#define KW_FLOAT 326
#define KW_FRIEND 327
#define KW_FOR 328
#define KW_GOTO 329
#define KW_IF 330
#define KW_INLINE 331
#define KW_INT 332
#define KW_LONG 333
#define KW_LONGLONG 334
#define KW_MAKE_PROPERTY 335
#define KW_MAKE_PROPERTY2 336
#define KW_MAKE_SEQ 337
#define KW_MUTABLE 338
#define KW_NAMESPACE 339
#define KW_NEW 340
#define KW_NOEXCEPT 341
#define KW_NULLPTR 342
#define KW_OPERATOR 343
#define KW_PRIVATE 344
#define KW_PROTECTED 345
#define KW_PUBLIC 346
#define KW_REGISTER 347
#define KW_RETURN 348
#define KW_SHORT 349
#define KW_SIGNED 350
#define KW_SIZEOF 351
#define KW_STATIC 352
#define KW_STATIC_ASSERT 353
#define KW_STATIC_CAST 354
#define KW_STRUCT 355
#define KW_TEMPLATE 356
#define KW_THROW 357
#define KW_TRUE 358
#define KW_TRY 359
#define KW_TYPEDEF 360
#define KW_TYPENAME 361
#define KW_UNION 362
#define KW_UNSIGNED 363
#define KW_USING 364
#define KW_VIRTUAL 365
#define KW_VOID 366
#define KW_VOLATILE 367
#define KW_WCHAR_T 368
#define KW_WHILE 369
#define START_CPP 370
#define START_CONST_EXPR 371
#define START_TYPE 372
#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_PROPERTY 337
#define KW_MAKE_PROPERTY2 338
#define KW_MAKE_SEQ 339
#define KW_MUTABLE 340
#define KW_NAMESPACE 341
#define KW_NEW 342
#define KW_NOEXCEPT 343
#define KW_NULLPTR 344
#define KW_OPERATOR 345
#define KW_OVERRIDE 346
#define KW_PRIVATE 347
#define KW_PROTECTED 348
#define KW_PUBLIC 349
#define KW_REGISTER 350
#define KW_REINTERPRET_CAST 351
#define KW_RETURN 352
#define KW_SHORT 353
#define KW_SIGNED 354
#define KW_SIZEOF 355
#define KW_STATIC 356
#define KW_STATIC_ASSERT 357
#define KW_STATIC_CAST 358
#define KW_STRUCT 359
#define KW_TEMPLATE 360
#define KW_THREAD_LOCAL 361
#define KW_THROW 362
#define KW_TRUE 363
#define KW_TRY 364
#define KW_TYPEDEF 365
#define KW_TYPEID 366
#define KW_TYPENAME 367
#define KW_UNION 368
#define KW_UNSIGNED 369
#define KW_USING 370
#define KW_VIRTUAL 371
#define KW_VOID 372
#define KW_VOLATILE 373
#define KW_WCHAR_T 374
#define KW_WHILE 375
#define START_CPP 376
#define START_CONST_EXPR 377
#define START_TYPE 378

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,29 @@ CPPEnumType(CPPIdentifier *ident, CPPType *element_type,
}
}
////////////////////////////////////////////////////////////////////
// Function: CPPEnumType::get_element_type
// Access: Public
// Description: Returns the integral type used to store enum values.
////////////////////////////////////////////////////////////////////
CPPType *CPPEnumType::
get_element_type() {
if (_element_type == NULL) {
// This enum is untyped. Use a suitable default, ie. 'int'.
// In the future, we might want to check whether it fits in an int.
static CPPType *default_element_type = NULL;
if (default_element_type == NULL) {
default_element_type =
CPPType::new_type(new CPPConstType(new CPPSimpleType(CPPSimpleType::T_int, 0)));
}
return default_element_type;
} else {
// This enum has an explicit type, so use that.
return CPPType::new_type(new CPPConstType(_element_type));
}
}
////////////////////////////////////////////////////////////////////
// Function: CPPEnumType::add_element
// Access: Public
@ -67,22 +90,8 @@ CPPInstance *CPPEnumType::
add_element(const string &name, CPPExpression *value) {
CPPIdentifier *ident = new CPPIdentifier(name);
ident->_native_scope = _parent_scope;
CPPInstance *inst;
static CPPType *default_element_type = NULL;
if (_element_type == NULL) {
// This enum is untyped. Use a suitable default, ie. 'int'.
if (default_element_type == NULL) {
default_element_type =
CPPType::new_type(new CPPConstType(new CPPSimpleType(CPPSimpleType::T_int, 0)));
}
inst = new CPPInstance(default_element_type, ident);
} else {
// This enum has an explicit type, so use that.
inst = new CPPInstance(CPPType::new_type(new CPPConstType(_element_type)), ident);
}
CPPInstance *inst = new CPPInstance(get_element_type(), ident);
inst->_storage_class |= CPPInstance::SC_constexpr;
_elements.push_back(inst);

View File

@ -37,6 +37,8 @@ public:
CPPEnumType(CPPIdentifier *ident, CPPType *element_type,
CPPScope *current_scope, const CPPFile &file);
CPPType *get_element_type();
CPPInstance *add_element(const string &name,
CPPExpression *value = (CPPExpression *)NULL);

View File

@ -356,9 +356,10 @@ CPPExpression(int trinary_operator, CPPExpression *op1, CPPExpression *op2,
// operation.
////////////////////////////////////////////////////////////////////
CPPExpression CPPExpression::
typecast_op(CPPType *type, CPPExpression *op1) {
typecast_op(CPPType *type, CPPExpression *op1, Type cast_type) {
assert(cast_type >= T_typecast && cast_type <= T_reinterpret_cast);
CPPExpression expr(0);
expr._type = T_typecast;
expr._type = cast_type;
expr._u._typecast._to = type;
expr._u._typecast._op1 = op1;
return expr;
@ -410,6 +411,36 @@ new_op(CPPType *type, CPPExpression *op1) {
return expr;
}
////////////////////////////////////////////////////////////////////
// Function: CPPExpression::named typeid_op constructor
// Access: Public, Static
// Description: Creates an expression that represents a use of the
// typeid operator.
////////////////////////////////////////////////////////////////////
CPPExpression CPPExpression::
typeid_op(CPPType *type, CPPType *std_type_info) {
CPPExpression expr(0);
expr._type = T_typeid_type;
expr._u._typeid._type = type;
expr._u._typeid._std_type_info = std_type_info;
return expr;
}
////////////////////////////////////////////////////////////////////
// Function: CPPExpression::named typeid_op constructor
// Access: Public, Static
// Description: Creates an expression that represents a use of the
// typeid operator.
////////////////////////////////////////////////////////////////////
CPPExpression CPPExpression::
typeid_op(CPPExpression *op1, CPPType *std_type_info) {
CPPExpression expr(0);
expr._type = T_typeid_expr;
expr._u._typeid._expr = op1;
expr._u._typeid._std_type_info = std_type_info;
return expr;
}
////////////////////////////////////////////////////////////////////
// Function: CPPExpression::named sizeof_func constructor
// Access: Public, Static
@ -591,6 +622,10 @@ evaluate() const {
return Result();
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
assert(_u._typecast._op1 != NULL);
r1 = _u._typecast._op1->evaluate();
if (r1._type != RT_error) {
@ -706,6 +741,9 @@ evaluate() const {
case UNARY_MINUS:
return (r1._type == RT_real) ? Result(-r1.as_real()) : Result(-r1.as_integer());
case UNARY_PLUS:
return r1;
case UNARY_STAR:
case UNARY_REF:
return Result();
@ -835,6 +873,10 @@ evaluate() const {
case T_raw_literal:
return Result();
case T_typeid_type:
case T_typeid_expr:
return Result();
default:
cerr << "**invalid operand**\n";
abort();
@ -940,6 +982,10 @@ determine_type() const {
return (CPPType *)NULL;
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
case T_construct:
case T_default_construct:
return _u._typecast._to;
@ -973,7 +1019,34 @@ determine_type() const {
return int_type;
case UNARY_MINUS:
return t1;
case UNARY_PLUS:
if (t1 != NULL) {
switch (t1->get_subtype()) {
case CPPDeclaration::ST_array:
// Decay into pointer.
return CPPType::new_type(new CPPPointerType(t1->as_array_type()->_element_type));
case CPPDeclaration::ST_enum:
// Convert into integral type.
return t1->as_enum_type()->get_element_type();
case CPPDeclaration::ST_simple:
{
CPPSimpleType *simple_type = t1->as_simple_type();
if ((simple_type->_flags & CPPSimpleType::F_short) != 0 ||
simple_type->_type == CPPSimpleType::T_bool ||
simple_type->_type == CPPSimpleType::T_wchar_t ||
simple_type->_type == CPPSimpleType::T_char16_t) {
// Integer promotion.
return int_type;
}
}
// Fall through.
default:
return t1;
}
}
return NULL;
case UNARY_STAR:
case '[': // Array element reference
@ -1059,6 +1132,10 @@ determine_type() const {
}
return NULL;
case T_typeid_type:
case T_typeid_expr:
return _u._typeid._std_type_info;
default:
cerr << "**invalid operand**\n";
abort();
@ -1103,6 +1180,10 @@ is_fully_specified() const {
return _u._ident->is_fully_specified();
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
case T_construct:
case T_new:
return (_u._typecast._to->is_fully_specified() &&
@ -1136,6 +1217,12 @@ is_fully_specified() const {
case T_raw_literal:
return _u._literal._value->is_fully_specified();
case T_typeid_type:
return _u._typeid._type->is_fully_specified();
case T_typeid_expr:
return _u._typeid._expr->is_fully_specified();
default:
return true;
}
@ -1215,6 +1302,10 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
break;
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
case T_construct:
case T_new:
rep->_u._typecast._op1 =
@ -1254,6 +1345,20 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
any_changed = any_changed || (rep->_u._op._op1 != _u._op._op1);
break;
case T_typeid_type:
rep->_u._typeid._type =
_u._typeid._type->substitute_decl(subst, current_scope, global_scope)
->as_type();
any_changed = any_changed || (rep->_u._typeid._type != _u._typeid._type);
break;
case T_typeid_expr:
rep->_u._typeid._expr =
_u._typeid._expr->substitute_decl(subst, current_scope, global_scope)
->as_expression();
any_changed = any_changed || (rep->_u._typeid._expr != _u._typeid._expr);
break;
default:
break;
}
@ -1295,6 +1400,10 @@ is_tbd() const {
return true;
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
case T_construct:
case T_new:
case T_default_construct:
@ -1321,6 +1430,12 @@ is_tbd() const {
}
return false;
case T_typeid_type:
return _u._typeid._type->is_tbd();
case T_typeid_expr:
return _u._typeid._expr->is_tbd();
default:
return false;
}
@ -1450,6 +1565,38 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
out << ")";
break;
case T_static_cast:
out << "static_cast<";
_u._typecast._to->output(out, indent_level, scope, false);
out << ">(";
_u._typecast._op1->output(out, indent_level, scope, false);
out << ")";
break;
case T_dynamic_cast:
out << "dynamic_cast<";
_u._typecast._to->output(out, indent_level, scope, false);
out << ">(";
_u._typecast._op1->output(out, indent_level, scope, false);
out << ")";
break;
case T_const_cast:
out << "const_cast<";
_u._typecast._to->output(out, indent_level, scope, false);
out << ">(";
_u._typecast._op1->output(out, indent_level, scope, false);
out << ")";
break;
case T_reinterpret_cast:
out << "reinterpret_cast<";
_u._typecast._to->output(out, indent_level, scope, false);
out << ">(";
_u._typecast._op1->output(out, indent_level, scope, false);
out << ")";
break;
case T_construct:
_u._typecast._to->output(out, indent_level, scope, false);
out << "(";
@ -1507,6 +1654,11 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
_u._op._op1->output(out, indent_level, scope, false);
break;
case UNARY_PLUS:
out << '+';
_u._op._op1->output(out, indent_level, scope, false);
break;
case UNARY_STAR:
out << "(* ";
_u._op._op1->output(out, indent_level, scope, false);
@ -1599,11 +1751,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
break;
case '.':
out << "(";
_u._op._op1->output(out, indent_level, scope, false);
out << ".";
_u._op._op2->output(out, indent_level, scope, false);
out << ")";
break;
case POINTSAT:
@ -1671,6 +1821,18 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
}
break;
case T_typeid_type:
out << "typeid(";
_u._typeid._type->output(out, indent_level, scope, false);
out << ")";
break;
case T_typeid_expr:
out << "typeid(";
_u._typeid._expr->output(out, indent_level, scope, false);
out << ")";
break;
case T_default:
out << "default";
break;
@ -1802,6 +1964,10 @@ is_equal(const CPPDeclaration *other) const {
return *_u._ident == *ot->_u._ident;
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
case T_construct:
case T_new:
return _u._typecast._to == ot->_u._typecast._to &&
@ -1832,6 +1998,12 @@ is_equal(const CPPDeclaration *other) const {
return _str == ot->_str &&
_u._literal._operator == ot->_u._literal._operator;
case T_typeid_type:
return _u._typeid._type == ot->_u._typeid._type;
case T_typeid_expr:
return _u._typeid._expr == ot->_u._typeid._expr;
default:
cerr << "(** invalid operand type " << (int)_type << " **)";
}
@ -1885,6 +2057,10 @@ is_less(const CPPDeclaration *other) const {
return *_u._ident < *ot->_u._ident;
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
case T_construct:
case T_new:
if (_u._typecast._to != ot->_u._typecast._to) {
@ -1925,6 +2101,12 @@ is_less(const CPPDeclaration *other) const {
}
return _str < ot->_str;
case T_typeid_type:
return _u._typeid._type < ot->_u._typeid._type;
case T_typeid_expr:
return *_u._typeid._expr < *ot->_u._typeid._expr;
default:
cerr << "(** invalid operand type " << (int)_type << " **)";
}

View File

@ -30,6 +30,43 @@ class CPPFunctionGroup;
////////////////////////////////////////////////////////////////////
class CPPExpression : public CPPDeclaration {
public:
enum Type {
T_nullptr,
T_boolean,
T_integer,
T_real,
T_string,
T_wstring,
T_u8string,
T_u16string,
T_u32string,
T_variable,
T_function,
T_unknown_ident,
T_typecast,
T_static_cast,
T_dynamic_cast,
T_const_cast,
T_reinterpret_cast,
T_construct,
T_default_construct,
T_new,
T_default_new,
T_sizeof,
T_alignof,
T_unary_operation,
T_binary_operation,
T_trinary_operation,
T_literal,
T_raw_literal,
T_typeid_type,
T_typeid_expr,
// These are used when parsing =default and =delete methods.
T_default,
T_delete,
};
CPPExpression(bool value);
CPPExpression(unsigned long long value);
CPPExpression(int value);
@ -41,9 +78,11 @@ public:
CPPExpression(int binary_operator, CPPExpression *op1, CPPExpression *op2);
CPPExpression(int trinary_operator, CPPExpression *op1, CPPExpression *op2, CPPExpression *op3);
static CPPExpression typecast_op(CPPType *type, CPPExpression *op1);
static CPPExpression typecast_op(CPPType *type, CPPExpression *op1, Type cast_type = T_typecast);
static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
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 sizeof_func(CPPType *type);
static CPPExpression alignof_func(CPPType *type);
@ -102,38 +141,6 @@ public:
virtual CPPExpression *as_expression();
enum Type {
T_nullptr,
T_boolean,
T_integer,
T_real,
T_string,
T_wstring,
T_u8string,
T_u16string,
T_u32string,
T_variable,
T_function,
T_unknown_ident,
T_typecast,
T_construct,
T_default_construct,
T_new,
T_default_new,
T_sizeof,
T_alignof,
T_unary_operation,
T_binary_operation,
T_trinary_operation,
T_literal,
T_raw_literal,
// These are used when parsing =default and =delete methods.
T_default,
T_delete,
};
Type _type;
string _str;
union {
@ -143,13 +150,18 @@ public:
CPPInstance *_variable;
CPPFunctionGroup *_fgroup;
CPPIdentifier *_ident;
class {
public:
struct {
union {
CPPType *_type;
CPPExpression *_expr;
};
CPPType *_std_type_info;
} _typeid;
struct {
CPPType *_to;
CPPExpression *_op1;
} _typecast;
class {
public:
struct {
// One of the yytoken values: a character, or something
// like EQCOMPARE.
int _operator;
@ -157,8 +169,7 @@ public:
CPPExpression *_op2;
CPPExpression *_op3;
} _op;
class {
public:
struct {
CPPInstance *_operator;
CPPExpression *_value;
} _literal;

View File

@ -214,10 +214,10 @@ is_equivalent(const CPPType &other) const {
// Description:
////////////////////////////////////////////////////////////////////
void CPPExtensionType::
output(ostream &out, int, CPPScope *scope, bool) const {
output(ostream &out, int, CPPScope *scope, bool complete) const {
if (_ident != NULL) {
// If we have a name, use it.
if (cppparser_output_class_keyword) {
if (complete || cppparser_output_class_keyword) {
out << _type << " ";
}
out << _ident->get_local_name(scope);

View File

@ -193,12 +193,44 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
void CPPFunctionType::
output(ostream &out, int indent_level, CPPScope *scope, bool complete,
int num_default_parameters) const {
_return_type->output(out, indent_level, scope, complete);
out << "(";
_parameters->output(out, scope, true, num_default_parameters);
out << ")";
if (_flags & F_const_method) {
out << " const";
if (_flags & F_trailing_return_type) {
// It was declared using trailing return type, so let's format it that way.
out << "auto(";
_parameters->output(out, scope, true, num_default_parameters);
out << ")";
if (_flags & F_const_method) {
out << " const";
}
if (_flags & F_noexcept) {
out << " noexcept";
}
if (_flags & F_final) {
out << " final";
}
if (_flags & F_override) {
out << " override";
}
out << " -> ";
_return_type->output(out, indent_level, scope, false);
} else {
_return_type->output(out, indent_level, scope, complete);
out << "(";
_parameters->output(out, scope, true, num_default_parameters);
out << ")";
if (_flags & F_const_method) {
out << " const";
}
if (_flags & F_noexcept) {
out << " noexcept";
}
if (_flags & F_final) {
out << " final";
}
if (_flags & F_override) {
out << " override";
}
}
}
@ -241,6 +273,18 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
// No return type for constructors and destructors.
out << prename << name << str;
} else if (_flags & F_trailing_return_type) {
// It was declared using trailing return type, so let's format it that way.
out << "auto ";
if (prename.empty()) {
out << name;
} else {
out << "(" << prename << name << ")";
}
out << str;
} else {
if (prename.empty()) {
_return_type->output_instance(out, indent_level, scope, complete,
@ -257,6 +301,17 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
if (_flags & F_noexcept) {
out << " noexcept";
}
if (_flags & F_final) {
out << " final";
}
if (_flags & F_override) {
out << " override";
}
if (_flags & F_trailing_return_type) {
out << " -> ";
_return_type->output(out, indent_level, scope, false);
}
}
////////////////////////////////////////////////////////////////////

View File

@ -39,6 +39,9 @@ public:
F_noexcept = 0x080,
F_copy_constructor = 0x200,
F_move_constructor = 0x400,
F_trailing_return_type = 0x800,
F_final = 0x1000,
F_override = 0x2000,
};
CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,

View File

@ -39,7 +39,8 @@ CPPInstance(CPPType *type, const string &name, int storage_class) :
_type(type),
_ident(new CPPIdentifier(name)),
_storage_class(storage_class),
_alignment(NULL)
_alignment(NULL),
_bit_width(-1)
{
_initializer = NULL;
}
@ -55,7 +56,8 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
_type(type),
_ident(ident),
_storage_class(storage_class),
_alignment(NULL)
_alignment(NULL),
_bit_width(-1)
{
_initializer = NULL;
}
@ -79,6 +81,7 @@ CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
ii->_ident = NULL;
_storage_class = storage_class;
_initializer = NULL;
_bit_width = ii->_bit_width;
CPPParameterList *params = ii->get_initializer();
if (params != (CPPParameterList *)NULL) {
@ -106,7 +109,8 @@ CPPInstance(const CPPInstance &copy) :
_ident(copy._ident),
_initializer(copy._initializer),
_storage_class(copy._storage_class),
_alignment(copy._alignment)
_alignment(copy._alignment),
_bit_width(copy._bit_width)
{
assert(_type != NULL);
}
@ -612,6 +616,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
if (_storage_class & SC_constexpr) {
out << "constexpr ";
}
if (_storage_class & SC_thread_local) {
out << "thread_local ";
}
string name;
if (_ident != NULL) {
@ -627,6 +634,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
_type->output_instance(out, indent_level, scope, complete, "", name);
}
if (_bit_width != -1) {
out << " : " << _bit_width;
}
if (_storage_class & SC_pure_virtual) {
out << " = 0";
}

View File

@ -64,6 +64,8 @@ public:
// These are for =default and =delete functions.
SC_defaulted = 0x4000,
SC_deleted = 0x8000,
SC_thread_local = 0x10000,
};
CPPInstance(CPPType *type, const string &name, int storage_class = 0);
@ -119,6 +121,7 @@ public:
int _storage_class;
CPPExpression *_alignment;
int _bit_width;
private:
typedef map<const CPPTemplateParameterList *, CPPInstance *, CPPTPLCompare> Instantiations;

View File

@ -43,10 +43,11 @@ Modifier(CPPInstanceIdentifierType type) :
// Description:
////////////////////////////////////////////////////////////////////
CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
func_type(CPPParameterList *params, int flags) {
func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
Modifier mod(IIT_func);
mod._func_params = params;
mod._func_flags = flags;
mod._trailing_return_type = trailing_return_type;
return mod;
}
@ -93,7 +94,9 @@ initializer_type(CPPParameterList *params) {
// Description:
////////////////////////////////////////////////////////////////////
CPPInstanceIdentifier::
CPPInstanceIdentifier(CPPIdentifier *ident) : _ident(ident) {
CPPInstanceIdentifier(CPPIdentifier *ident) :
_ident(ident),
_bit_width(-1) {
}
////////////////////////////////////////////////////////////////////
@ -128,7 +131,7 @@ add_modifier(CPPInstanceIdentifierType type) {
// Description:
////////////////////////////////////////////////////////////////////
void CPPInstanceIdentifier::
add_func_modifier(CPPParameterList *params, int flags) {
add_func_modifier(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
// As a special hack, if we added a parameter list to an operator
// function, check if the parameter list is empty. If it is, this
// is really a unary operator, so set the unary_op flag. Operators
@ -146,7 +149,12 @@ add_func_modifier(CPPParameterList *params, int flags) {
flags |= CPPFunctionType::F_operator;
}
_modifiers.push_back(Modifier::func_type(params, flags));
if (trailing_return_type != NULL) {
// Remember whether trailing return type notation was used.
flags |= CPPFunctionType::F_trailing_return_type;
}
_modifiers.push_back(Modifier::func_type(params, flags, trailing_return_type));
}
////////////////////////////////////////////////////////////////////
@ -188,6 +196,25 @@ add_initializer_modifier(CPPParameterList *params) {
_modifiers.push_back(Modifier::initializer_type(params));
}
////////////////////////////////////////////////////////////////////
// Function: CPPInstanceIdentifier::add_trailing_return_type
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void CPPInstanceIdentifier::
add_trailing_return_type(CPPType *type) {
// This is an awkward hack. Improve in the future.
if (!_modifiers.empty()) {
Modifier &mod = _modifiers.back();
if (mod._type == IIT_func) {
mod._trailing_return_type = type;
mod._func_flags |= CPPFunctionType::F_trailing_return_type;
return;
}
}
cerr << "trailing return type can only be added to a function\n";
}
////////////////////////////////////////////////////////////////////
// Function: CPPInstanceIdentifier::get_initializer
// Access: Public
@ -237,6 +264,8 @@ get_scope(CPPScope *current_scope, CPPScope *global_scope,
CPPType *CPPInstanceIdentifier::
r_unroll_type(CPPType *start_type,
CPPInstanceIdentifier::Modifiers::const_iterator mi) {
assert(start_type != NULL);
start_type = CPPType::new_type(start_type);
if (mi == _modifiers.end()) {
@ -298,6 +327,14 @@ r_unroll_type(CPPType *start_type,
case IIT_func:
{
CPPType *return_type = r_unroll_type(start_type, mi);
if (mod._trailing_return_type != (CPPType *)NULL) {
CPPSimpleType *simple_type = return_type->as_simple_type();
if (simple_type != NULL && simple_type->_type == CPPSimpleType::T_auto) {
return_type = mod._trailing_return_type;
} else {
cerr << "function with trailing return type needs auto\n";
}
}
result = new CPPFunctionType(return_type, mod._func_params,
mod._func_flags);
}

View File

@ -57,11 +57,14 @@ public:
CPPType *unroll_type(CPPType *start_type);
void add_modifier(CPPInstanceIdentifierType type);
void add_func_modifier(CPPParameterList *params, int flags);
void add_func_modifier(CPPParameterList *params, int flags,
CPPType *trailing_return_type = NULL);
void add_scoped_pointer_modifier(CPPIdentifier *scoping);
void add_array_modifier(CPPExpression *expr);
void add_initializer_modifier(CPPParameterList *params);
void add_trailing_return_type(CPPType *type);
CPPParameterList *get_initializer() const;
CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope,
@ -72,7 +75,8 @@ public:
class Modifier {
public:
Modifier(CPPInstanceIdentifierType type);
static Modifier func_type(CPPParameterList *params, int flags);
static Modifier func_type(CPPParameterList *params, int flags,
CPPType *trailing_return_type);
static Modifier array_type(CPPExpression *expr);
static Modifier scoped_pointer_type(CPPIdentifier *scoping);
static Modifier initializer_type(CPPParameterList *params);
@ -82,10 +86,13 @@ public:
int _func_flags;
CPPIdentifier *_scoping;
CPPExpression *_expr;
CPPType *_trailing_return_type;
};
typedef vector<Modifier> Modifiers;
Modifiers _modifiers;
int _bit_width;
private:
CPPType *
r_unroll_type(CPPType *start_type, Modifiers::const_iterator mi);

View File

@ -1367,6 +1367,50 @@ skip_cpp_comment(int c) {
return c;
}
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::skip_digit_separator
// Access: Private
// Description: Skips a C++14 digit separator that has just been
// found through peek().
////////////////////////////////////////////////////////////////////
int CPPPreprocessor::
skip_digit_separator(int c) {
if (c != '\'') {
return c;
}
get();
c = peek();
if (isdigit(c)) {
return c;
}
YYLTYPE loc;
loc.file = get_file();
loc.first_line = get_line_number();
loc.first_column = get_col_number();
loc.last_line = loc.first_line;
loc.last_column = loc.first_column;
if (c != '\'') {
// This assumes that this isn't a character constant directly follows
// a digit sequence, like 123'a' -- I can't think of a situation
// where that's legal anyway, though.
error("digit separator cannot occur at end of digit sequence", loc);
return c;
}
while (c == '\'') {
get();
++loc.last_column;
c = peek();
}
error("adjacent digit separators", loc);
return c;
}
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::process_directive
// Access: Private
@ -2395,7 +2439,8 @@ extract_manifest_args_inline(const string &name, int num_args,
////////////////////////////////////////////////////////////////////
// Function: CPPPreprocessor::get_number
// Access: Private
// Description:
// Description: Assuming that we've just read a digit or a period
// indicating the start of a number, read the rest.
////////////////////////////////////////////////////////////////////
CPPToken CPPPreprocessor::
get_number(int c) {
@ -2410,16 +2455,16 @@ get_number(int c) {
bool leading_zero = (c == '0');
bool decimal_point = (c == '.');
c = peek();
c = skip_digit_separator(peek());
if (leading_zero && c == 'x') {
if (leading_zero && (c == 'x' || c == 'X')) {
// Here we have a hex number.
num += get();
c = peek();
while (c != EOF && (isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f'))) {
num += get();
c = peek();
c = skip_digit_separator(peek());
}
loc.last_line = get_line_number();
@ -2429,11 +2474,30 @@ get_number(int c) {
result.u.integer = strtol(num.c_str(), (char **)NULL, 16);
return get_literal(INTEGER, loc, num, result);
} else if (leading_zero && (c == 'b' || c == 'B')) {
// A C++14-style binary number.
get();
c = peek();
string bin(1, (char)c);
while (c != EOF && (c == '0' || c == '1')) {
bin += get();
c = skip_digit_separator(peek());
}
loc.last_line = get_line_number();
loc.last_column = get_col_number();
YYSTYPE result;
result.u.integer = strtol(bin.c_str(), (char **)NULL, 2);
return get_literal(INTEGER, loc, bin, result);
}
while (c != EOF && isdigit(c)) {
num += get();
c = peek();
c = skip_digit_separator(peek());
}
if (c == '.' && !decimal_point) {
@ -2459,7 +2523,7 @@ get_number(int c) {
}
while (c != EOF && isdigit(c)) {
num += get();
c = peek();
c = skip_digit_separator(peek());
}
}
@ -2517,6 +2581,7 @@ check_keyword(const string &name) {
if (name == "__const") return KW_CONST;
if (name == "__const__") return KW_CONST;
if (name == "constexpr") return KW_CONSTEXPR;
if (name == "const_cast") return KW_CONST_CAST;
if (name == "decltype") return KW_DECLTYPE;
if (name == "default") return KW_DEFAULT;
if (name == "delete") return KW_DELETE;
@ -2530,6 +2595,7 @@ check_keyword(const string &name) {
if (name == "explicit") return KW_EXPLICIT;
if (name == "__published") return KW_PUBLISHED;
if (name == "false") return KW_FALSE;
if (name == "final") return KW_FINAL;
if (name == "float") return KW_FLOAT;
if (name == "friend") return KW_FRIEND;
if (name == "for") return KW_FOR;
@ -2549,10 +2615,12 @@ check_keyword(const string &name) {
if (name == "nullptr") return KW_NULLPTR;
if (name == "new") return KW_NEW;
if (name == "operator") return KW_OPERATOR;
if (name == "override") return KW_OVERRIDE;
if (name == "private") return KW_PRIVATE;
if (name == "protected") return KW_PROTECTED;
if (name == "public") return KW_PUBLIC;
if (name == "register") return KW_REGISTER;
if (name == "reinterpret_cast") return KW_REINTERPRET_CAST;
if (name == "return") return KW_RETURN;
if (name == "short") return KW_SHORT;
if (name == "signed") return KW_SIGNED;
@ -2562,10 +2630,12 @@ check_keyword(const string &name) {
if (name == "static_cast") return KW_STATIC_CAST;
if (name == "struct") return KW_STRUCT;
if (name == "template") return KW_TEMPLATE;
if (name == "thread_local") return KW_THREAD_LOCAL;
if (name == "throw") return KW_THROW;
if (name == "true") return KW_TRUE;
if (name == "try") return KW_TRY;
if (name == "typedef") return KW_TYPEDEF;
if (name == "typeid") return KW_TYPEID;
if (name == "typename") return KW_TYPENAME;
if (name == "union") return KW_UNION;
if (name == "unsigned") return KW_UNSIGNED;
@ -2589,10 +2659,6 @@ check_keyword(const string &name) {
if (name == "xor") return '^';
if (name == "xor_eq") return XOREQUAL;
if (!cpp_longlong_keyword.empty() && name == cpp_longlong_keyword) {
return KW_LONGLONG;
}
return 0;
}

View File

@ -126,6 +126,7 @@ private:
int skip_comment(int c);
int skip_c_comment(int c);
int skip_cpp_comment(int c);
int skip_digit_separator(int c);
int process_directive(int c);
int get_preprocessor_command(int c, string &command);

View File

@ -48,7 +48,8 @@ CPPStructType(CPPStructType::Type type, CPPIdentifier *ident,
CPPScope *current_scope, CPPScope *scope,
const CPPFile &file) :
CPPExtensionType(type, ident, current_scope, file),
_scope(scope)
_scope(scope),
_final(false)
{
_subst_decl_recursive_protect = false;
_incomplete = true;
@ -64,7 +65,8 @@ CPPStructType(const CPPStructType &copy) :
CPPExtensionType(copy),
_scope(copy._scope),
_incomplete(copy._incomplete),
_derivation(copy._derivation)
_derivation(copy._derivation),
_final(copy._final)
{
_subst_decl_recursive_protect = false;
}
@ -80,6 +82,7 @@ operator = (const CPPStructType &copy) {
_scope = copy._scope;
_incomplete = copy._incomplete;
_derivation = copy._derivation;
_final = copy._final;
}
////////////////////////////////////////////////////////////////////
@ -99,6 +102,15 @@ append_derivation(CPPType *base, CPPVisibility vis, bool is_virtual) {
def = base->as_typedef_type();
}
if (vis == V_unknown && base->as_extension_type() != NULL) {
// Default visibility.
if (base->as_extension_type()->_type == T_class) {
vis = V_private;
} else {
vis = V_public;
}
}
Base b;
b._base = base;
b._vis = vis;
@ -794,10 +806,14 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
out << _type;
}
if (_final) {
out << " final";
}
// Show any derivation we may have
if (!_derivation.empty()) {
Derivation::const_iterator di = _derivation.begin();
out << ": " << *di;
out << " : " << *di;
++di;
while (di != _derivation.end()) {
out << ", " << *di;

View File

@ -78,6 +78,7 @@ public:
CPPScope *_scope;
bool _incomplete;
bool _final;
class Base {
public:

View File

@ -200,6 +200,10 @@ output(ostream &out) const {
out << "UNARY_MINUS";
break;
case UNARY_PLUS:
out << "UNARY_PLUS";
break;
case UNARY_NEGATE:
out << "UNARY_NEGATE";
break;

View File

@ -25,7 +25,8 @@ CPPTypedefType::
CPPTypedefType(CPPType *type, const string &name, CPPScope *current_scope) :
CPPType(CPPFile()),
_type(type),
_ident(new CPPIdentifier(name))
_ident(new CPPIdentifier(name)),
_using(false)
{
if (_ident != NULL) {
_ident->_native_scope = current_scope;
@ -49,7 +50,8 @@ CPPTypedefType::
CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope) :
CPPType(CPPFile()),
_type(type),
_ident(ident)
_ident(ident),
_using(false)
{
if (_ident != NULL) {
_ident->_native_scope = current_scope;
@ -68,8 +70,10 @@ CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope) :
CPPTypedefType::
CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
CPPScope *current_scope, const CPPFile &file) :
CPPType(file)
CPPType(file),
_using(false)
{
assert(ii != NULL);
_type = ii->unroll_type(type);
_ident = ii->_ident;
ii->_ident = NULL;
@ -363,8 +367,14 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
}
if (complete) {
out << "typedef ";
_type->output_instance(out, indent_level, scope, false, "", name);
if (_using) {
// It was declared using the "using" keyword.
out << "using " << name << " = ";
_type->output(out, 0, scope, false);
} else {
out << "typedef ";
_type->output_instance(out, indent_level, scope, false, "", name);
}
} else {
out << name;
}
@ -401,7 +411,7 @@ is_equal(const CPPDeclaration *other) const {
const CPPTypedefType *ot = ((CPPDeclaration *)other)->as_typedef_type();
assert(ot != NULL);
return (*_type == *ot->_type) && (*_ident == *ot->_ident);
return (*_type == *ot->_type) && (*_ident == *ot->_ident) && (_using == ot->_using);
}
////////////////////////////////////////////////////////////////////

View File

@ -65,6 +65,7 @@ public:
CPPType *_type;
CPPIdentifier *_ident;
bool _using;
protected:
virtual bool is_equal(const CPPDeclaration *other) const;

View File

@ -36,8 +36,8 @@ using namespace std;
#define TYPENAME typename
#define CONSTEXPR constexpr
#define NOEXCEPT noexcept
#define FINAL
#define OVERRIDE
#define FINAL final
#define OVERRIDE override
#define MOVE(x) x
#define DEFAULT_CTOR = default

View File

@ -272,10 +272,6 @@ void show_help() {
<< " function wrappers already, from some external source. This is most\n"
<< " useful in conjunction with -true-names.\n\n"
<< " -longlong typename\n"
<< " Specify the name of the 64-bit integer type for the current compiler.\n"
<< " By default, this is \"long long\".\n\n"
<< " -promiscuous\n"
<< " Export *all* public symbols, functions, and classes seen, even those\n"
<< " not explicitly marked to be published.\n\n"
@ -436,6 +432,7 @@ main(int argc, char **argv) {
break;
case CO_longlong:
cerr << "Warning: ignoring deprecated -longlong option.\n";
cpp_longlong_keyword = optarg;
break;

View File

@ -1,5 +1,22 @@
#pragma once
class type_info;
class bad_cast;
class bad_typeid;
#include <stdtypedefs.h>
namespace std {
class type_info {
public:
type_info(const type_info& rhs) = delete;
virtual ~type_info();
type_info &operator = (const type_info &rhs) = delete;
bool operator ==(const type_info &rhs) const noexcept;
bool operator !=(const type_info &rhs) const noexcept;
bool before(const type_info &rhs) const noexcept;
size_t hash_code() const noexcept;
const char *name() const noexcept;
};
class bad_cast;
class bad_typeid;
}