mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
cppparser: support C++11 lambda expressions
This commit is contained in:
parent
5aabd56697
commit
e12420571b
@ -8,6 +8,7 @@
|
||||
|
||||
#include "cppBisonDefs.h"
|
||||
#include "cppParser.h"
|
||||
#include "cppClosureType.h"
|
||||
#include "cppExpression.h"
|
||||
#include "cppSimpleType.h"
|
||||
#include "cppExtensionType.h"
|
||||
@ -44,6 +45,7 @@ static CPPEnumType *current_enum = NULL;
|
||||
static int current_storage_class = 0;
|
||||
static CPPType *current_type = NULL;
|
||||
static CPPExpression *current_expr = NULL;
|
||||
static CPPClosureType *current_closure = NULL;
|
||||
static int publish_nest_level = 0;
|
||||
static CPPVisibility publish_previous;
|
||||
static YYLTYPE publish_loc;
|
||||
@ -363,6 +365,8 @@ pop_struct() {
|
||||
%type <u.param_list> function_parameters
|
||||
%type <u.param_list> formal_parameter_list
|
||||
%type <u.param_list> formal_parameters
|
||||
%type <u.closure_type> capture_list
|
||||
%type <u.capture> capture
|
||||
%type <u.expr> template_parameter_maybe_initialize
|
||||
%type <u.expr> maybe_initialize
|
||||
%type <u.expr> maybe_initialize_or_constructor_body
|
||||
@ -1221,6 +1225,15 @@ function_post:
|
||||
{
|
||||
$$ = $1 | (int)CPPFunctionType::F_noexcept;
|
||||
}
|
||||
/* | function_post KW_NOEXCEPT '(' const_expr ')'
|
||||
{
|
||||
CPPExpression::Result result = $4->evaluate();
|
||||
if (result._type == CPPExpression::RT_error) {
|
||||
yywarning("noexcept requires a constant expression", @4);
|
||||
} else if (result.as_boolean()) {
|
||||
$$ = $1 | (int)CPPFunctionType::F_noexcept;
|
||||
}
|
||||
}*/
|
||||
| function_post KW_FINAL
|
||||
{
|
||||
$$ = $1 | (int)CPPFunctionType::F_final;
|
||||
@ -1241,6 +1254,11 @@ function_post:
|
||||
{
|
||||
// Used for lambdas, currently ignored.
|
||||
$$ = $1;
|
||||
}
|
||||
| function_post KW_CONSTEXPR
|
||||
{
|
||||
// Used for lambdas in C++17, currently ignored.
|
||||
$$ = $1;
|
||||
}
|
||||
| function_post KW_THROW '(' ')'
|
||||
{
|
||||
@ -3468,11 +3486,16 @@ const_operand:
|
||||
}
|
||||
| '[' capture_list ']' function_post maybe_trailing_return_type '{' code '}'
|
||||
{
|
||||
$$ = NULL;
|
||||
$2->_flags = $4;
|
||||
$2->_return_type = $5;
|
||||
$$ = new CPPExpression(CPPExpression::lambda($2));
|
||||
}
|
||||
| '[' capture_list ']' '(' function_parameter_list ')' function_post maybe_trailing_return_type '{' code '}'
|
||||
{
|
||||
$$ = NULL;
|
||||
$2->_parameters = $5;
|
||||
$2->_flags = $7;
|
||||
$2->_return_type = $8;
|
||||
$$ = new CPPExpression(CPPExpression::lambda($2));
|
||||
}
|
||||
| KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
|
||||
{
|
||||
@ -3794,15 +3817,63 @@ formal_const_operand:
|
||||
/* The contents of the [] list preceding a lambda expression. */
|
||||
capture_list:
|
||||
empty
|
||||
{
|
||||
$$ = new CPPClosureType();
|
||||
}
|
||||
| '='
|
||||
{
|
||||
$$ = new CPPClosureType(CPPClosureType::CT_by_value);
|
||||
}
|
||||
| '&'
|
||||
{
|
||||
$$ = new CPPClosureType(CPPClosureType::CT_by_reference);
|
||||
}
|
||||
| capture
|
||||
| capture ',' capture_list
|
||||
{
|
||||
$$ = new CPPClosureType();
|
||||
$$->_captures.push_back(*$1);
|
||||
delete $1;
|
||||
}
|
||||
| capture_list ',' capture
|
||||
{
|
||||
$$ = $1;
|
||||
$$->_captures.push_back(*$3);
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
capture:
|
||||
'&'
|
||||
| '='
|
||||
| '&' name
|
||||
'&' name
|
||||
{
|
||||
$$ = new CPPClosureType::Capture;
|
||||
$$->_name = $2->get_simple_name();
|
||||
$$->_type = CPPClosureType::CT_by_reference;
|
||||
}
|
||||
| '&' name ELLIPSIS
|
||||
{
|
||||
$$ = new CPPClosureType::Capture;
|
||||
$$->_name = $2->get_simple_name();
|
||||
$$->_type = CPPClosureType::CT_by_reference;
|
||||
}
|
||||
| name
|
||||
{
|
||||
$$ = new CPPClosureType::Capture;
|
||||
$$->_name = $1->get_simple_name();
|
||||
if ($$->_name == "this") {
|
||||
$$->_type = CPPClosureType::CT_by_reference;
|
||||
} else {
|
||||
$$->_type = CPPClosureType::CT_by_value;
|
||||
}
|
||||
}
|
||||
| '*' name
|
||||
{
|
||||
$$ = new CPPClosureType::Capture;
|
||||
$$->_name = $2->get_simple_name();
|
||||
$$->_type = CPPClosureType::CT_by_value;
|
||||
if ($$->_name != "this") {
|
||||
yywarning("only capture name 'this' may be preceded by an asterisk", @2);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
class_derivation_name:
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cppClosureType.h"
|
||||
#include "cppExtensionType.h"
|
||||
#include "cppFile.h"
|
||||
|
||||
@ -42,6 +43,7 @@ class CPPParameterList;
|
||||
class CPPTemplateParameterList;
|
||||
class CPPScope;
|
||||
class CPPIdentifier;
|
||||
class CPPCaptureType;
|
||||
|
||||
void parse_cpp(CPPParser *cp);
|
||||
CPPExpression *parse_const_expr(CPPPreprocessor *pp,
|
||||
@ -81,6 +83,8 @@ public:
|
||||
CPPExtensionType::Type extension_enum;
|
||||
CPPExpression *expr;
|
||||
CPPIdentifier *identifier;
|
||||
CPPClosureType *closure_type;
|
||||
CPPClosureType::Capture *capture;
|
||||
} u;
|
||||
};
|
||||
#define YYSTYPE cppyystype
|
||||
|
188
dtool/src/cppparser/cppClosureType.cxx
Executable file
188
dtool/src/cppparser/cppClosureType.cxx
Executable file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cppClosureType.cxx
|
||||
* @author rdb
|
||||
* @date 2017-01-14
|
||||
*/
|
||||
|
||||
#include "cppClosureType.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPClosureType::
|
||||
CPPClosureType(CaptureType default_capture) :
|
||||
CPPFunctionType(NULL, NULL, 0),
|
||||
_default_capture(default_capture) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPClosureType::
|
||||
CPPClosureType(const CPPClosureType ©) :
|
||||
CPPFunctionType(copy),
|
||||
_captures(copy._captures),
|
||||
_default_capture(copy._default_capture)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void CPPClosureType::
|
||||
operator = (const CPPClosureType ©) {
|
||||
CPPFunctionType::operator = (copy);
|
||||
_captures = copy._captures;
|
||||
_default_capture = copy._default_capture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new capture to the beginning of the capture list.
|
||||
*/
|
||||
void CPPClosureType::
|
||||
add_capture(string name, CaptureType type) {
|
||||
if (type == CT_none) {
|
||||
if (name == "this") {
|
||||
type = CT_by_reference;
|
||||
} else {
|
||||
type = CT_by_value;
|
||||
}
|
||||
}
|
||||
|
||||
Capture capture = {move(name), type};
|
||||
_captures.insert(_captures.begin(), move(capture));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this declaration is an actual, factual declaration, or
|
||||
* false if some part of the declaration depends on a template parameter which
|
||||
* has not yet been instantiated.
|
||||
*/
|
||||
bool CPPClosureType::
|
||||
is_fully_specified() const {
|
||||
return CPPFunctionType::is_fully_specified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is default-constructible.
|
||||
*/
|
||||
bool CPPClosureType::
|
||||
is_default_constructible() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is copy-constructible.
|
||||
*/
|
||||
bool CPPClosureType::
|
||||
is_copy_constructible() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is destructible.
|
||||
*/
|
||||
bool CPPClosureType::
|
||||
is_destructible() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void CPPClosureType::
|
||||
output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
|
||||
out.put('[');
|
||||
|
||||
bool have_capture = false;
|
||||
switch (_default_capture) {
|
||||
case CT_none:
|
||||
break;
|
||||
case CT_by_reference:
|
||||
out.put('&');
|
||||
have_capture = true;
|
||||
break;
|
||||
case CT_by_value:
|
||||
out.put('=');
|
||||
have_capture = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Captures::const_iterator it;
|
||||
for (it = _captures.begin(); it != _captures.end(); ++it) {
|
||||
if (have_capture) {
|
||||
out << ", ";
|
||||
}
|
||||
if ((*it)._name == "this") {
|
||||
if ((*it)._type == CT_by_value) {
|
||||
out.put('*');
|
||||
}
|
||||
} else {
|
||||
if ((*it)._type == CT_by_reference) {
|
||||
out.put('&');
|
||||
}
|
||||
}
|
||||
out << (*it)._name;
|
||||
have_capture = true;
|
||||
}
|
||||
out.put(']');
|
||||
|
||||
if (_parameters != NULL) {
|
||||
out.put('(');
|
||||
_parameters->output(out, scope, true, -1);
|
||||
out.put(')');
|
||||
}
|
||||
|
||||
if (_flags & F_noexcept) {
|
||||
out << " noexcept";
|
||||
}
|
||||
|
||||
if (_return_type != NULL) {
|
||||
out << " -> ";
|
||||
_return_type->output(out, indent_level, scope, false);
|
||||
}
|
||||
|
||||
out << " {}";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPDeclaration::SubType CPPClosureType::
|
||||
get_subtype() const {
|
||||
return ST_closure;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPClosureType *CPPClosureType::
|
||||
as_closure_type() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by CPPDeclaration() to determine whether this type is equivalent to
|
||||
* another type of the same type.
|
||||
*/
|
||||
bool CPPClosureType::
|
||||
is_equal(const CPPDeclaration *other) const {
|
||||
return (this == other);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by CPPDeclaration() to determine whether this type should be ordered
|
||||
* before another type of the same type, in an arbitrary but fixed ordering.
|
||||
*/
|
||||
bool CPPClosureType::
|
||||
is_less(const CPPDeclaration *other) const {
|
||||
return (this < other);
|
||||
}
|
64
dtool/src/cppparser/cppClosureType.h
Executable file
64
dtool/src/cppparser/cppClosureType.h
Executable file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cppClosureType.h
|
||||
* @author rdb
|
||||
* @date 2017-01-14
|
||||
*/
|
||||
|
||||
#ifndef CPPCLOSURETYPE_H
|
||||
#define CPPCLOSURETYPE_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
|
||||
#include "cppFunctionType.h"
|
||||
|
||||
/**
|
||||
* The type of a lambda expression. This is like a function, but with
|
||||
* additional captures defined.
|
||||
*/
|
||||
class CPPClosureType : public CPPFunctionType {
|
||||
public:
|
||||
enum CaptureType {
|
||||
CT_none,
|
||||
CT_by_reference,
|
||||
CT_by_value,
|
||||
};
|
||||
|
||||
CPPClosureType(CaptureType default_capture = CT_none);
|
||||
CPPClosureType(const CPPClosureType ©);
|
||||
void operator = (const CPPClosureType ©);
|
||||
|
||||
struct Capture {
|
||||
string _name;
|
||||
CaptureType _type;
|
||||
};
|
||||
typedef vector<Capture> Captures;
|
||||
Captures _captures;
|
||||
|
||||
CaptureType _default_capture;
|
||||
|
||||
void add_capture(string name, CaptureType type);
|
||||
|
||||
virtual bool is_fully_specified() const;
|
||||
|
||||
virtual bool is_default_constructible() const;
|
||||
virtual bool is_copy_constructible() const;
|
||||
virtual bool is_destructible() const;
|
||||
|
||||
virtual void output(ostream &out, int indent_level, CPPScope *scope,
|
||||
bool complete) const;
|
||||
virtual SubType get_subtype() const;
|
||||
virtual CPPClosureType *as_closure_type();
|
||||
|
||||
protected:
|
||||
virtual bool is_equal(const CPPDeclaration *other) const;
|
||||
virtual bool is_less(const CPPDeclaration *other) const;
|
||||
};
|
||||
|
||||
#endif
|
@ -311,6 +311,14 @@ as_make_seq() {
|
||||
return (CPPMakeSeq *)NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPClosureType *CPPDeclaration::
|
||||
as_closure_type() {
|
||||
return (CPPClosureType *)NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by CPPDeclaration to determine whether this type is equivalent to
|
||||
* another type of the same type.
|
||||
|
@ -48,6 +48,7 @@ class CPPEnumType;
|
||||
class CPPTypeProxy;
|
||||
class CPPMakeProperty;
|
||||
class CPPMakeSeq;
|
||||
class CPPClosureType;
|
||||
class CPPClassTemplateParameter;
|
||||
class CPPTBDType;
|
||||
class CPPScope;
|
||||
@ -85,6 +86,7 @@ public:
|
||||
ST_tbd,
|
||||
ST_type_proxy,
|
||||
ST_typedef,
|
||||
ST_closure,
|
||||
};
|
||||
|
||||
CPPDeclaration(const CPPFile &file);
|
||||
@ -140,6 +142,7 @@ public:
|
||||
virtual CPPTypeProxy *as_type_proxy();
|
||||
virtual CPPMakeProperty *as_make_property();
|
||||
virtual CPPMakeSeq *as_make_seq();
|
||||
virtual CPPClosureType *as_closure_type();
|
||||
|
||||
inline const CPPInstance *as_instance() const {
|
||||
return ((CPPDeclaration *)this)->as_instance();
|
||||
@ -207,6 +210,9 @@ public:
|
||||
inline const CPPMakeSeq *as_make_seq() const {
|
||||
return ((CPPDeclaration *)this)->as_make_seq();
|
||||
}
|
||||
inline const CPPClosureType *as_closure_type() const {
|
||||
return ((CPPDeclaration *)this)->as_closure_type();
|
||||
}
|
||||
|
||||
CPPVisibility _vis;
|
||||
CPPTemplateScope *_template_scope;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "cppInstance.h"
|
||||
#include "cppFunctionGroup.h"
|
||||
#include "cppFunctionType.h"
|
||||
#include "cppClosureType.h"
|
||||
#include "cppStructType.h"
|
||||
#include "cppBison.h"
|
||||
#include "pdtoa.h"
|
||||
@ -438,6 +439,17 @@ alignof_func(CPPType *type) {
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CPPExpression CPPExpression::
|
||||
lambda(CPPClosureType *type) {
|
||||
CPPExpression expr(0);
|
||||
expr._type = T_lambda;
|
||||
expr._u._closure_type = type;
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -1169,6 +1181,9 @@ determine_type() const {
|
||||
case T_type_trait:
|
||||
return bool_type;
|
||||
|
||||
case T_lambda:
|
||||
return _u._closure_type;
|
||||
|
||||
default:
|
||||
cerr << "**invalid operand**\n";
|
||||
abort();
|
||||
@ -1259,6 +1274,9 @@ is_fully_specified() const {
|
||||
case T_type_trait:
|
||||
return _u._type_trait._type->is_fully_specified();
|
||||
|
||||
case T_lambda:
|
||||
return _u._closure_type->is_fully_specified();
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
@ -1478,6 +1496,9 @@ is_tbd() const {
|
||||
case T_type_trait:
|
||||
return _u._type_trait._type->is_tbd();
|
||||
|
||||
case T_lambda:
|
||||
return _u._closure_type->is_tbd();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -1950,6 +1971,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
|
||||
out << ')';
|
||||
break;
|
||||
|
||||
case T_lambda:
|
||||
_u._closure_type->output(out, indent_level, scope, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
out << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
@ -2109,6 +2134,9 @@ is_equal(const CPPDeclaration *other) const {
|
||||
return _u._type_trait._trait == ot->_u._type_trait._trait &&
|
||||
_u._type_trait._type == ot->_u._type_trait._type;
|
||||
|
||||
case T_lambda:
|
||||
return _u._closure_type == ot->_u._closure_type;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
@ -2216,6 +2244,9 @@ is_less(const CPPDeclaration *other) const {
|
||||
}
|
||||
return *_u._type_trait._type < *ot->_u._type_trait._type;
|
||||
|
||||
case T_lambda:
|
||||
return _u._closure_type < ot->_u._closure_type;
|
||||
|
||||
default:
|
||||
cerr << "(** invalid operand type " << (int)_type << " **)";
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ public:
|
||||
T_typeid_type,
|
||||
T_typeid_expr,
|
||||
T_type_trait,
|
||||
T_lambda,
|
||||
|
||||
// These are used when parsing =default and =delete methods.
|
||||
T_default,
|
||||
@ -87,6 +88,7 @@ public:
|
||||
static CPPExpression sizeof_func(CPPType *type);
|
||||
static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
|
||||
static CPPExpression alignof_func(CPPType *type);
|
||||
static CPPExpression lambda(CPPClosureType *type);
|
||||
|
||||
static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
|
||||
static CPPExpression literal(long double value, CPPInstance *lit_op);
|
||||
@ -150,6 +152,7 @@ public:
|
||||
CPPInstance *_variable;
|
||||
CPPFunctionGroup *_fgroup;
|
||||
CPPIdentifier *_ident;
|
||||
CPPClosureType *_closure_type;
|
||||
struct {
|
||||
union {
|
||||
CPPType *_type;
|
||||
|
@ -31,7 +31,8 @@ CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
|
||||
|
||||
// If the parameter list contains just the token "void", it means no
|
||||
// parameters.
|
||||
if (_parameters->_parameters.size() == 1 &&
|
||||
if (_parameters != NULL &&
|
||||
_parameters->_parameters.size() == 1 &&
|
||||
_parameters->_parameters.front()->_type->as_simple_type() != NULL &&
|
||||
_parameters->_parameters.front()->_type->as_simple_type()->_type ==
|
||||
CPPSimpleType::T_void &&
|
||||
@ -95,8 +96,10 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
||||
->as_type();
|
||||
}
|
||||
|
||||
rep->_parameters =
|
||||
_parameters->substitute_decl(subst, current_scope, global_scope);
|
||||
if (_parameters != NULL) {
|
||||
rep->_parameters =
|
||||
_parameters->substitute_decl(subst, current_scope, global_scope);
|
||||
}
|
||||
|
||||
if (rep->_return_type == _return_type &&
|
||||
rep->_parameters == _parameters) {
|
||||
@ -117,8 +120,12 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
|
||||
CPPType *CPPFunctionType::
|
||||
resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
|
||||
CPPType *rtype = _return_type->resolve_type(current_scope, global_scope);
|
||||
CPPParameterList *params =
|
||||
_parameters->resolve_type(current_scope, global_scope);
|
||||
CPPParameterList *params;
|
||||
if (_parameters == NULL) {
|
||||
params = NULL;
|
||||
} else {
|
||||
params = _parameters->resolve_type(current_scope, global_scope);
|
||||
}
|
||||
|
||||
if (rtype != _return_type || params != _parameters) {
|
||||
CPPFunctionType *rep = new CPPFunctionType(*this);
|
||||
@ -139,7 +146,7 @@ is_tbd() const {
|
||||
if (_return_type->is_tbd()) {
|
||||
return true;
|
||||
}
|
||||
return _parameters->is_tbd();
|
||||
return _parameters == NULL || _parameters->is_tbd();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -294,6 +301,10 @@ get_num_default_parameters() const {
|
||||
// The trick is just to count, beginning from the end and working towards
|
||||
// the front, the number of parameters that have some initializer.
|
||||
|
||||
if (_parameters == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CPPParameterList::Parameters ¶ms = _parameters->_parameters;
|
||||
CPPParameterList::Parameters::const_reverse_iterator pi;
|
||||
int count = 0;
|
||||
@ -362,7 +373,11 @@ is_equal(const CPPDeclaration *other) const {
|
||||
if (_flags != ot->_flags) {
|
||||
return false;
|
||||
}
|
||||
if (*_parameters != *ot->_parameters) {
|
||||
if (_parameters == ot->_parameters) {
|
||||
return true;
|
||||
}
|
||||
if (_parameters == NULL || ot->_parameters == NULL ||
|
||||
*_parameters != *ot->_parameters) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -384,6 +399,11 @@ is_less(const CPPDeclaration *other) const {
|
||||
if (_flags != ot->_flags) {
|
||||
return _flags < ot->_flags;
|
||||
}
|
||||
|
||||
if (_parameters == ot->_parameters) {
|
||||
return 0;
|
||||
}
|
||||
if (_parameters == NULL || ot->_parameters == NULL) {
|
||||
return _parameters < ot->_parameters;
|
||||
}
|
||||
return *_parameters < *ot->_parameters;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "cppFunctionType.cxx"
|
||||
#include "cppGlobals.cxx"
|
||||
#include "cppCommentBlock.cxx"
|
||||
#include "cppClosureType.cxx"
|
||||
#include "cppConstType.cxx"
|
||||
#include "cppDeclaration.cxx"
|
||||
#include "cppMakeProperty.cxx"
|
||||
|
Loading…
x
Reference in New Issue
Block a user