Skip to content

Commit

Permalink
cppparser: support for various C++11/C++14/C++17 features:
Browse files Browse the repository at this point in the history
 - decltype(auto)
 - attributes (ie. [[deprecated]]), incl. with C++17 "using"
 - extern template class (parses)
 - sizeof struct members
 - aggregate initialization
 - initializers in capture lists
 - alignas (parses)
  • Loading branch information
rdb committed Jan 15, 2017
1 parent e124205 commit e2771d3
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 43 deletions.
138 changes: 105 additions & 33 deletions dtool/src/cppparser/cppBison.yxx
Expand Up @@ -249,6 +249,8 @@ pop_struct() {
%token XOREQUAL
%token LSHIFTEQUAL
%token RSHIFTEQUAL
%token ATTR_LEFT
%token ATTR_RIGHT

%token KW_ALIGNAS
%token KW_ALIGNOF
Expand Down Expand Up @@ -874,10 +876,18 @@ storage_class:
{
$$ = $2 | (int)CPPInstance::SC_thread_local;
}
| '[' '[' attribute_specifiers ']' ']' storage_class
| ATTR_LEFT attribute_specifiers ATTR_RIGHT storage_class
{
// Ignore attribute specifiers for now.
$$ = $6;
$$ = $4;
}
| KW_ALIGNAS '(' const_expr ')' storage_class
{
$$ = $5;
}
| KW_ALIGNAS '(' type_decl ')' storage_class
{
$$ = $5;
}
;

Expand All @@ -889,6 +899,7 @@ attribute_specifiers:
attribute_specifier:
name
| name '(' formal_parameter_list ')'
| KW_USING name ':' attribute_specifier
;

type_like_declaration:
Expand Down Expand Up @@ -1272,10 +1283,10 @@ function_post:
{
$$ = $1;
}
/* | function_post '[' '[' attribute_specifiers ']' ']'
| function_post ATTR_LEFT attribute_specifiers ATTR_RIGHT
{
$$ = $1;
}*/
}
;

function_operator:
Expand Down Expand Up @@ -1443,15 +1454,16 @@ more_template_declaration:
;

template_declaration:
KW_TEMPLATE
KW_EXTERN template_declaration
| KW_TEMPLATE
{
push_scope(new CPPTemplateScope(current_scope));
}
'<' template_formal_parameters '>' more_template_declaration
{
pop_scope();
}
| KW_TEMPLATE type_like_declaration
| KW_TEMPLATE type_like_declaration
;

template_formal_parameters:
Expand Down Expand Up @@ -1903,6 +1915,10 @@ function_parameter:
| KW_REGISTER function_parameter
{
$$ = $2;
}
| ATTR_LEFT attribute_specifiers ATTR_RIGHT function_parameter
{
$$ = $4;
}
;

