cppparser: Implement is_trivially_copyable type trait

This commit is contained in:
rdb 2023-02-20 21:04:36 +01:00
parent 88a6484ab3
commit 5e24e7347c
27 changed files with 3832 additions and 3639 deletions

View File

@ -80,6 +80,14 @@ is_trivial() const {
return _element_type->is_trivial();
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPArrayType::
is_trivially_copyable() const {
return _element_type->is_trivially_copyable();
}
/**
* Returns true if the type is default-constructible.
*/

View File

@ -40,6 +40,7 @@ public:
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;
virtual bool is_copy_assignable() const;

File diff suppressed because it is too large Load Diff

View File

@ -155,55 +155,56 @@ extern int cppyydebug;
KW_IS_POLYMORPHIC = 356, /* KW_IS_POLYMORPHIC */
KW_IS_STANDARD_LAYOUT = 357, /* KW_IS_STANDARD_LAYOUT */
KW_IS_TRIVIAL = 358, /* KW_IS_TRIVIAL */
KW_IS_UNION = 359, /* KW_IS_UNION */
KW_LONG = 360, /* KW_LONG */
KW_MAKE_MAP_KEYS_SEQ = 361, /* KW_MAKE_MAP_KEYS_SEQ */
KW_MAKE_MAP_PROPERTY = 362, /* KW_MAKE_MAP_PROPERTY */
KW_MAKE_PROPERTY = 363, /* KW_MAKE_PROPERTY */
KW_MAKE_PROPERTY2 = 364, /* KW_MAKE_PROPERTY2 */
KW_MAKE_SEQ = 365, /* KW_MAKE_SEQ */
KW_MAKE_SEQ_PROPERTY = 366, /* KW_MAKE_SEQ_PROPERTY */
KW_MUTABLE = 367, /* KW_MUTABLE */
KW_NAMESPACE = 368, /* KW_NAMESPACE */
KW_NEW = 369, /* KW_NEW */
KW_NOEXCEPT = 370, /* KW_NOEXCEPT */
KW_NOEXCEPT_LPAREN = 371, /* KW_NOEXCEPT_LPAREN */
KW_NULLPTR = 372, /* KW_NULLPTR */
KW_OPERATOR = 373, /* KW_OPERATOR */
KW_OVERRIDE = 374, /* KW_OVERRIDE */
KW_PRIVATE = 375, /* KW_PRIVATE */
KW_PROTECTED = 376, /* KW_PROTECTED */
KW_PUBLIC = 377, /* KW_PUBLIC */
KW_REGISTER = 378, /* KW_REGISTER */
KW_REINTERPRET_CAST = 379, /* KW_REINTERPRET_CAST */
KW_RETURN = 380, /* KW_RETURN */
KW_SHORT = 381, /* KW_SHORT */
KW_SIGNED = 382, /* KW_SIGNED */
KW_SIZEOF = 383, /* KW_SIZEOF */
KW_STATIC = 384, /* KW_STATIC */
KW_STATIC_ASSERT = 385, /* KW_STATIC_ASSERT */
KW_STATIC_CAST = 386, /* KW_STATIC_CAST */
KW_STRUCT = 387, /* KW_STRUCT */
KW_TEMPLATE = 388, /* KW_TEMPLATE */
KW_THREAD_LOCAL = 389, /* KW_THREAD_LOCAL */
KW_THROW = 390, /* KW_THROW */
KW_TRUE = 391, /* KW_TRUE */
KW_TRY = 392, /* KW_TRY */
KW_TYPEDEF = 393, /* KW_TYPEDEF */
KW_TYPEID = 394, /* KW_TYPEID */
KW_TYPENAME = 395, /* KW_TYPENAME */
KW_UNDERLYING_TYPE = 396, /* KW_UNDERLYING_TYPE */
KW_UNION = 397, /* KW_UNION */
KW_UNSIGNED = 398, /* KW_UNSIGNED */
KW_USING = 399, /* KW_USING */
KW_VIRTUAL = 400, /* KW_VIRTUAL */
KW_VOID = 401, /* KW_VOID */
KW_VOLATILE = 402, /* KW_VOLATILE */
KW_WCHAR_T = 403, /* KW_WCHAR_T */
KW_WHILE = 404, /* KW_WHILE */
START_CPP = 405, /* START_CPP */
START_CONST_EXPR = 406, /* START_CONST_EXPR */
START_TYPE = 407 /* START_TYPE */
KW_IS_TRIVIALLY_COPYABLE = 359, /* KW_IS_TRIVIALLY_COPYABLE */
KW_IS_UNION = 360, /* KW_IS_UNION */
KW_LONG = 361, /* KW_LONG */
KW_MAKE_MAP_KEYS_SEQ = 362, /* KW_MAKE_MAP_KEYS_SEQ */
KW_MAKE_MAP_PROPERTY = 363, /* KW_MAKE_MAP_PROPERTY */
KW_MAKE_PROPERTY = 364, /* KW_MAKE_PROPERTY */
KW_MAKE_PROPERTY2 = 365, /* KW_MAKE_PROPERTY2 */
KW_MAKE_SEQ = 366, /* KW_MAKE_SEQ */
KW_MAKE_SEQ_PROPERTY = 367, /* KW_MAKE_SEQ_PROPERTY */
KW_MUTABLE = 368, /* KW_MUTABLE */
KW_NAMESPACE = 369, /* KW_NAMESPACE */
KW_NEW = 370, /* KW_NEW */
KW_NOEXCEPT = 371, /* KW_NOEXCEPT */
KW_NOEXCEPT_LPAREN = 372, /* KW_NOEXCEPT_LPAREN */
KW_NULLPTR = 373, /* KW_NULLPTR */
KW_OPERATOR = 374, /* KW_OPERATOR */
KW_OVERRIDE = 375, /* KW_OVERRIDE */
KW_PRIVATE = 376, /* KW_PRIVATE */
KW_PROTECTED = 377, /* KW_PROTECTED */
KW_PUBLIC = 378, /* KW_PUBLIC */
KW_REGISTER = 379, /* KW_REGISTER */
KW_REINTERPRET_CAST = 380, /* KW_REINTERPRET_CAST */
KW_RETURN = 381, /* KW_RETURN */
KW_SHORT = 382, /* KW_SHORT */
KW_SIGNED = 383, /* KW_SIGNED */
KW_SIZEOF = 384, /* KW_SIZEOF */
KW_STATIC = 385, /* KW_STATIC */
KW_STATIC_ASSERT = 386, /* KW_STATIC_ASSERT */
KW_STATIC_CAST = 387, /* KW_STATIC_CAST */
KW_STRUCT = 388, /* KW_STRUCT */
KW_TEMPLATE = 389, /* KW_TEMPLATE */
KW_THREAD_LOCAL = 390, /* KW_THREAD_LOCAL */
KW_THROW = 391, /* KW_THROW */
KW_TRUE = 392, /* KW_TRUE */
KW_TRY = 393, /* KW_TRY */
KW_TYPEDEF = 394, /* KW_TYPEDEF */
KW_TYPEID = 395, /* KW_TYPEID */
KW_TYPENAME = 396, /* KW_TYPENAME */
KW_UNDERLYING_TYPE = 397, /* KW_UNDERLYING_TYPE */
KW_UNION = 398, /* KW_UNION */
KW_UNSIGNED = 399, /* KW_UNSIGNED */
KW_USING = 400, /* KW_USING */
KW_VIRTUAL = 401, /* KW_VIRTUAL */
KW_VOID = 402, /* KW_VOID */
KW_VOLATILE = 403, /* KW_VOLATILE */
KW_WCHAR_T = 404, /* KW_WCHAR_T */
KW_WHILE = 405, /* KW_WHILE */
START_CPP = 406, /* START_CPP */
START_CONST_EXPR = 407, /* START_CONST_EXPR */
START_TYPE = 408 /* START_TYPE */
};
typedef enum yytokentype yytoken_kind_t;
#endif
@ -313,55 +314,56 @@ extern int cppyydebug;
#define KW_IS_POLYMORPHIC 356
#define KW_IS_STANDARD_LAYOUT 357
#define KW_IS_TRIVIAL 358
#define KW_IS_UNION 359
#define KW_LONG 360
#define KW_MAKE_MAP_KEYS_SEQ 361
#define KW_MAKE_MAP_PROPERTY 362
#define KW_MAKE_PROPERTY 363
#define KW_MAKE_PROPERTY2 364
#define KW_MAKE_SEQ 365
#define KW_MAKE_SEQ_PROPERTY 366
#define KW_MUTABLE 367
#define KW_NAMESPACE 368
#define KW_NEW 369
#define KW_NOEXCEPT 370
#define KW_NOEXCEPT_LPAREN 371
#define KW_NULLPTR 372
#define KW_OPERATOR 373
#define KW_OVERRIDE 374
#define KW_PRIVATE 375
#define KW_PROTECTED 376
#define KW_PUBLIC 377
#define KW_REGISTER 378
#define KW_REINTERPRET_CAST 379
#define KW_RETURN 380
#define KW_SHORT 381
#define KW_SIGNED 382
#define KW_SIZEOF 383
#define KW_STATIC 384
#define KW_STATIC_ASSERT 385
#define KW_STATIC_CAST 386
#define KW_STRUCT 387
#define KW_TEMPLATE 388
#define KW_THREAD_LOCAL 389
#define KW_THROW 390
#define KW_TRUE 391
#define KW_TRY 392
#define KW_TYPEDEF 393
#define KW_TYPEID 394
#define KW_TYPENAME 395
#define KW_UNDERLYING_TYPE 396
#define KW_UNION 397
#define KW_UNSIGNED 398
#define KW_USING 399
#define KW_VIRTUAL 400
#define KW_VOID 401
#define KW_VOLATILE 402
#define KW_WCHAR_T 403
#define KW_WHILE 404
#define START_CPP 405
#define START_CONST_EXPR 406
#define START_TYPE 407
#define KW_IS_TRIVIALLY_COPYABLE 359
#define KW_IS_UNION 360
#define KW_LONG 361
#define KW_MAKE_MAP_KEYS_SEQ 362
#define KW_MAKE_MAP_PROPERTY 363
#define KW_MAKE_PROPERTY 364
#define KW_MAKE_PROPERTY2 365
#define KW_MAKE_SEQ 366
#define KW_MAKE_SEQ_PROPERTY 367
#define KW_MUTABLE 368
#define KW_NAMESPACE 369
#define KW_NEW 370
#define KW_NOEXCEPT 371
#define KW_NOEXCEPT_LPAREN 372
#define KW_NULLPTR 373
#define KW_OPERATOR 374
#define KW_OVERRIDE 375
#define KW_PRIVATE 376
#define KW_PROTECTED 377
#define KW_PUBLIC 378
#define KW_REGISTER 379
#define KW_REINTERPRET_CAST 380
#define KW_RETURN 381
#define KW_SHORT 382
#define KW_SIGNED 383
#define KW_SIZEOF 384
#define KW_STATIC 385
#define KW_STATIC_ASSERT 386
#define KW_STATIC_CAST 387
#define KW_STRUCT 388
#define KW_TEMPLATE 389
#define KW_THREAD_LOCAL 390
#define KW_THROW 391
#define KW_TRUE 392
#define KW_TRY 393
#define KW_TYPEDEF 394
#define KW_TYPEID 395
#define KW_TYPENAME 396
#define KW_UNDERLYING_TYPE 397
#define KW_UNION 398
#define KW_UNSIGNED 399
#define KW_USING 400
#define KW_VIRTUAL 401
#define KW_VOID 402
#define KW_VOLATILE 403
#define KW_WCHAR_T 404
#define KW_WHILE 405
#define START_CPP 406
#define START_CONST_EXPR 407
#define START_TYPE 408
/* Value type. */

