From 3dfda75d7163bd4c553488a76f33536a001dfa35 Mon Sep 17 00:00:00 2001 From: guwirth Date: Wed, 28 Aug 2024 14:26:03 +0200 Subject: [PATCH] C++23 if consteval - [if consteval](https://en.cppreference.com/w/cpp/language/if#Consteval_if) [P1938R3](https://wg21.link/P1938R3) - linked #2536 --- cxx-squid/dox/diff-cpp20-cpp23_grammar.txt | 7 ---- .../org/sonar/cxx/parser/CxxGrammarImpl.java | 4 +- .../org/sonar/cxx/parser/StatementTest.java | 10 ++++- .../parser/own/C++23/if-consteval.cc | 40 +++++++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 cxx-squid/src/test/resources/parser/own/C++23/if-consteval.cc diff --git a/cxx-squid/dox/diff-cpp20-cpp23_grammar.txt b/cxx-squid/dox/diff-cpp20-cpp23_grammar.txt index 6cb8e1bf02..641ecc13bf 100644 --- a/cxx-squid/dox/diff-cpp20-cpp23_grammar.txt +++ b/cxx-squid/dox/diff-cpp20-cpp23_grammar.txt @@ -204,13 +204,6 @@ label-seq: label label-seq label -selection-statement: - if constexpropt ( init-statementopt condition ) statement - if constexpropt ( init-statementopt condition ) statement else statement - if !opt consteval compound-statement - if !opt consteval compound-statement else statement - switch ( init-statementopt condition ) statement - **A.7 Declarations [gram.dcl]** declaration: diff --git a/cxx-squid/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java b/cxx-squid/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java index ab2ea45f0a..04622b1c9c 100644 --- a/cxx-squid/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java +++ b/cxx-squid/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java @@ -969,7 +969,9 @@ private static void statements(LexerfulGrammarBuilder b) { b.firstOf( b.sequence(CxxKeyword.IF, b.optional(CxxKeyword.CONSTEXPR), "(", b.optional(initStatement), condition, ")", statement, b.optional(CxxKeyword.ELSE, statement)), // C++ - b.sequence(CxxKeyword.SWITCH, "(", b.optional(initStatement), condition, ")", statement) + b.sequence(CxxKeyword.IF, b.optional("!"), CxxKeyword.CONSTEVAL, + compoundStatement, b.optional(CxxKeyword.ELSE, statement)), // C++23 + b.sequence(CxxKeyword.SWITCH, "(", b.optional(initStatement), condition, ")", statement) // C++ ) ); diff --git a/cxx-squid/src/test/java/org/sonar/cxx/parser/StatementTest.java b/cxx-squid/src/test/java/org/sonar/cxx/parser/StatementTest.java index 9e0f0284d8..a4194c8251 100644 --- a/cxx-squid/src/test/java/org/sonar/cxx/parser/StatementTest.java +++ b/cxx-squid/src/test/java/org/sonar/cxx/parser/StatementTest.java @@ -90,7 +90,10 @@ void selectionStatement_reallife() { // fix #2286 .matches("if(a() < 0 || c >= 1) {}") .matches("if(a() < 0 || c > 1) {}") - .matches("if(a() < 0 || c >> 1) {}"); + .matches("if(a() < 0 || c >> 1) {}") + // C++23 + .matches("if !consteval {}") + .matches("if !consteval {} else ;"); } @Test @@ -131,6 +134,7 @@ void selectionStatement() { mockRule(CxxGrammarImpl.statement); mockRule(CxxGrammarImpl.condition); mockRule(CxxGrammarImpl.initStatement); + mockRule(CxxGrammarImpl.compoundStatement); assertThatParser() .matches("if ( condition ) statement") @@ -141,6 +145,10 @@ void selectionStatement() { .matches("if constexpr ( condition ) statement else statement") .matches("if ( initStatement condition ) statement else statement") .matches("if constexpr ( initStatement condition ) statement else statement") + .matches("if consteval compoundStatement") + .matches("if ! consteval compoundStatement") + .matches("if consteval compoundStatement else statement") + .matches("if ! consteval compoundStatement else statement") .matches("switch ( condition ) statement") .matches("switch ( initStatement condition ) statement"); } diff --git a/cxx-squid/src/test/resources/parser/own/C++23/if-consteval.cc b/cxx-squid/src/test/resources/parser/own/C++23/if-consteval.cc new file mode 100644 index 0000000000..f5bf815a15 --- /dev/null +++ b/cxx-squid/src/test/resources/parser/own/C++23/if-consteval.cc @@ -0,0 +1,40 @@ +constexpr bool is_constant_evaluated() noexcept +{ + if consteval { return true; } else { return false; } +} + +constexpr bool is_runtime_evaluated() noexcept +{ + if !consteval { return true; } else { return false; } +} + +consteval std::uint64_t ipow_ct(std::uint64_t base, std::uint8_t exp) +{ + if (!base) return base; + std::uint64_t res{1}; + while (exp) + { + if (exp & 1) res *= base; + exp /= 2; + base *= base; + } + return res; +} + +constexpr std::uint64_t ipow(std::uint64_t base, std::uint8_t exp) +{ + if consteval // use a compile-time friendly algorithm + { + return ipow_ct(base, exp); + } + else // use runtime evaluation + { + return std::pow(base, exp); + } +} + +int main(int, const char* argv[]) +{ + static_assert(ipow(0, 10) == 0 && ipow(2, 10) == 1024); + std::cout << ipow(std::strlen(argv[0]), 3) << '\n'; +}