Skip to content

Commit

Permalink
Allow additional contract flags, e.g., `assert<Bounds, audit, new_cod…
Browse files Browse the repository at this point in the history
…e>( ... )`
  • Loading branch information
hsutter committed Dec 17, 2023
1 parent 2893e64 commit c119d32
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 55 deletions.
24 changes: 20 additions & 4 deletions regression-tests/pure2-contracts.cpp2
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
test_condition_evaluation: (tag) -> bool = { std::cout << tag << "\n"; return true; }

audit: bool = true;

main: () = {
// A few basic tests
assert( 1 != 2, "ack, arithmetic is buggy" );
assert<Type>( typeid(int) != typeid(double), "ack, C types are broken" );
assert<Unevaluated>( any-grammatical.kind(of, nonsense * here) is "all ignored" );

assert( test_condition_evaluation(1), "default" ); // evaluated: prints "1"
assert<Type>( test_condition_evaluation(2), "type" ); // evaluated: prints "2"
// Now test that conditions are only evaluated if there's
// a handler active + any other control flags are enabled

assert( test_condition_evaluation(1), "default" ); // evaluated: prints "1"

// Type has a handler
assert<Type>( test_condition_evaluation(2), "type" ); // evaluated: prints "2"
cpp2::Type.set_handler();
assert<Type>( test_condition_evaluation(3), "type" ); // not evaluated
assert<Unevaluated>( test_condition_evaluation(4) ); // not evaluated
// Type does not have a handler
assert<Type>( test_condition_evaluation(3), "type" ); // not evaluated

// Bounds has a handler, and audit is true
assert<Bounds, audit>( test_condition_evaluation(4), "type" ); // evaluated: prints "4"
audit = false;
// Bounds has a handler, but audit is false
assert<Bounds, audit>( test_condition_evaluation(5), "type" ); // not evaluated

assert<Unevaluated>( test_condition_evaluation(6) ); // not evaluated
}
4 changes: 3 additions & 1 deletion regression-tests/pure2-print.cpp2
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

// Exercise the pretty-print visualizer for the various grammar elements

testing_enabled: bool = false;