View File

@ -310,6 +310,7 @@ pop_struct() {
%token KW_IS_POLYMORPHIC
%token KW_IS_STANDARD_LAYOUT
%token KW_IS_TRIVIAL
%token KW_IS_TRIVIALLY_COPYABLE
%token KW_IS_UNION
%token KW_LONG
%token KW_MAKE_MAP_KEYS_SEQ
@ -3939,6 +3940,10 @@ const_operand:
| KW_IS_TRIVIAL '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIAL, $3));
}
| KW_IS_TRIVIALLY_COPYABLE '(' full_type ')'
{
$$ = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIALLY_COPYABLE, $3));
}
| KW_IS_UNION '(' full_type ')'
{

View File

@ -110,6 +110,14 @@ is_trivial() const {
return _wrapped_around->is_trivial();
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPConstType::
is_trivially_copyable() const {
return _wrapped_around->is_trivially_copyable();
}
/**
* Returns true if the type can be constructed using the given argument.
*/

View File

@ -39,6 +39,7 @@ public:
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -953,6 +953,9 @@ evaluate() const {
case KW_IS_TRIVIAL:
return Result(_u._type_trait._type->is_trivial());
case KW_IS_TRIVIALLY_COPYABLE:
return Result(_u._type_trait._type->is_trivially_copyable());
case KW_IS_UNION:
{
CPPExtensionType *ext_type = _u._type_trait._type->as_extension_type();
@ -2138,6 +2141,9 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool) const {
case KW_IS_TRIVIAL:
out << "__is_trivial";
break;
case KW_IS_TRIVIALLY_COPYABLE:
out << "__is_trivially_copyable";
break;
case KW_IS_UNION:
out << "__is_union";
break;

View File

@ -104,6 +104,14 @@ is_trivial() const {
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPExtensionType::
is_trivially_copyable() const {
return (_type == T_enum || _type == T_enum_class || _type == T_enum_struct);
}
/**
* Returns true if the type can be constructed using the given argument.
*/

View File

@ -49,6 +49,7 @@ public:
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -188,6 +188,14 @@ is_trivial() const {
return false;
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPFunctionType::
is_trivially_copyable() const {
return false;
}
/**
*
*/

View File

@ -68,6 +68,7 @@ public:
virtual bool is_tbd() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual void output(std::ostream &out, int indent_level, CPPScope *scope,
bool complete) const;

View File

@ -107,6 +107,14 @@ is_trivial() const {
return true;
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPPointerType::
is_trivially_copyable() const {
return true;
}
/**
* Returns true if the type can be constructed using the given argument.
*/

View File

@ -38,6 +38,7 @@ public:
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *other) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -2680,6 +2680,7 @@ check_keyword(const string &name) {
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_trivially_copyable") return KW_IS_TRIVIALLY_COPYABLE;
if (name == "__is_union") return KW_IS_UNION;
if (name == "long") return KW_LONG;
if (name == "__make_map_keys_seq") return KW_MAKE_MAP_KEYS_SEQ;

View File

@ -105,6 +105,14 @@ is_trivial() const {
return false;
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPReferenceType::
is_trivially_copyable() const {
return false;
}
/**
* Returns true if the type can be constructed using the given argument.
*/

View File

@ -44,6 +44,7 @@ public:
virtual bool is_tbd() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -63,7 +63,15 @@ is_standard_layout() const {
*/
bool CPPSimpleType::
is_trivial() const {
return true;
return (_type != T_unknown && _type != T_parameter && _type != T_auto);
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPSimpleType::
is_trivially_copyable() const {
return (_type != T_unknown && _type != T_parameter && _type != T_auto);
}
/**

View File

@ -73,6 +73,7 @@ public:
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -355,6 +355,80 @@ is_trivial() const {
return is_default_constructible(V_public);
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPStructType::
is_trivially_copyable() const {
// Make sure all base classes are trivially copyable 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 != nullptr && !base->is_trivially_copyable())) {
return false;
}
}
assert(_scope != nullptr);
// Make sure all members are trivially copyable.
CPPScope::Variables::const_iterator vi;
for (vi = _scope->_variables.begin(); vi != _scope->_variables.end(); ++vi) {
CPPInstance *instance = (*vi).second;
assert(instance != nullptr);
if (instance->_storage_class & CPPInstance::SC_static) {
// Static members don't count.
continue;
}
assert(instance->_type != nullptr);
if (!instance->_type->is_trivially_copyable()) {
return false;
}
}
// Now look for functions that are virtual or con/destructors.
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_virtual) {
// Virtual functions are banned right off the bat.
return false;
}
// The following checks don't apply for defaulted functions.
if (inst->_storage_class & CPPInstance::SC_defaulted) {
continue;
}
assert(inst->_type != nullptr);
CPPFunctionType *ftype = inst->_type->as_function_type();
assert(ftype != nullptr);
if (ftype->_flags & (CPPFunctionType::F_destructor |
CPPFunctionType::F_move_constructor |
CPPFunctionType::F_copy_constructor)) {
// User-provided destructors and copy/move constructors are not
// trivial unless they are defaulted (and not virtual).
return false;
}
if (fgroup->_name == "operator =") {
// Or assignment operators.
return false;
}
}
}
return true;
}
/**
* 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

View File

@ -54,6 +54,7 @@ public:
virtual bool is_incomplete() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *arg_type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -88,6 +88,14 @@ is_trivial() const {
return false;
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPType::
is_trivially_copyable() const {
return false;
}
/**
* Returns true if the type can be constructed using the given argument.
*/

View File

@ -48,6 +48,7 @@ public:
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -187,6 +187,14 @@ is_trivial() const {
return _type->is_trivial();
}
/**
* Returns true if the type can be safely copied by memcpy or memmove.
*/
bool CPPTypedefType::
is_trivially_copyable() const {
return _type->is_trivially_copyable();
}
/**
* Returns true if the type can be constructed using the given argument.
*/

View File

@ -46,6 +46,7 @@ public:
virtual bool is_fundamental() const;
virtual bool is_standard_layout() const;
virtual bool is_trivial() const;
virtual bool is_trivially_copyable() const;
virtual bool is_constructible(const CPPType *type) const;
virtual bool is_default_constructible() const;
virtual bool is_copy_constructible() const;

View File

@ -82,6 +82,7 @@ show_type_or_expression(const string &str) {
<< "is_fundamental = " << type->is_fundamental() << "\n"
<< "is_standard_layout = " << type->is_standard_layout() << "\n"
<< "is_trivial = " << type->is_trivial() << "\n"
<< "is_trivially_copyable = " << type->is_trivially_copyable() << "\n"
<< "is_default_constructible = " << type->is_default_constructible() << "\n"
<< "is_copy_constructible = " << type->is_copy_constructible() << "\n"
<< "is_copy_assignable = " << type->is_copy_assignable() << "\n"

View File

@ -47,6 +47,9 @@ namespace std {
template<class T>
struct is_trivial : integral_constant<bool, __is_trivial(T)> {};
template<class T>
struct is_trivially_copyable : integral_constant<bool, __is_trivially_copyable(T)> {};
template<class T>
struct is_standard_layout : integral_constant<bool, __is_standard_layout(T)> {};