From f10444ecb9a6063c944235a57c5f1bd520b953be Mon Sep 17 00:00:00 2001 From: Herb Sutter <herb.sutter@gmail.com> Date: Wed, 8 Nov 2023 07:18:00 -1000 Subject: [PATCH] Require `;` after assert statement It's just consistent. And update the grammar. --- .../mixed-bounds-safety-with-assert-2.cpp2 | 4 +-- .../mixed-bounds-safety-with-assert.cpp2 | 4 +-- .../mixed-bugfix-for-literal-as-nttp.cpp2 | 6 ++--- ...re2-bugfix-for-assign-expression-list.cpp2 | 6 ++--- ...2-bugfix-for-non-local-initialization.cpp2 | 4 +-- .../pure2-concept-definition.cpp2 | 4 +-- regression-tests/pure2-print.cpp2 | 2 +- source/parse.h | 25 ++++++++----------- source/reflect.h | 2 +- source/reflect.h2 | 18 ++++++------- 10 files changed, 36 insertions(+), 39 deletions(-) diff --git a/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 b/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 index 054cfb7e49..4b6c11d0cf 100644 --- a/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 +++ b/regression-tests/mixed-bounds-safety-with-assert-2.cpp2 @@ -9,8 +9,8 @@ main: () -> int = { add_42_to_subrange: (inout rng:_, start:int, end:int) = { - assert<Bounds>( 0 <= start ) - assert<Bounds>( end <= rng.ssize() ) + assert<Bounds>( 0 <= start ); + assert<Bounds>( end <= rng.ssize() ); count := 0; for rng diff --git a/regression-tests/mixed-bounds-safety-with-assert.cpp2 b/regression-tests/mixed-bounds-safety-with-assert.cpp2 index d4245c6bab..dc9fba07cc 100644 --- a/regression-tests/mixed-bounds-safety-with-assert.cpp2 +++ b/regression-tests/mixed-bounds-safety-with-assert.cpp2 @@ -7,8 +7,8 @@ main: () -> int = { } print_subrange: (rng:_, start:int, end:int) = { - assert<Bounds>( 0 <= start ) - assert<Bounds>( end <= rng.ssize() ) + assert<Bounds>( 0 <= start ); + assert<Bounds>( end <= rng.ssize() ); count := 0; for rng diff --git a/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 b/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 index 2600a3a668..932218b968 100644 --- a/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 +++ b/regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2 @@ -1,7 +1,7 @@ #include <chrono> using namespace std::chrono_literals; main: () = { - assert( 10 as i32 == 10 ) - assert( 10LL as i32 == 10 ) - assert( 10s as std::chrono::seconds == 10s ) + assert( 10 as i32 == 10 ); + assert( 10LL as i32 == 10 ); + assert( 10s as std::chrono::seconds == 10s ); } diff --git a/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 b/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 index b7eb84a0d6..5341a7e608 100644 --- a/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 +++ b/regression-tests/pure2-bugfix-for-assign-expression-list.cpp2 @@ -2,9 +2,9 @@ main: () = { vec: type == std::vector<int>; v: vec = (0); v = (); - assert( v == :vec = () ) + assert( v == :vec = () ); v = (1); - assert( v == :vec = (1) ) + assert( v == :vec = (1) ); v = (2, 3); - assert( v == :vec = (2, 3) ) + assert( v == :vec = (2, 3) ); } diff --git a/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 b/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 index 3079f017c5..faa06039ea 100644 --- a/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 +++ b/regression-tests/pure2-bugfix-for-non-local-initialization.cpp2 @@ -3,6 +3,6 @@ t: @struct type = { this: std::integral_constant<u, :u = (17, 29)>; } main: () = { - assert<Testing>( t::value[0] == 17 ) - assert<Testing>( t::value[1] == 29 ) + assert<Testing>( t::value[0] == 17 ); + assert<Testing>( t::value[1] == 29 ); } diff --git a/regression-tests/pure2-concept-definition.cpp2 b/regression-tests/pure2-concept-definition.cpp2 index 6a5c52c380..7b9cffb369 100644 --- a/regression-tests/pure2-concept-definition.cpp2 +++ b/regression-tests/pure2-concept-definition.cpp2 @@ -1,5 +1,5 @@ arithmetic: <T> concept = std::integral<T> || std::floating_point<T>; main: () = { - assert<Testing>( arithmetic<i32> ) - assert<Testing>( arithmetic<float> ) + assert<Testing>( arithmetic<i32> ); + assert<Testing>( arithmetic<float> ); } diff --git a/regression-tests/pure2-print.cpp2 b/regression-tests/pure2-print.cpp2 index 9791701e23..038fd328f5 100644 --- a/regression-tests/pure2-print.cpp2 +++ b/regression-tests/pure2-print.cpp2 @@ -46,7 +46,7 @@ outer: @print type = { else if !m.empty() { b(); } else { c(); } - assert( true ) + assert( true ); return :() -> std::string = (s + m[0])$; (); } diff --git a/source/parse.h b/source/parse.h index 9a8537ce2b..1215f15593 100644 --- a/source/parse.h +++ b/source/parse.h @@ -7001,9 +7001,12 @@ class parser //G jump-statement //G iteration-statement //G compound-statement - //G contract + //G contract-statement //G declaration //G expression-statement + //G + //G contract-statement + //G contract ';' // //GTODO try-block //G @@ -7089,6 +7092,11 @@ class parser error("only 'assert' contracts are allowed at statement scope"); return {}; } + if (curr().type() != lexeme::Semicolon) { + error("missing ';' after contract-statement"); + return {}; + } + next(); n->statement = std::move(s); assert (n->is_contract()); return n; @@ -7467,8 +7475,8 @@ class parser //G contract: - //G contract-kind contract-group? ':' logical-or-expression ']' ']' - //G contract-kind contract-group? ':' logical-or-expression ',' string-literal ']' ']' + //G contract-kind contract-group? ':' '(' logical-or-expression ')' + //G contract-kind contract-group? ':' '(' logical-or-expression ',' string-literal ')' //G //G contract-group: //G '<' id-expression '>' @@ -7540,17 +7548,6 @@ class parser } next(); - // Allow optional ';' after an assert, which is really an empty - // statement (I'm not putting it in the grammar) and so this is - // to skip the "empty statement" check and error - if ( - *n->kind == "assert" - && curr().type() == lexeme::Semicolon - ) - { - next(); - } - return n; } diff --git a/source/reflect.h b/source/reflect.h index 59cc45b5c0..2d14523226 100644 --- a/source/reflect.h +++ b/source/reflect.h @@ -156,7 +156,7 @@ type_id: @polymorphic_base @copyable type = = { compiler_services = s; n = n_; - assert( n, "a meta::type_id must point to a valid type_id_node, not null" ) + assert( n, "a meta::type_id must point to a valid type_id_node, not null" ); } is_wildcard : (this) -> bool = n.is_wildcard(); diff --git a/source/reflect.h2 b/source/reflect.h2 index 370f77fb17..f3f926e4fb 100644 --- a/source/reflect.h2 +++ b/source/reflect.h2 @@ -107,7 +107,7 @@ compiler_services: @polymorphic_base @copyable type = tokens := generated_lexers.back()&; tokens*.lex( lines*, true ); - assert( std::ssize(tokens* .get_map()) == 1 ) + assert( std::ssize(tokens* .get_map()) == 1 ); // Now parse this single declaration from // the lexed tokens @@ -168,7 +168,7 @@ type_id: @polymorphic_base @copyable type = = { compiler_services = s; n = n_; - assert( n, "a meta::type_id must point to a valid type_id_node, not null" ) + assert( n, "a meta::type_id must point to a valid type_id_node, not null" ); } is_wildcard : (this) -> bool = n*.is_wildcard(); @@ -204,7 +204,7 @@ declaration_base: @polymorphic_base @copyable type = = { compiler_services = s; n = n_; - assert( n, "a meta::declaration must point to a valid declaration_node, not null" ) + assert( n, "a meta::declaration must point to a valid declaration_node, not null" ); } position: (override this) -> source_position = n*.position(); @@ -285,7 +285,7 @@ declaration: @polymorphic_base @copyable type = pre<Type>( parent_is_type() ) // this precondition should be sufficient ... = { test := n*.type_member_mark_for_removal(); - assert( test ) // ... to ensure this assert is true + assert( test ); // ... to ensure this assert is true } } @@ -304,7 +304,7 @@ function_declaration: @copyable type = ) = { declaration = (n_, s); - assert( n*.is_function() ) + assert( n*.is_function() ); } index_of_parameter_named : (this, s: std::string_view) -> int = n*.index_of_parameter_named(s); @@ -361,7 +361,7 @@ object_declaration: @copyable type = ) = { declaration = (n_, s); - assert( n*.is_object() ) + assert( n*.is_object() ); } is_const : (this) -> bool = n*.is_const(); @@ -397,7 +397,7 @@ type_declaration: @copyable type = ) = { declaration = (n_, s); - assert( n*.is_type() ) + assert( n*.is_type() ); } reserve_names: (this, name: std::string_view, forward etc...) = @@ -510,7 +510,7 @@ alias_declaration: @copyable type = ) = { declaration = (n_, s); - assert( n*.is_alias() ) + assert( n*.is_alias() ); } } @@ -1239,7 +1239,7 @@ apply_metafunctions: ( ) -> bool = { - assert( n.is_type() ) + assert( n.is_type() ); // Check for _names reserved for the metafunction implementation for rtype.get_members()