From e93d5dce4b50ac862dd8c24965b38a417c6126e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Wed, 21 Jun 2023 18:23:04 -0400 Subject: [PATCH 1/3] fix(parse): recognize const and pointer template arguments --- .../pure2-bugfix-for-template-argument.cpp2 | 3 ++ ...bugfix-for-template-argument.cpp.execution | 0 ...e2-bugfix-for-template-argument.cpp.output | 0 .../pure2-bugfix-for-template-argument.cpp | 23 ++++++++ ...2-bugfix-for-template-argument.cpp2.output | 2 + source/parse.h | 53 +++++++++++-------- 6 files changed, 60 insertions(+), 21 deletions(-) create mode 100644 regression-tests/pure2-bugfix-for-template-argument.cpp2 create mode 100644 regression-tests/test-results/gcc-13/pure2-bugfix-for-template-argument.cpp.execution create mode 100644 regression-tests/test-results/gcc-13/pure2-bugfix-for-template-argument.cpp.output create mode 100644 regression-tests/test-results/pure2-bugfix-for-template-argument.cpp create mode 100644 regression-tests/test-results/pure2-bugfix-for-template-argument.cpp2.output diff --git a/regression-tests/pure2-bugfix-for-template-argument.cpp2 b/regression-tests/pure2-bugfix-for-template-argument.cpp2 new file mode 100644 index 0000000000..823e64137a --- /dev/null +++ b/regression-tests/pure2-bugfix-for-template-argument.cpp2 @@ -0,0 +1,3 @@ +main: () = // + std::is_void_v<* i32> // + && std::is_void_v; diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-template-argument.cpp.execution b/regression-tests/test-results/gcc-13/pure2-bugfix-for-template-argument.cpp.execution new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-template-argument.cpp.output b/regression-tests/test-results/gcc-13/pure2-bugfix-for-template-argument.cpp.output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/pure2-bugfix-for-template-argument.cpp b/regression-tests/test-results/pure2-bugfix-for-template-argument.cpp new file mode 100644 index 0000000000..e0218aa238 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-template-argument.cpp @@ -0,0 +1,23 @@ + +#define CPP2_USE_MODULES Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-template-argument.cpp2" +auto main() -> int; + + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-template-argument.cpp2" +auto main() -> int { // + std::is_void_v // + && std::is_void_v; } + diff --git a/regression-tests/test-results/pure2-bugfix-for-template-argument.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-template-argument.cpp2.output new file mode 100644 index 0000000000..f25ea8720b --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-template-argument.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-template-argument.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/source/parse.h b/source/parse.h index 2fbf60396a..830e5fdc56 100644 --- a/source/parse.h +++ b/source/parse.h @@ -721,7 +721,7 @@ struct postfix_expression_node if (ops.empty()) { return false; } else { - return (ops.front().op->type() == lexeme::Ampersand + return (ops.front().op->type() == lexeme::Ampersand || ops.front().op->type() == lexeme::Tilde); } } @@ -3965,7 +3965,7 @@ class parser // || curr().type() == lexeme::LeftBrace ) { - bool inside_initializer = ( + bool inside_initializer = ( peek(-1) && peek(-1)->type() == lexeme::Assignment ); auto open_paren = &curr(); @@ -3987,12 +3987,12 @@ class parser next(); if ( curr().type() != lexeme::Semicolon - && curr().type() != lexeme::RightParen - && curr().type() != lexeme::RightBracket + && curr().type() != lexeme::RightParen + && curr().type() != lexeme::RightBracket && curr().type() != lexeme::Comma ) { expr_list->inside_initializer = false; - } + } n->expr = std::move(expr_list); return n; } @@ -4350,7 +4350,7 @@ class parser //G shift-expression '<<' additive-expression //G shift-expression '>>' additive-expression //G - auto shift_expression(bool allow_angle_operators = true) + auto shift_expression(bool allow_angle_operators = true) -> auto { if (allow_angle_operators) { @@ -4385,7 +4385,7 @@ class parser //G shift-expression //G compare-expression '<=>' shift-expression //G - auto compare_expression(bool allow_angle_operators = true) + auto compare_expression(bool allow_angle_operators = true) -> auto { return binary_expression ( @@ -4401,7 +4401,7 @@ class parser //G relational-expression '<=' compare-expression //G relational-expression '>=' compare-expression //G - auto relational_expression(bool allow_angle_operators = true) + auto relational_expression(bool allow_angle_operators = true) -> auto { if (allow_angle_operators) { @@ -4433,7 +4433,7 @@ class parser //G equality-expression '==' relational-expression //G equality-expression '!=' relational-expression //G - auto equality_expression(bool allow_angle_operators = true) + auto equality_expression(bool allow_angle_operators = true) -> auto { return binary_expression ( @@ -4446,7 +4446,7 @@ class parser //G equality-expression //G bit-and-expression '&' equality-expression //G - auto bit_and_expression(bool allow_angle_operators = true) + auto bit_and_expression(bool allow_angle_operators = true) -> auto { return binary_expression ( @@ -4459,7 +4459,7 @@ class parser //G bit-and-expression //G bit-xor-expression '^' bit-and-expression //G - auto bit_xor_expression(bool allow_angle_operators = true) + auto bit_xor_expression(bool allow_angle_operators = true) -> auto { return binary_expression ( @@ -4472,7 +4472,7 @@ class parser //G bit-xor-expression //G bit-or-expression '|' bit-xor-expression //G - auto bit_or_expression(bool allow_angle_operators = true) + auto bit_or_expression(bool allow_angle_operators = true) -> auto { return binary_expression ( @@ -4485,7 +4485,7 @@ class parser //G bit-or-expression //G logical-and-expression '&&' bit-or-expression //G - auto logical_and_expression(bool allow_angle_operators = true) + auto logical_and_expression(bool allow_angle_operators = true) -> auto { return binary_expression ( @@ -4500,7 +4500,7 @@ class parser //G logical-and-expression //G logical-or-expression '||' logical-and-expression //G - auto logical_or_expression(bool allow_angle_operators = true) + auto logical_or_expression(bool allow_angle_operators = true) -> auto { return binary_expression ( @@ -4789,6 +4789,7 @@ class parser //G //G template-argument: //G # note: < > << >> are not allowed in expressions until new ( is opened + //G 'const' type-id //G expression //G type-id //G @@ -4818,12 +4819,22 @@ class parser n->open_angle = curr().position(); next(); - + auto term = unqualified_id_node::term{}; do { - // disallow unparenthesized relational comparisons in template args - if (auto e = expression(false)) { + if (auto e = [&]() { + // If the template-argument can only be a type id + // skip the expression production, because it start with + if ( + curr().type() == lexeme::Multiply // '*' + || curr() == "const" // 'const' + ) { + return decltype(expression()){}; + } + // disallow unparenthesized relational comparisons in template args + return expression(false); + }()) { term.arg = std::move(e); } else if (auto i = type_id()) { @@ -6389,7 +6400,7 @@ class parser } assert (n->is_type()); } - + // Or a function type, declaring a function - and tell the function whether it's in a user-defined type else if (auto t = function_type(n.get(), named)) { @@ -6537,11 +6548,11 @@ class parser ) { auto& type = std::get(n->type); - // object initialized by the address of the curr() object + // object initialized by the address of the curr() object if (peek(1)->type() == lexeme::Ampersand) { type->address_of = &curr(); } - // object initialized by (potentially multiple) dereference of the curr() object + // object initialized by (potentially multiple) dereference of the curr() object else if (peek(1)->type() == lexeme::Multiply) { type->dereference_of = &curr(); for (int i = 1; peek(i)->type() == lexeme::Multiply; ++i) @@ -6746,7 +6757,7 @@ class parser return {}; } if ( - t->is_wildcard() + t->is_wildcard() || ( t->get_token() && t->get_token()->to_string(true) == "auto" ) ) { errors.emplace_back( From 6a2351e121e96bb3aea81d5c5af785cdb9cc5798 Mon Sep 17 00:00:00 2001 From: Herb Sutter Date: Thu, 10 Aug 2023 21:21:54 -0700 Subject: [PATCH 2/3] Minor: Massage the new code's format and comment Signed-off-by: Herb Sutter --- source/parse.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/source/parse.h b/source/parse.h index 830e5fdc56..a1dba7d191 100644 --- a/source/parse.h +++ b/source/parse.h @@ -4823,18 +4823,20 @@ class parser auto term = unqualified_id_node::term{}; do { - if (auto e = [&]() { - // If the template-argument can only be a type id - // skip the expression production, because it start with - if ( - curr().type() == lexeme::Multiply // '*' - || curr() == "const" // 'const' - ) { - return decltype(expression()){}; - } - // disallow unparenthesized relational comparisons in template args - return expression(false); - }()) { + if ( + auto e = [&]() { + // If the template-argument starts with * or const, it can only be + // a type id, so skip the expression production + if ( + curr().type() == lexeme::Multiply // '*' + || curr() == "const" // 'const' + ) { + return decltype(expression()){}; + } + return expression(false); // false == disallow unparenthesized relational comparisons in template args + }() + ) + { term.arg = std::move(e); } else if (auto i = type_id()) { From 8fcef3f9b4d3ed4c5a57426630ffc99f4fb4fca8 Mon Sep 17 00:00:00 2001 From: Herb Sutter Date: Thu, 10 Aug 2023 21:30:32 -0700 Subject: [PATCH 3/3] Update parse.h Signed-off-by: Herb Sutter --- source/parse.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/source/parse.h b/source/parse.h index a1dba7d191..62a348feed 100644 --- a/source/parse.h +++ b/source/parse.h @@ -4823,14 +4823,14 @@ class parser auto term = unqualified_id_node::term{}; do { - if ( - auto e = [&]() { - // If the template-argument starts with * or const, it can only be - // a type id, so skip the expression production + // If it doesn't start with * or const (which can only be a type id), + // try parsing it as an expression + if (auto e = [&]{ if ( - curr().type() == lexeme::Multiply // '*' - || curr() == "const" // 'const' - ) { + curr().type() == lexeme::Multiply // '*' + || curr() == "const" // 'const' + ) + { return decltype(expression()){}; } return expression(false); // false == disallow unparenthesized relational comparisons in template args @@ -4839,12 +4839,16 @@ class parser { term.arg = std::move(e); } + + // Else try parsing it as a type id else if (auto i = type_id()) { term.arg = std::move(i); } + else { break; } + n->template_args.push_back( std::move(term) ); } // Use the lambda trick to jam in a "next" clause