Expand Down Expand Up @@ -2246,16 +2262,16 @@ type:
{
$$ = CPPType::new_type($1);
}
| struct_keyword name
| struct_keyword struct_attributes name
{
CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
if (type != NULL) {
$$ = type;
} else {
CPPExtensionType *et =
CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
->as_extension_type();
CPPScope *scope = $2->get_scope(current_scope, global_scope);
CPPScope *scope = $3->get_scope(current_scope, global_scope);
if (scope != NULL) {
scope->define_extension_type(et);
}
Expand Down Expand Up @@ -2286,6 +2302,10 @@ type:
str << *$3;
yyerror("could not determine type of " + str.str(), @3);
}
}
| KW_DECLTYPE '(' KW_AUTO ')'
{
$$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto));
}
| KW_UNDERLYING_TYPE '(' full_type ')'
{
Expand Down Expand Up @@ -2343,16 +2363,16 @@ type_decl:
{
$$ = new CPPTypeDeclaration(CPPType::new_type($1));
}
| struct_keyword name
| struct_keyword struct_attributes name
{
CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
if (type != NULL) {
$$ = type;
} else {
CPPExtensionType *et =
CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
->as_extension_type();
CPPScope *scope = $2->get_scope(current_scope, global_scope);
CPPScope *scope = $3->get_scope(current_scope, global_scope);
if (scope != NULL) {
scope->define_extension_type(et);
}
Expand Down Expand Up @@ -2401,6 +2421,10 @@ type_decl:
str << *$3;
yyerror("could not determine type of " + str.str(), @3);
}
}
| KW_DECLTYPE '(' KW_AUTO ')'
{
$$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto));
}
| KW_UNDERLYING_TYPE '(' full_type ')'
{
Expand Down Expand Up @@ -2435,16 +2459,16 @@ predefined_type:
{
$$ = CPPType::new_type(new CPPTBDType($2));
}
| struct_keyword name
| struct_keyword struct_attributes name
{
CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
if (type != NULL) {
$$ = type;
} else {
CPPExtensionType *et =
CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
->as_extension_type();
CPPScope *scope = $2->get_scope(current_scope, global_scope);
CPPScope *scope = $3->get_scope(current_scope, global_scope);
if (scope != NULL) {
scope->define_extension_type(et);
}
Expand Down Expand Up @@ -2525,8 +2549,15 @@ full_type:
}
;

struct_attributes:
empty
| struct_attributes ATTR_LEFT attribute_specifiers ATTR_RIGHT
| struct_attributes KW_ALIGNAS '(' const_expr ')'
| struct_attributes KW_ALIGNAS '(' type_decl ')'
;

anonymous_struct:
struct_keyword '{'
struct_keyword struct_attributes '{'
{
CPPVisibility starting_vis =
($1 == CPPExtensionType::T_class) ? V_private : V_public;
Expand All @@ -2550,19 +2581,19 @@ anonymous_struct:
;

named_struct:
struct_keyword name_no_final
struct_keyword struct_attributes name_no_final
{
CPPVisibility starting_vis =
($1 == CPPExtensionType::T_class) ? V_private : V_public;

CPPScope *scope = $2->get_scope(current_scope, global_scope, current_lexer);
CPPScope *scope = $3->get_scope(current_scope, global_scope, current_lexer);
if (scope == NULL) {
scope = current_scope;
}
CPPScope *new_scope = new CPPScope(scope, $2->_names.back(),
CPPScope *new_scope = new CPPScope(scope, $3->_names.back(),
starting_vis);

CPPStructType *st = new CPPStructType($1, $2, current_scope,
CPPStructType *st = new CPPStructType($1, $3, current_scope,
new_scope, @1.file);
new_scope->set_struct_type(st);
current_scope->define_extension_type(st);
Expand Down Expand Up @@ -2945,6 +2976,7 @@ element:
| SCOPE | PLUSPLUS | MINUSMINUS
| TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
| OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
| ATTR_LEFT | ATTR_RIGHT
| KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_CATCH
| KW_CHAR | KW_CHAR16_T | KW_CHAR32_T | KW_CLASS | KW_CONST
| KW_CONSTEXPR | KW_CONST_CAST | KW_DECLTYPE | KW_DEFAULT
Expand Down Expand Up @@ -3028,6 +3060,18 @@ no_angle_bracket_const_expr:
| KW_SIZEOF '(' full_type ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
}
| KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
{
CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
if (arg == (CPPDeclaration *)NULL) {
yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
} else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
CPPInstance *inst = arg->as_instance();
$$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
} else {
$$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
}
}
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
{
Expand Down Expand Up @@ -3190,6 +3234,16 @@ const_expr:
}
assert(type != NULL);
$$ = new CPPExpression(CPPExpression::construct_op(type, $3));
}
| TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}'
{
// Aggregate initialization.
CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
if (type == NULL) {
yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
}
assert(type != NULL);
$$ = new CPPExpression(CPPExpression::aggregate_init_op(type, $3));
}
| KW_INT '(' optional_const_expr_comma ')'
{
Expand Down Expand Up @@ -3270,6 +3324,18 @@ const_expr:
| KW_SIZEOF '(' full_type ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
}
| KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
{
CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
if (arg == (CPPDeclaration *)NULL) {
yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
} else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
CPPInstance *inst = arg->as_instance();
$$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
} else {
$$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
}
}
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
{
Expand Down Expand Up @@ -3602,6 +3668,18 @@ formal_const_expr:
| KW_SIZEOF '(' full_type ')' %prec UNARY
{
$$ = new CPPExpression(CPPExpression::sizeof_func($3));
}
| KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
{
CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
if (arg == (CPPDeclaration *)NULL) {
yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
} else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
CPPInstance *inst = arg->as_instance();
$$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
} else {
$$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
}
}
| KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
{
Expand Down Expand Up @@ -3828,15 +3906,17 @@ capture_list:
{
$$ = new CPPClosureType(CPPClosureType::CT_by_reference);
}
| capture
| capture maybe_initialize
{
$$ = new CPPClosureType();
$1->_initializer = $2;
$$->_captures.push_back(*$1);
delete $1;
}
| capture_list ',' capture
| capture_list ',' capture maybe_initialize
{
$$ = $1;
$3->_initializer = $4;
$$->_captures.push_back(*$3);
delete $3;
}
Expand Down Expand Up @@ -3884,14 +3964,6 @@ class_derivation_name:
type = CPPType::new_type(new CPPTBDType($1));
}
$$ = type;
}
| struct_keyword name
{
CPPType *type = $2->find_type(current_scope, global_scope, true, current_lexer);
if (type == NULL) {
type = CPPType::new_type(new CPPTBDType($2));
}
$$ = type;
}
| KW_TYPENAME name
{
Expand Down
19 changes: 13 additions & 6 deletions dtool/src/cppparser/cppClosureType.cxx
Expand Up @@ -12,6 +12,7 @@
*/

#include "cppClosureType.h"
#include "cppExpression.h"

/**
*
Expand Down Expand Up @@ -47,7 +48,7 @@ operator = (const CPPClosureType &copy) {
* Adds a new capture to the beginning of the capture list.
*/
void CPPClosureType::
add_capture(string name, CaptureType type) {
add_capture(string name, CaptureType type, CPPExpression *initializer) {
if (type == CT_none) {
if (name == "this") {
type = CT_by_reference;
Expand All @@ -56,7 +57,7 @@ add_capture(string name, CaptureType type) {
}
}

Capture capture = {move(name), type};
Capture capture = {move(name), type, initializer};
_captures.insert(_captures.begin(), move(capture));
}

Expand Down Expand Up @@ -117,19 +118,25 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {

Captures::const_iterator it;
for (it = _captures.begin(); it != _captures.end(); ++it) {
const Capture &capture = *it;
if (have_capture) {
out << ", ";
}
if ((*it)._name == "this") {
if ((*it)._type == CT_by_value) {
if (capture._name == "this") {
if (capture._type == CT_by_value) {
out.put('*');
}
} else {
if ((*it)._type == CT_by_reference) {
if (capture._type == CT_by_reference) {
out.put('&');
}
}
out << (*it)._name;
out << capture._name;

if (capture._initializer != NULL) {
out << " = " << *capture._initializer;
}

have_capture = true;
}
out.put(']');
Expand Down
3 changes: 2 additions & 1 deletion dtool/src/cppparser/cppClosureType.h
Expand Up @@ -37,13 +37,14 @@ class CPPClosureType : public CPPFunctionType {
struct Capture {
string _name;
CaptureType _type;
CPPExpression *_initializer;
};
typedef vector<Capture> Captures;
Captures _captures;

CaptureType _default_capture;

void add_capture(string name, CaptureType type);
void add_capture(string name, CaptureType type, CPPExpression *initializer = NULL);

virtual bool is_fully_specified() const;

Expand Down

0 comments on commit e2771d3

Please sign in to comment.