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..113c46233f 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(