From 855c47d1e55cd983204ea7476e484c93993d0d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Fri, 2 Jun 2023 23:19:49 -0400 Subject: [PATCH 1/3] fix(cpp1): contract check invalid alternative --- ...ugfix-for-runtime-invalid-alternative.cpp2 | 7 +++++ .../test-results/mixed-inspect-templates.cpp | 8 ++--- .../test-results/mixed-inspect-values-2.cpp | 4 +-- .../test-results/mixed-inspect-values.cpp | 12 +++---- ...spect-with-typeof-of-template-arg-list.cpp | 2 +- ...bugfix-for-runtime-invalid-alternative.cpp | 31 +++++++++++++++++++ ...or-runtime-invalid-alternative.cpp2.output | 2 ++ ...ion-in-generic-function-multiple-types.cpp | 4 +-- ...expression-with-as-in-generic-function.cpp | 2 +- ...ect-fallback-with-variant-any-optional.cpp | 8 ++--- ...c-void-empty-with-variant-any-optional.cpp | 2 +- ...-type-safety-2-with-inspect-expression.cpp | 2 +- source/cppfront.cpp | 6 ++-- 13 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 regression-tests/pure2-bugfix-for-runtime-invalid-alternative.cpp2 create mode 100644 regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp create mode 100644 regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp2.output diff --git a/regression-tests/pure2-bugfix-for-runtime-invalid-alternative.cpp2 b/regression-tests/pure2-bugfix-for-runtime-invalid-alternative.cpp2 new file mode 100644 index 0000000000..6c57e7723f --- /dev/null +++ b/regression-tests/pure2-bugfix-for-runtime-invalid-alternative.cpp2 @@ -0,0 +1,7 @@ +f: (x) = { + [[assert: inspect x -> i32 { + is 1 = :() -> bool = 2;(""); + is _ = 1; + } == 1]] +} +main: () = f(1); diff --git a/regression-tests/test-results/mixed-inspect-templates.cpp b/regression-tests/test-results/mixed-inspect-templates.cpp index 9d0b42766a..e32ab92cf1 100644 --- a/regression-tests/test-results/mixed-inspect-templates.cpp +++ b/regression-tests/test-results/mixed-inspect-templates.cpp @@ -33,10 +33,10 @@ struct my_type {}; #line 8 "mixed-inspect-templates.cpp2" [[nodiscard]] auto fun(auto const& v) -> std::string{ return [&] () -> std::string { auto&& __expr = v; - if (cpp2::is(__expr)) { if constexpr( requires{"std::vector";} ) if constexpr( std::is_convertible_v ) return "std::vector"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr)) { if constexpr( requires{"std::array";} ) if constexpr( std::is_convertible_v ) return "std::array"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr)) { if constexpr( requires{"std::variant";} ) if constexpr( std::is_convertible_v ) return "std::variant"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr)) { if constexpr( requires{"my_type";} ) if constexpr( std::is_convertible_v ) return "my_type"; else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr)) { if constexpr( requires{"std::vector";} ) if constexpr( std::is_convertible_v ) return "std::vector"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr)) { if constexpr( requires{"std::array";} ) if constexpr( std::is_convertible_v ) return "std::array"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr)) { if constexpr( requires{"std::variant";} ) if constexpr( std::is_convertible_v ) return "std::variant"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr)) { if constexpr( requires{"my_type";} ) if constexpr( std::is_convertible_v ) return "my_type"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return "unknown"; } (); } diff --git a/regression-tests/test-results/mixed-inspect-values-2.cpp b/regression-tests/test-results/mixed-inspect-values-2.cpp index 4b2cde6324..c9f8ac5b5d 100644 --- a/regression-tests/test-results/mixed-inspect-values-2.cpp +++ b/regression-tests/test-results/mixed-inspect-values-2.cpp @@ -39,8 +39,8 @@ constexpr auto empty = [](auto&& x){ auto i {15}; std::cout << [&] () -> std::string { auto&& __expr = i; - if (cpp2::is(__expr, (less_than(10)))) { if constexpr( requires{"i less than 10";} ) if constexpr( std::is_convertible_v ) return "i less than 10"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr, in(11, 20))) { if constexpr( requires{"i is between 11 and 20";} ) if constexpr( std::is_convertible_v ) return "i is between 11 and 20"; else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr, (less_than(10)))) { if constexpr( requires{"i less than 10";} ) if constexpr( std::is_convertible_v ) return "i less than 10"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr, in(11, 20))) { if constexpr( requires{"i is between 11 and 20";} ) if constexpr( std::is_convertible_v ) return "i is between 11 and 20"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return "i is out of our interest"; } () << std::endl; diff --git a/regression-tests/test-results/mixed-inspect-values.cpp b/regression-tests/test-results/mixed-inspect-values.cpp index d4e0430e76..8587b5f774 100644 --- a/regression-tests/test-results/mixed-inspect-values.cpp +++ b/regression-tests/test-results/mixed-inspect-values.cpp @@ -56,12 +56,12 @@ auto test(auto const& x) -> void; auto test(auto const& x) -> void{ auto forty_two {42}; std::cout << [&] () -> std::string { auto&& __expr = x; - if (cpp2::is(__expr, 0)) { if constexpr( requires{"zero";} ) if constexpr( std::is_convertible_v ) return "zero"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr, (in(1, 2)))) { if constexpr( requires{"1 or 2";} ) if constexpr( std::is_convertible_v ) return "1 or 2"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr, in_2_3)) { if constexpr( requires{"3";} ) if constexpr( std::is_convertible_v ) return "3"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr, std::move(forty_two))) { if constexpr( requires{"the answer";} ) if constexpr( std::is_convertible_v ) return "the answer"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr)) { if constexpr( requires{"integer " + cpp2::to_string(x);} ) if constexpr( std::is_convertible_v ) return "integer " + cpp2::to_string(x); else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr)) { if constexpr( requires{cpp2::as(x);} ) if constexpr( std::is_convertible_v(x))),std::string> ) return cpp2::as(x); else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr, 0)) { if constexpr( requires{"zero";} ) if constexpr( std::is_convertible_v ) return "zero"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr, (in(1, 2)))) { if constexpr( requires{"1 or 2";} ) if constexpr( std::is_convertible_v ) return "1 or 2"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr, in_2_3)) { if constexpr( requires{"3";} ) if constexpr( std::is_convertible_v ) return "3"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr, std::move(forty_two))) { if constexpr( requires{"the answer";} ) if constexpr( std::is_convertible_v ) return "the answer"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr)) { if constexpr( requires{"integer " + cpp2::to_string(x);} ) if constexpr( std::is_convertible_v ) return "integer " + cpp2::to_string(x); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr)) { if constexpr( requires{cpp2::as(x);} ) if constexpr( std::is_convertible_v(x))),std::string> ) return cpp2::as(x); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return "(no match)"; } () << "\n"; } diff --git a/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp b/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp index 9698ad3b5c..ccd25b1e82 100644 --- a/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp +++ b/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp @@ -29,7 +29,7 @@ auto calc() { #line 7 "mixed-inspect-with-typeof-of-template-arg-list.cpp2" [[nodiscard]] auto fun(auto const& v) -> int{ return [&] () -> int { auto&& __expr = v; - if (cpp2::is(__expr)) { if constexpr( requires{calc<1,2>();} ) if constexpr( std::is_convertible_v())),int> ) return calc<1,2>(); else return int{}; else return int{}; } + if (cpp2::is(__expr)) { if constexpr( requires{calc<1,2>();} ) if constexpr( std::is_convertible_v())),int> ) return calc<1,2>(); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return 0; } (); } diff --git a/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp b/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp new file mode 100644 index 0000000000..e76ac5f2dd --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp @@ -0,0 +1,31 @@ + +#define CPP2_USE_MODULES Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-runtime-invalid-alternative.cpp2" +auto f(auto const& x) -> void; + + +#line 7 "pure2-bugfix-for-runtime-invalid-alternative.cpp2" +auto main() -> int; + + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-runtime-invalid-alternative.cpp2" +auto f(auto const& x) -> void{ + cpp2::Default.expects([&] () -> cpp2::i32 { auto&& __expr = x; + if (cpp2::is(__expr, 1)) { if constexpr( requires{[]() -> bool { return 2; }("");} ) if constexpr( std::is_convertible_v bool { return 2; }(""))),cpp2::i32> ) return []() -> bool { return 2; }(""); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else return 1; } + ()==1, ""); +} +auto main() -> int { f(1); } + diff --git a/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp2.output new file mode 100644 index 0000000000..fef18713a7 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-runtime-invalid-alternative.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp b/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp index 9fe635a1a6..1c5ff2f9ef 100644 --- a/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp +++ b/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp @@ -45,8 +45,8 @@ auto test_generic(auto const& x, auto const& msg) -> void{ << std::setw(30) << msg << " value is " << [&] () -> std::string { auto&& __expr = x; - if (cpp2::is(__expr)) { if constexpr( requires{"integer " + std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return "integer " + std::to_string(cpp2::as(x)); else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr)) { if constexpr( requires{'"' + cpp2::as(x) + '"';} ) if constexpr( std::is_convertible_v(x) + '"')),std::string> ) return '"' + cpp2::as(x) + '"'; else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr)) { if constexpr( requires{"integer " + std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return "integer " + std::to_string(cpp2::as(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr)) { if constexpr( requires{'"' + cpp2::as(x) + '"';} ) if constexpr( std::is_convertible_v(x) + '"')),std::string> ) return '"' + cpp2::as(x) + '"'; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return "not an int or string"; } () << "\n"; diff --git a/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp b/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp index 422360f099..9eec76c0bd 100644 --- a/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp +++ b/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp @@ -32,7 +32,7 @@ auto print_an_int(auto const& x) -> void{ << std::setw(30) << cpp2::to_string(x) << " value is " << [&] () -> std::string { auto&& __expr = x; - if (cpp2::is(__expr)) { if constexpr( requires{std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return std::to_string(cpp2::as(x)); else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr)) { if constexpr( requires{std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return std::to_string(cpp2::as(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return "not an int"; } () << "\n"; diff --git a/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp b/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp index 7d7662bdcd..57f188d628 100644 --- a/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp +++ b/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp @@ -39,10 +39,10 @@ auto test_generic(auto const& x, auto const& msg) -> void{ std::cout << "\n" << msg << "\n ..." << [&] () -> std::string { auto&& __expr = x; - if (cpp2::is(__expr)) { if constexpr( requires{" matches std::string";} ) if constexpr( std::is_convertible_v ) return " matches std::string"; else return std::string{}; else return std::string{}; } - else if (cpp2::is>(__expr)) { if constexpr( requires{" matches std::variant";} ) if constexpr( std::is_convertible_v")),std::string> ) return " matches std::variant"; else return std::string{}; else return std::string{}; } - else if (cpp2::is(__expr)) { if constexpr( requires{" matches std::any";} ) if constexpr( std::is_convertible_v ) return " matches std::any"; else return std::string{}; else return std::string{}; } - else if (cpp2::is>(__expr)) { if constexpr( requires{" matches std::optional";} ) if constexpr( std::is_convertible_v")),std::string> ) return " matches std::optional"; else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr)) { if constexpr( requires{" matches std::string";} ) if constexpr( std::is_convertible_v ) return " matches std::string"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is>(__expr)) { if constexpr( requires{" matches std::variant";} ) if constexpr( std::is_convertible_v")),std::string> ) return " matches std::variant"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is(__expr)) { if constexpr( requires{" matches std::any";} ) if constexpr( std::is_convertible_v ) return " matches std::any"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } + else if (cpp2::is>(__expr)) { if constexpr( requires{" matches std::optional";} ) if constexpr( std::is_convertible_v")),std::string> ) return " matches std::optional"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return " no match"; } () << "\n"; diff --git a/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp b/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp index 24cb1df600..ca00669cc2 100644 --- a/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp +++ b/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp @@ -43,7 +43,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{ std::cout << "\n" << msg << "\n ..." << [&] () -> std::string { auto&& __expr = x; - if (cpp2::is(__expr)) { if constexpr( requires{" VOYDE AND EMPTIE";} ) if constexpr( std::is_convertible_v ) return " VOYDE AND EMPTIE"; else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr)) { if constexpr( requires{" VOYDE AND EMPTIE";} ) if constexpr( std::is_convertible_v ) return " VOYDE AND EMPTIE"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return " no match"; } () << "\n"; diff --git a/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp b/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp index 4f4c83f3e8..8962164341 100644 --- a/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp +++ b/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp @@ -45,7 +45,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{ << std::setw(30) << msg << " value is " << [&] () -> std::string { auto&& __expr = x; - if (cpp2::is(__expr)) { if constexpr( requires{std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return std::to_string(cpp2::as(x)); else return std::string{}; else return std::string{}; } + if (cpp2::is(__expr)) { if constexpr( requires{std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return std::to_string(cpp2::as(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else return "not an int"; } () << "\n"; diff --git a/source/cppfront.cpp b/source/cppfront.cpp index 382dfe122d..b1fde99ab7 100644 --- a/source/cppfront.cpp +++ b/source/cppfront.cpp @@ -1991,8 +1991,10 @@ class cppfront ) { assert(alt->statement->is_expression()); - printer.print_cpp2("; else return " + result_type + "{}", alt->position()); - printer.print_cpp2("; else return " + result_type + "{}", alt->position()); + printer.print_cpp2( + "; cpp2::Type.expects(false, \"Statement of chosen alternative is invalid.\")", + alt->position() + ); } printer.print_cpp2(return_suffix, alt->position()); From 1880055609334fafffbaf7d672a554f28bfd765c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Mon, 5 Jun 2023 22:33:47 -0400 Subject: [PATCH 2/3] refactor(cpp1): emit without else to silence warning --- regression-tests/test-results/mixed-inspect-templates.cpp | 2 +- regression-tests/test-results/mixed-inspect-values-2.cpp | 2 +- regression-tests/test-results/mixed-inspect-values.cpp | 2 +- .../mixed-inspect-with-typeof-of-template-arg-list.cpp | 2 +- .../pure2-bugfix-for-runtime-invalid-alternative.cpp | 2 +- ...pect-expression-in-generic-function-multiple-types.cpp | 2 +- ...re2-inspect-expression-with-as-in-generic-function.cpp | 2 +- .../pure2-inspect-fallback-with-variant-any-optional.cpp | 2 +- ...spect-generic-void-empty-with-variant-any-optional.cpp | 2 +- .../pure2-type-safety-2-with-inspect-expression.cpp | 2 +- source/cppfront.cpp | 8 ++++---- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/regression-tests/test-results/mixed-inspect-templates.cpp b/regression-tests/test-results/mixed-inspect-templates.cpp index e32ab92cf1..9e3f481934 100644 --- a/regression-tests/test-results/mixed-inspect-templates.cpp +++ b/regression-tests/test-results/mixed-inspect-templates.cpp @@ -37,7 +37,7 @@ struct my_type {}; else if (cpp2::is(__expr)) { if constexpr( requires{"std::array";} ) if constexpr( std::is_convertible_v ) return "std::array"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is(__expr)) { if constexpr( requires{"std::variant";} ) if constexpr( std::is_convertible_v ) return "std::variant"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is(__expr)) { if constexpr( requires{"my_type";} ) if constexpr( std::is_convertible_v ) return "my_type"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return "unknown"; } + return "unknown"; } (); } diff --git a/regression-tests/test-results/mixed-inspect-values-2.cpp b/regression-tests/test-results/mixed-inspect-values-2.cpp index c9f8ac5b5d..80ea46435a 100644 --- a/regression-tests/test-results/mixed-inspect-values-2.cpp +++ b/regression-tests/test-results/mixed-inspect-values-2.cpp @@ -41,7 +41,7 @@ constexpr auto empty = [](auto&& x){ std::cout << [&] () -> std::string { auto&& __expr = i; if (cpp2::is(__expr, (less_than(10)))) { if constexpr( requires{"i less than 10";} ) if constexpr( std::is_convertible_v ) return "i less than 10"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is(__expr, in(11, 20))) { if constexpr( requires{"i is between 11 and 20";} ) if constexpr( std::is_convertible_v ) return "i is between 11 and 20"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return "i is out of our interest"; } + return "i is out of our interest"; } () << std::endl; if (cpp2::is(i, (less_than(20)))) { diff --git a/regression-tests/test-results/mixed-inspect-values.cpp b/regression-tests/test-results/mixed-inspect-values.cpp index 8587b5f774..587780e865 100644 --- a/regression-tests/test-results/mixed-inspect-values.cpp +++ b/regression-tests/test-results/mixed-inspect-values.cpp @@ -62,7 +62,7 @@ auto test(auto const& x) -> void{ else if (cpp2::is(__expr, std::move(forty_two))) { if constexpr( requires{"the answer";} ) if constexpr( std::is_convertible_v ) return "the answer"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is(__expr)) { if constexpr( requires{"integer " + cpp2::to_string(x);} ) if constexpr( std::is_convertible_v ) return "integer " + cpp2::to_string(x); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is(__expr)) { if constexpr( requires{cpp2::as(x);} ) if constexpr( std::is_convertible_v(x))),std::string> ) return cpp2::as(x); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return "(no match)"; } + return "(no match)"; } () << "\n"; } diff --git a/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp b/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp index ccd25b1e82..29fbb27a93 100644 --- a/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp +++ b/regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp @@ -30,7 +30,7 @@ auto calc() { [[nodiscard]] auto fun(auto const& v) -> int{ return [&] () -> int { auto&& __expr = v; if (cpp2::is(__expr)) { if constexpr( requires{calc<1,2>();} ) if constexpr( std::is_convertible_v())),int> ) return calc<1,2>(); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return 0; } + return 0; } (); } diff --git a/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp b/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp index e76ac5f2dd..0ae68b9e62 100644 --- a/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp +++ b/regression-tests/test-results/pure2-bugfix-for-runtime-invalid-alternative.cpp @@ -24,7 +24,7 @@ auto main() -> int; auto f(auto const& x) -> void{ cpp2::Default.expects([&] () -> cpp2::i32 { auto&& __expr = x; if (cpp2::is(__expr, 1)) { if constexpr( requires{[]() -> bool { return 2; }("");} ) if constexpr( std::is_convertible_v bool { return 2; }(""))),cpp2::i32> ) return []() -> bool { return 2; }(""); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return 1; } + return 1; } ()==1, ""); } auto main() -> int { f(1); } diff --git a/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp b/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp index 1c5ff2f9ef..a07c4c0a24 100644 --- a/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp +++ b/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp @@ -47,7 +47,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{ << [&] () -> std::string { auto&& __expr = x; if (cpp2::is(__expr)) { if constexpr( requires{"integer " + std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return "integer " + std::to_string(cpp2::as(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is(__expr)) { if constexpr( requires{'"' + cpp2::as(x) + '"';} ) if constexpr( std::is_convertible_v(x) + '"')),std::string> ) return '"' + cpp2::as(x) + '"'; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return "not an int or string"; } + return "not an int or string"; } () << "\n"; } diff --git a/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp b/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp index 9eec76c0bd..56d7931f11 100644 --- a/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp +++ b/regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp @@ -33,7 +33,7 @@ auto print_an_int(auto const& x) -> void{ << " value is " << [&] () -> std::string { auto&& __expr = x; if (cpp2::is(__expr)) { if constexpr( requires{std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return std::to_string(cpp2::as(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return "not an int"; } + return "not an int"; } () << "\n"; } diff --git a/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp b/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp index 57f188d628..697af7f875 100644 --- a/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp +++ b/regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp @@ -43,7 +43,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{ else if (cpp2::is>(__expr)) { if constexpr( requires{" matches std::variant";} ) if constexpr( std::is_convertible_v")),std::string> ) return " matches std::variant"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is(__expr)) { if constexpr( requires{" matches std::any";} ) if constexpr( std::is_convertible_v ) return " matches std::any"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } else if (cpp2::is>(__expr)) { if constexpr( requires{" matches std::optional";} ) if constexpr( std::is_convertible_v")),std::string> ) return " matches std::optional"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return " no match"; } + return " no match"; } () << "\n"; } diff --git a/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp b/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp index ca00669cc2..b16391bd60 100644 --- a/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp +++ b/regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp @@ -44,7 +44,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{ << "\n" << msg << "\n ..." << [&] () -> std::string { auto&& __expr = x; if (cpp2::is(__expr)) { if constexpr( requires{" VOYDE AND EMPTIE";} ) if constexpr( std::is_convertible_v ) return " VOYDE AND EMPTIE"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return " no match"; } + return " no match"; } () << "\n"; } diff --git a/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp b/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp index 8962164341..c6557feed9 100644 --- a/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp +++ b/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp @@ -46,7 +46,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{ << " value is " << [&] () -> std::string { auto&& __expr = x; if (cpp2::is(__expr)) { if constexpr( requires{std::to_string(cpp2::as(x));} ) if constexpr( std::is_convertible_v(x)))),std::string> ) return std::to_string(cpp2::as(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); } - else return "not an int"; } + return "not an int"; } () << "\n"; } diff --git a/source/cppfront.cpp b/source/cppfront.cpp index b1fde99ab7..d3a228c122 100644 --- a/source/cppfront.cpp +++ b/source/cppfront.cpp @@ -1911,10 +1911,6 @@ class cppfront for (auto first = true; auto&& alt : n.alternatives) { assert(alt && alt->is_as_keyword); - if (!first) { - printer.print_cpp2("else ", alt->position()); - } - first = false; auto id = std::string{}; printer.emit_to_string(&id); @@ -1972,6 +1968,10 @@ class cppfront } } else { + if (!first) { + printer.print_cpp2("else ", alt->position()); + } + first = false; printer.print_cpp2("if " + constexpr_qualifier, alt->position()); if (alt->type_id) { printer.print_cpp2("(cpp2::is<" + id + ">(__expr)) ", alt->position()); From 095edee3a72da8be0158d20ac3b4a352e1e5b1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Tue, 6 Jun 2023 00:27:50 -0400 Subject: [PATCH 3/3] test: add `test-results/gcc-13` --- regression-tests/test-results/gcc-13/gcc-version.output | 5 +++++ ...ure2-bugfix-for-runtime-invalid-alternative.cpp.execution | 2 ++ .../pure2-bugfix-for-runtime-invalid-alternative.cpp.output | 0 3 files changed, 7 insertions(+) create mode 100644 regression-tests/test-results/gcc-13/gcc-version.output create mode 100644 regression-tests/test-results/gcc-13/pure2-bugfix-for-runtime-invalid-alternative.cpp.execution create mode 100644 regression-tests/test-results/gcc-13/pure2-bugfix-for-runtime-invalid-alternative.cpp.output diff --git a/regression-tests/test-results/gcc-13/gcc-version.output b/regression-tests/test-results/gcc-13/gcc-version.output new file mode 100644 index 0000000000..7bbac4c854 --- /dev/null +++ b/regression-tests/test-results/gcc-13/gcc-version.output @@ -0,0 +1,5 @@ +c++ (GCC) 13.1.1 20230429 +Copyright (C) 2023 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-runtime-invalid-alternative.cpp.execution b/regression-tests/test-results/gcc-13/pure2-bugfix-for-runtime-invalid-alternative.cpp.execution new file mode 100644 index 0000000000..e121c2cc81 --- /dev/null +++ b/regression-tests/test-results/gcc-13/pure2-bugfix-for-runtime-invalid-alternative.cpp.execution @@ -0,0 +1,2 @@ +Type safety violation: Statement of chosen alternative is invalid. +terminate called without an active exception diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-runtime-invalid-alternative.cpp.output b/regression-tests/test-results/gcc-13/pure2-bugfix-for-runtime-invalid-alternative.cpp.output new file mode 100644 index 0000000000..e69de29bb2