Skip to content

feat: add _type-id_ production for decltype #921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion regression-tests/mixed-bugfix-for-ufcs-non-local.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ d: _ == t<o.f()>(); // Fails on Clang 12 (lambda in unevaluated context).

u: @struct type = {
b: bool == o.f();
c: bool == :(x: std::type_identity_t<decltype(o.f())>) x;(true); // Fails on Clang 12 (lambda in unevaluated context).
c: bool == :(x: decltype(o.f())) x;(true); // Fails on Clang 12 (lambda in unevaluated context).
g: (s, sz) pre(s.sz() != 0) = { }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

v: <T> concept = :() -> bool = true;();

u: type == std::type_identity_t<decltype(:() = {})>;
u: type == decltype(:() = {});

t: @struct type = {
this: std::type_identity_t<decltype(:() = {})>;
this: decltype(:() = {});
}

main: () = { }
1 change: 1 addition & 0 deletions regression-tests/pure2-deduction-1-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
f: () -> decltype(auto) = 0;
1 change: 1 addition & 0 deletions regression-tests/pure2-deduction-2-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x: decltype(auto) = 0;
2 changes: 1 addition & 1 deletion regression-tests/pure2-last-use.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ issue_313: () = {
_ = e is (e);

f := new<int>(0);
_ = f is std::type_identity_t<decltype(f)>; // OK?
_ = f is decltype(f); // OK?

g := new<int>(0);
for (identity(g)* + identity(g)*)
Expand Down
2 changes: 2 additions & 0 deletions regression-tests/pure2-print.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ outer: @print type = {
all: <Args...: type> (args...: Args) -> bool =
(... && args);

y: (_: decltype(0)) = { }

}

main: () = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ mixed-bugfix-for-ufcs-non-local.cpp2:27:29: error: a lambda expression cannot ap
../../../include/cpp2util.h:2099:66: note: expanded from macro 'CPP2_UFCS_'
#define CPP2_UFCS_(LAMBDADEFCAPT,SFINAE,MVFWD,QUALID,TEMPKW,...) \
^
mixed-bugfix-for-ufcs-non-local.cpp2:41:84: error: lambda expression in an unevaluated operand
inline CPP2_CONSTEXPR bool u::c{ [](cpp2::impl::in<std::type_identity_t<decltype(CPP2_UFCS_NONLOCAL(f)(o))>> x) -> auto { return x; }(true) };// Fails on Clang 12 (lambda in unevaluated context).
^
mixed-bugfix-for-ufcs-non-local.cpp2:41:63: error: lambda expression in an unevaluated operand
inline CPP2_CONSTEXPR bool u::c{ [](cpp2::impl::in<decltype(CPP2_UFCS_NONLOCAL(f)(o))> x) -> auto { return x; }(true) };// Fails on Clang 12 (lambda in unevaluated context).
^
../../../include/cpp2util.h:2137:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL'
#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,CPP2_UFCS_IDENTITY,CPP2_UFCS_IDENTITY,(),,__VA_ARGS__)
^
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
pure2-bugfix-for-non-local-function-expression.cpp2:5:34: error: lambda expression in an unevaluated operand
template<typename T> concept v = []() -> bool { return true; }();
^
pure2-bugfix-for-non-local-function-expression.cpp2:7:41: error: lambda expression in an unevaluated operand
using u = std::type_identity_t<decltype([]() -> void{})>;
^
pure2-bugfix-for-non-local-function-expression.cpp2:9:47: error: lambda expression in an unevaluated operand
class t: public std::type_identity_t<decltype([]() -> void{})> {
^
pure2-bugfix-for-non-local-function-expression.cpp2:7:20: error: lambda expression in an unevaluated operand
using u = decltype([]() -> void{});
^
pure2-bugfix-for-non-local-function-expression.cpp2:9:26: error: lambda expression in an unevaluated operand
class t: public decltype([]() -> void{}) {
^
3 errors generated.
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ auto g() -> void{

#line 40 "mixed-bugfix-for-ufcs-non-local.cpp2"
inline CPP2_CONSTEXPR bool u::b{ CPP2_UFCS_NONLOCAL(f)(o) };
inline CPP2_CONSTEXPR bool u::c{ [](cpp2::impl::in<std::type_identity_t<decltype(CPP2_UFCS_NONLOCAL(f)(o))>> x) -> auto { return x; }(true) };// Fails on Clang 12 (lambda in unevaluated context).
inline CPP2_CONSTEXPR bool u::c{ [](cpp2::impl::in<decltype(CPP2_UFCS_NONLOCAL(f)(o))> x) -> auto { return x; }(true) };// Fails on Clang 12 (lambda in unevaluated context).
auto u::g(auto const& s, auto const& sz) -> void{
if (cpp2::cpp2_default.is_active() && !(CPP2_UFCS(sz)(s) != 0) ) { cpp2::cpp2_default.report_violation(""); }}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class t;
#line 5 "pure2-bugfix-for-non-local-function-expression.cpp2"
template<typename T> concept v = []() -> bool { return true; }();

using u = std::type_identity_t<decltype([]() -> void{})>;
using u = decltype([]() -> void{});

class t: public std::type_identity_t<decltype([]() -> void{})> {
class t: public decltype([]() -> void{}) {

};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-deduction-1-error.cpp2...
pure2-deduction-1-error.cpp2(1,10): error: decltype(auto) is not needed in Cpp2 - for return types, use '-> forward _' instead

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pure2-deduction-2-error.cpp2...
pure2-deduction-2-error.cpp2(1,4): error: decltype(auto) is not needed in Cpp2 - for return types, use '-> forward _' instead

2 changes: 1 addition & 1 deletion regression-tests/test-results/pure2-last-use.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ auto issue_313() -> void{
static_cast<void>(cpp2::impl::is(e, (e)));

auto f {cpp2_new<int>(0)};
static_cast<void>(cpp2::impl::is<std::type_identity_t<decltype(f)>>(f));// OK?
static_cast<void>(cpp2::impl::is<decltype(f)>(f));// OK?

auto g {cpp2_new<int>(0)};
for (
Expand Down
10 changes: 8 additions & 2 deletions regression-tests/test-results/pure2-print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,15 @@ CPP2_REQUIRES_ (cpp2::impl::cmp_greater_eq(sizeof...(Args),0u)) ;

#line 100 "pure2-print.cpp2"
public: template<typename ...Args> [[nodiscard]] static auto all(Args const& ...args) -> bool;

#line 103 "pure2-print.cpp2"
public: static auto y([[maybe_unused]] cpp2::impl::in<decltype(0)> unnamed_param_1) -> void;
public: outer() = default;
public: outer(outer const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(outer const&) -> void = delete;


#line 103 "pure2-print.cpp2"
#line 105 "pure2-print.cpp2"
};

auto main() -> int;
Expand Down Expand Up @@ -199,7 +202,10 @@ requires (cpp2::impl::cmp_greater_eq(sizeof...(Args),0u)) {
template<typename ...Args> [[nodiscard]] auto outer::all(Args const& ...args) -> bool {
return (... && args); }

#line 105 "pure2-print.cpp2"
#line 103 "pure2-print.cpp2"
auto outer::y([[maybe_unused]] cpp2::impl::in<decltype(0)> unnamed_param_1) -> void{}

#line 107 "pure2-print.cpp2"
auto main() -> int{
outer::test();
}
Expand Down
4 changes: 4 additions & 0 deletions regression-tests/test-results/pure2-print.cpp2.output
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ outer:/* @print */ type =
}

all: <Args...: type, >(in args...: Args, ) -> move bool = (... && args);

y:(in _: decltype(0), ) =
{
}
}
ok (all Cpp2, passes safety checks)

47 changes: 45 additions & 2 deletions source/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -1365,9 +1365,10 @@ struct type_id_node
int dereference_cnt = {};
token const* suspicious_initialization = {};

enum active : u8 { empty=0, qualified, unqualified, function, keyword };
enum active : u8 { empty=0, decltype_, qualified, unqualified, function, keyword };
std::variant<
std::monostate,
std::unique_ptr<postfix_expression_node>,
std::unique_ptr<qualified_id_node>,
std::unique_ptr<unqualified_id_node>,
std::unique_ptr<function_type_node>,
Expand Down Expand Up @@ -1419,6 +1420,9 @@ struct type_id_node
if (id.index() == unqualified) {
return std::get<unqualified>(id)->template_arguments();
}
else if (id.index() != qualified) {
cpp2_default.report_violation("ICE: this type_id has no template arguments");
}
// else
return std::get<qualified>(id)->template_arguments();
}
Expand All @@ -1432,6 +1436,8 @@ struct type_id_node
switch (id.index()) {
break;case empty:
return {};
break;case decltype_:
return {};
break;case qualified:
return {};
break;case unqualified:
Expand Down Expand Up @@ -1460,6 +1466,7 @@ struct type_id_node
for (auto q : pc_qualifiers) {
v.start(*q, depth+1);
}
try_visit<decltype_ >(id, v, depth);
try_visit<qualified >(id, v, depth);
try_visit<unqualified>(id, v, depth);
try_visit<function >(id, v, depth);
Expand Down Expand Up @@ -2770,6 +2777,8 @@ auto type_id_node::to_string() const
switch (id.index()) {
break;case empty:
ret += "_";
break;case decltype_:
ret += std::get<decltype_>(id)->to_string();
break;case qualified:
ret += std::get<qualified>(id)->to_string();
break;case unqualified:
Expand Down Expand Up @@ -5084,6 +5093,7 @@ auto pretty_print_visualize(type_id_node const& n, int indent)
}

if (n.id.index() == type_id_node::empty) { ret += "_"; }
ret += try_pretty_print_visualize<type_id_node::decltype_ >(n.id, indent);
ret += try_pretty_print_visualize<type_id_node::qualified >(n.id, indent);
ret += try_pretty_print_visualize<type_id_node::unqualified>(n.id, indent);
ret += try_pretty_print_visualize<type_id_node::function >(n.id, indent);
Expand Down Expand Up @@ -6867,6 +6877,7 @@ class parser


//G type-id:
//G type-qualifier-seq? 'decltype' '(' expression ')' is-type-constraint?
//G type-qualifier-seq? qualified-id is-type-constraint?
//G type-qualifier-seq? unqualified-id is-type-constraint?
//G type-qualifier-seq? function-type is-type-constraint?
Expand Down Expand Up @@ -6909,7 +6920,39 @@ class parser
next();
}

if (auto id = qualified_id()) {
if (auto& c = curr();
c == "decltype"
)
{
if (
peek(1) && peek(1)->type() == lexeme::LeftParen
&& peek(2) && *peek(2) == "auto"
&& peek(3) && peek(3)->type() == lexeme::RightParen)
{
error(
"decltype(auto) is not needed in Cpp2 - for return types, use '-> forward _' instead",
false,
c.position()
);
}
if (auto id = postfix_expression();
id
&& id->ops.size() == 1
&& id->ops[0].expr_list->expressions.size() == 1
&& id->ops[0].expr_list->open_paren->type() == lexeme::LeftParen
)
{
n->pos = id->position();
n->id = std::move(id);
assert (n->id.index() == type_id_node::decltype_);
}
else
{
error("'decltype' must be followed by a single parenthesized expression", false, c.position());
return {};
}
}
else if (auto id = qualified_id()) {
n->pos = id->position();
n->id = std::move(id);
assert (n->id.index() == type_id_node::qualified);
Expand Down
1 change: 1 addition & 0 deletions source/to_cpp1.h
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,7 @@ class cppfront
printer.print_cpp2("auto", pos);
}
else {
try_emit<type_id_node::decltype_ >(n.id);
try_emit<type_id_node::unqualified>(n.id, 0, false);
try_emit<type_id_node::qualified >(n.id);
try_emit<type_id_node::keyword >(n.id);
Expand Down
Loading