outer: @print type = {

object_alias: <T> T requires true == 42;
Expand Down Expand Up @@ -30,7 +32,7 @@ outer: @print type = {

private h: (s: std::string, inout m: std::map<const int,std::string> ) -> std::string
pre( m.empty() == false || false, "message" )
pre<Bounds>( 0 < m.ssize() < 100 && true != false )
pre<Bounds, testing_enabled>( 0 < m.ssize() < 100 && true != false )
= {
a := :()={};
b := :()={};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
1
2
4
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
1
2
4
24 changes: 12 additions & 12 deletions regression-tests/test-results/gcc-10/pure2-print.cpp.output
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
In file included from pure2-print.cpp:7:
../../../include/cpp2util.h:10005:33: error: expected unqualified-id before ‘static_assert’
pure2-print.cpp2:7:1: note: in expansion of macro ‘CPP2_REQUIRES_’
pure2-print.cpp2:65:59: error: expected ‘;’ at end of member declaration
pure2-print.cpp2:9:1: note: in expansion of macro ‘CPP2_REQUIRES_’
pure2-print.cpp2:67:59: error: expected ‘;’ at end of member declaration
In file included from pure2-print.cpp:7:
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
pure2-print.cpp2:66:1: note: in expansion of macro ‘CPP2_REQUIRES_’
pure2-print.cpp2:68:1: note: in expansion of macro ‘CPP2_REQUIRES_’
../../../include/cpp2util.h:10005:33: error: expected initializer before ‘static_assert’
pure2-print.cpp2:94:1: note: in expansion of macro ‘CPP2_REQUIRES_’
pure2-print.cpp2:7:41: error: ‘constexpr const T outer::object_alias’ is not a static data member of ‘class outer’
pure2-print.cpp2:7:48: error: template definition of non-template ‘constexpr const T outer::object_alias’
pure2-print.cpp2:65:14: error: no declaration matches ‘void outer::mytype::variadic(const auto:90& ...) requires (is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(outer::mytype::variadic::x)>::type>::type, int> && ...)’
pure2-print.cpp2:65:29: note: candidate is: ‘template<class ... auto:89> static void outer::mytype::variadic(const auto:89& ...)’
pure2-print.cpp2:8:19: note: ‘class outer::mytype’ defined here
pure2-print.cpp2:93:37: error: no declaration matches ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’
pure2-print.cpp2:93:37: note: no functions named ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’
pure2-print.cpp2:4:7: note: ‘class outer’ defined here
pure2-print.cpp2:96:1: note: in expansion of macro ‘CPP2_REQUIRES_’
pure2-print.cpp2:9:41: error: ‘constexpr const T outer::object_alias’ is not a static data member of ‘class outer’
pure2-print.cpp2:9:48: error: template definition of non-template ‘constexpr const T outer::object_alias’
pure2-print.cpp2:67:14: error: no declaration matches ‘void outer::mytype::variadic(const auto:90& ...) requires (is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(outer::mytype::variadic::x)>::type>::type, int> && ...)’
pure2-print.cpp2:67:29: note: candidate is: ‘template<class ... auto:89> static void outer::mytype::variadic(const auto:89& ...)’
pure2-print.cpp2:10:19: note: ‘class outer::mytype’ defined here
pure2-print.cpp2:95:37: error: no declaration matches ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’
pure2-print.cpp2:95:37: note: no functions named ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’
pure2-print.cpp2:6:7: note: ‘class outer’ defined here
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
1
2
4
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
1
2
4
22 changes: 20 additions & 2 deletions regression-tests/test-results/pure2-contracts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
[[nodiscard]] auto test_condition_evaluation(auto const& tag) -> bool;

#line 3 "pure2-contracts.cpp2"
extern bool audit;

auto main() -> int;

//=== Cpp2 function definitions =================================================
Expand All @@ -23,15 +25,31 @@ auto main() -> int;
[[nodiscard]] auto test_condition_evaluation(auto const& tag) -> bool{std::cout << tag << "\n"; return true; }

#line 3 "pure2-contracts.cpp2"
bool audit {true};

auto main() -> int{
// A few basic tests
if (cpp2::Default.has_handler() && !(1 != 2) ) { cpp2::Default.violation("ack, arithmetic is buggy"); }
if (cpp2::Type.has_handler() && !(typeid(int) != typeid(double)) ) { cpp2::Type.violation("ack, C types are broken"); }

#line 8 "pure2-contracts.cpp2"
#line 11 "pure2-contracts.cpp2"
// Now test that conditions are only evaluated if there's
// a handler active + any other control flags are enabled

if (cpp2::Default.has_handler() && !(test_condition_evaluation(1)) ) { cpp2::Default.violation("default"); }// evaluated: prints "1"

// Type has a handler
if (cpp2::Type.has_handler() && !(test_condition_evaluation(2)) ) { cpp2::Type.violation("type"); }// evaluated: prints "2"
CPP2_UFCS(set_handler)(cpp2::Type);
// Type does not have a handler
if (cpp2::Type.has_handler() && !(test_condition_evaluation(3)) ) { cpp2::Type.violation("type"); }// not evaluated
// not evaluated

// Bounds has a handler, and audit is true
if (cpp2::Bounds.has_handler() && audit && !(test_condition_evaluation(4)) ) { cpp2::Bounds.violation("type"); }// evaluated: prints "4"
audit = false;
// Bounds has a handler, but audit is false
if (cpp2::Bounds.has_handler() && audit && !(test_condition_evaluation(5)) ) { cpp2::Bounds.violation("type"); }// not evaluated

// not evaluated
}

53 changes: 29 additions & 24 deletions regression-tests/test-results/pure2-print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#line 1 "pure2-print.cpp2"

#line 4 "pure2-print.cpp2"
#line 6 "pure2-print.cpp2"
class outer;


Expand All @@ -19,9 +19,11 @@ class outer;
// Exercise the pretty-print visualizer for the various grammar elements

#line 4 "pure2-print.cpp2"
extern bool testing_enabled;

class outer {

#line 6 "pure2-print.cpp2"
#line 8 "pure2-print.cpp2"
public: template<typename T>
CPP2_REQUIRES_ (true) static const T object_alias;
public: class mytype final
Expand All @@ -30,16 +32,16 @@ CPP2_REQUIRES_ (true) static const T object_alias;

public: [[nodiscard]] virtual auto g(cpp2::in<int> i) const -> int;

#line 31 "pure2-print.cpp2"
#line 33 "pure2-print.cpp2"
private: [[nodiscard]] static auto h(cpp2::in<std::string> s, std::map<int const,std::string>& m) -> std::string;
struct values_ret { int offset; std::string name; };



#line 54 "pure2-print.cpp2"
#line 56 "pure2-print.cpp2"
public: template<typename T> [[nodiscard]] auto values([[maybe_unused]] T const& unnamed_param_2) const& -> values_ret;

#line 59 "pure2-print.cpp2"
#line 61 "pure2-print.cpp2"
public: explicit mytype();

public: mytype([[maybe_unused]] mytype const& that);
Expand All @@ -48,32 +50,32 @@ struct values_ret { int offset; std::string name; };

public: static auto variadic(auto const& ...x) -> void
CPP2_REQUIRES_ ((std::is_convertible_v<CPP2_TYPEOF(x), int> && ...)) ;
#line 66 "pure2-print.cpp2"
#line 68 "pure2-print.cpp2"
};

public: static auto test() -> void;

#line 89 "pure2-print.cpp2"
#line 91 "pure2-print.cpp2"
public: template<typename ...Ts> class x {
private: std::tuple<Ts...> tup {};
public: x() = default;
public: x(x const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(x const&) -> void = delete;

#line 91 "pure2-print.cpp2"
#line 93 "pure2-print.cpp2"
};

public: template<typename ...Args> static auto print(std::ostream& out, Args const& ...args) -> void
CPP2_REQUIRES_ (cpp2::cmp_greater_eq(sizeof(Args)...,0)) ;

#line 97 "pure2-print.cpp2"
#line 99 "pure2-print.cpp2"
public: template<typename ...Args> [[nodiscard]] static auto all(Args const& ...args) -> bool;
public: outer() = default;
public: outer(outer const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(outer const&) -> void = delete;


#line 100 "pure2-print.cpp2"
#line 102 "pure2-print.cpp2"
};

auto main() -> int;
Expand All @@ -82,12 +84,15 @@ auto main() -> int;

#line 1 "pure2-print.cpp2"

#line 6 "pure2-print.cpp2"
#line 4 "pure2-print.cpp2"
bool testing_enabled {false};

#line 8 "pure2-print.cpp2"
template<typename T>
requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42;
#line 7 "pure2-print.cpp2"
#line 9 "pure2-print.cpp2"

#line 10 "pure2-print.cpp2"
#line 12 "pure2-print.cpp2"
[[nodiscard]] auto outer::mytype::f() -> int { return 42; }

[[nodiscard]] auto outer::mytype::g(cpp2::in<int> i) const -> int{
Expand All @@ -111,11 +116,11 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42;

[[nodiscard]] auto outer::mytype::h(cpp2::in<std::string> s, std::map<int const,std::string>& m) -> std::string

#line 34 "pure2-print.cpp2"
#line 36 "pure2-print.cpp2"
{
if (cpp2::Default.has_handler() && !(CPP2_UFCS(empty)(m) == false || false) ) { cpp2::Default.violation("message"); }
if (cpp2::Bounds.has_handler() && !([_0 = 0, _1 = CPP2_UFCS(ssize)(m), _2 = 100]{ return cpp2::cmp_less(_0,_1) && cpp2::cmp_less(_1,_2); }() && true != false) ) { cpp2::Bounds.violation(""); }
#line 35 "pure2-print.cpp2"
if (cpp2::Bounds.has_handler() && testing_enabled && !([_0 = 0, _1 = CPP2_UFCS(ssize)(m), _2 = 100]{ return cpp2::cmp_less(_0,_1) && cpp2::cmp_less(_1,_2); }() && true != false) ) { cpp2::Bounds.violation(""); }
#line 37 "pure2-print.cpp2"
auto a {[]() mutable -> void{}};
auto b {[]() mutable -> void{}};
auto c {[]() mutable -> void{}};
Expand All @@ -124,9 +129,9 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42;

do {} while ( [&]{ b() ; return true; }() && CPP2_UFCS(empty)(s));

for ( [[maybe_unused]] auto const& unnamed_param_1 : m ) { { do {goto CONTINUE_43_13; } while (false); c(); } CPP2_CONTINUE_BREAK(43_13) }
for ( [[maybe_unused]] auto const& unnamed_param_1 : m ) { { do {goto CONTINUE_45_13; } while (false); c(); } CPP2_CONTINUE_BREAK(45_13) }

#line 45 "pure2-print.cpp2"
#line 47 "pure2-print.cpp2"
if (cpp2::is(!(CPP2_UFCS(empty)(s)), (true))) {std::move(a)(); }
else {if (!(CPP2_UFCS(empty)(m))) {std::move(b)(); }
else {std::move(c)(); }}
Expand All @@ -139,7 +144,7 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42;
template<typename T> [[nodiscard]] auto outer::mytype::values([[maybe_unused]] T const& unnamed_param_2) const& -> values_ret{
cpp2::deferred_init<int> offset;
cpp2::deferred_init<std::string> name;
#line 55 "pure2-print.cpp2"
#line 57 "pure2-print.cpp2"
offset.construct(53);
name.construct("plugh");
return { std::move(offset.value()), std::move(name.value()) }; }
Expand All @@ -153,7 +158,7 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42;
auto outer::mytype::variadic(auto const& ...x) -> void
requires ((std::is_convertible_v<CPP2_TYPEOF(x), int> && ...)) {(std::cout << ... << x); }

#line 68 "pure2-print.cpp2"
#line 70 "pure2-print.cpp2"
auto outer::test() -> void{
namespace namespace_alias = ::std;

Expand All @@ -165,7 +170,7 @@ requires ((std::is_convertible_v<CPP2_TYPEOF(x), int> && ...)) {(std::cout << ..
cpp2::i8 constexpr object_alias_1 = 42;
auto constexpr object_alias_2 = 42;

#line 80 "pure2-print.cpp2"
#line 82 "pure2-print.cpp2"
::outer::mytype var {};
cout << CPP2_UFCS(g)(var, 42) << "\n";

Expand All @@ -175,17 +180,17 @@ requires ((std::is_convertible_v<CPP2_TYPEOF(x), int> && ...)) {(std::cout << ..
() << "\n";
}

#line 93 "pure2-print.cpp2"
#line 95 "pure2-print.cpp2"
template<typename ...Args> auto outer::print(std::ostream& out, Args const& ...args) -> void
requires (cpp2::cmp_greater_eq(sizeof(Args)...,0)) {
#line 94 "pure2-print.cpp2"
#line 96 "pure2-print.cpp2"
(out << ... << args);
}

template<typename ...Args> [[nodiscard]] auto outer::all(Args const& ...args) -> bool {
return (... && args); }

#line 102 "pure2-print.cpp2"
#line 104 "pure2-print.cpp2"
auto main() -> int{
outer::test();
}
Expand Down
2 changes: 1 addition & 1 deletion regression-tests/test-results/pure2-print.cpp2.output
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ outer: type =
inout m: std::map<const int, std::string>
) -> move std::string
pre( m.empty() == false || false, "message" )
pre<Bounds>( 0 < m.ssize() < 100 && true != false ) =
pre<Bounds,testing_enabled>( 0 < m.ssize() < 100 && true != false ) =
{
a: = :() =
{
Expand Down
2 changes: 1 addition & 1 deletion regression-tests/test-results/version
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

cppfront compiler v0.3.0 Build 8C17:0658
cppfront compiler v0.3.0 Build 8C17:1133
Copyright(c) Herb Sutter All rights reserved

SPDX-License-Identifier: CC-BY-NC-ND-4.0
Expand Down
2 changes: 1 addition & 1 deletion source/build.info
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"8C17:0658"
"8C17:1133"
Loading

0 comments on commit c119d32

Please sign in to comment.