Skip to content

Commit

Permalink
Add C++20 constexpr and consteval macros (#5048)
Browse files Browse the repository at this point in the history
  • Loading branch information
MungoG authored and GitHub Enterprise committed Oct 30, 2024
1 parent d08e955 commit e84a9dd
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 5 deletions.
24 changes: 24 additions & 0 deletions groups/bsl/bsls/bsls_compilerfeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ BSLS_IDENT("$Id: $")
// BSLS_COMPILERFEATURES_SUPPORT_ATTRIBUTE_NODISCARD: `[[nodiscard]]`
// BSLS_COMPILERFEATURES_SUPPORT_ATTRIBUTE_NORETURN: `[[noreturn]]` attribute
// BSLS_COMPILERFEATURES_SUPPORT_CONCEPTS: C++20 core language concepts
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20: `consteval` specifier
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR: `constexpr` specifier
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP14: C++14 `constexpr` spec.
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP17: C++17 `constexpr` spec.
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20: C++20 'constexpr' spec.
// BSLS_COMPILERFEATURES_SUPPORT_COROUTINE: core & lib C++20 coroutine support
// BSLS_COMPILERFEATURES_SUPPORT_CTAD: flag for template argument deduction
// BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE: flag for `decltype`
Expand Down Expand Up @@ -228,6 +230,10 @@ BSLS_IDENT("$Id: $")
// > supported by the current compiler settings for this platform, as
// > defined by ISO C++20.
//
// * `BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20`
// > This macro is defined if `consteval`, as defined by ISO C++20, is
// > supported by the current compiler settings for this platform.
//
// * `BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR`
// > This macro is defined if `constexpr` is supported by the current
// > compiler settings for this platform.
Expand All @@ -244,6 +250,11 @@ BSLS_IDENT("$Id: $")
// > by the current compiler settings for this platform. In particular,
// > this allows lambda functions to be defined in a `constexpr` function.
//
// * `BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20`
// > This macro is defined if 'constexpr' with C++20 semantics is supported
// > by the current compiler settings for this platform. In particular,
// > this allows transient allocations.
//
// * `BSLS_COMPILERFEATURES_SUPPORT_COROUTINE`
// > This macro is defined if coroutines with C++20 (or later) semantics are
// > supported by the current compiler settings, including the existence of
Expand Down Expand Up @@ -1115,6 +1126,19 @@ BSLS_IDENT("$Id: $")
#endif
#endif

#if __cplusplus > 201703L || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
// We test against 201907L instead of the published 202002L.
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
#if defined(__cpp_constexpr_dynamic_alloc) && \
__cpp_constexpr_dynamic_alloc >= 201907L
#define BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20 1
#endif
#endif
#if defined(__cpp_consteval) && __cpp_consteval >= 201811L
#define BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20 1
#endif
#endif

// ============================================================================
// ATTRIBUTE DETECTION
// ============================================================================
Expand Down
173 changes: 171 additions & 2 deletions groups/bsl/bsls/bsls_compilerfeatures.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@
// [27] BSLS_COMPILERFEATURES_SUPPORT_ATTRIBUTE_FALLTHROUGH
// [28] BSLS_COMPILERFEATURES_SUPPORT_ATTRIBUTE_MAYBE_UNUSED
// [38] BSLS_COMPILERFEATURES_SUPPORT_CONCEPTS
// [40] BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20
// [ 2] BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR
// [ 3] BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP14
// [ 4] BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP17
// [39] BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20
// [37] BSLS_COMPILERFEATURES_SUPPORT_COROUTINE
// [34] BSLS_COMPILERFEATURES_SUPPORT_CTAD
// [ 5] BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
Expand Down Expand Up @@ -92,7 +94,7 @@
// [ ] BSLS_COMPILERFEATURES_FORWARD_REF
// [ ] BSLS_COMPILERFEATURES_FORWARD
// ----------------------------------------------------------------------------
// [39] USAGE EXAMPLE
// [41] USAGE EXAMPLE

#ifdef BDE_VERIFY
// Suppress some pedantic bde_verify checks in this test driver
Expand Down Expand Up @@ -696,6 +698,20 @@ constexpr int moreRelaxedConstExprFunc(bool b)
}
#endif // BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP17

#if defined(BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20)
/// Return a different integer value depending on the specified `b` boolean
/// value. Function is declared `consteval` to test support for the keyword.
consteval int constEvalFunc(bool b)
{
if (b) {
return 6; // RETURN
}
else {
return 7; // RETURN
}
}
#endif // BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20

/// A type to represent `false`. Notice that its size is different from
/// that of `TrueType`.
struct FalseType {
Expand Down Expand Up @@ -845,6 +861,68 @@ constexpr int Feature17::call(bool b) {
}
}
#endif // BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP17

#if defined(BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20)
/// This literal type is for testing C++20 `constexpr` support.
struct ConstexprCpp20TrivialTypeForTest {
// PUBLIC DATA
int d_value;
};

/// This literal type is for testing C++20 `constexpr` support.
struct ConstexprCpp20Tester {

// PUBLIC DATA
int d_value;

// CREATORS

/// Create a, possibly `constexpr`, `ConstexprCpp20Tester` object.
constexpr ConstexprCpp20Tester();

/// Return, a possibly `constexpr` integer value that depends on the
/// specified `b` flag. This method is "complex", cannot be `constexpr`
/// in C++17, only in C++20 and onwards.
constexpr int call(bool b);

// ACCESSORS

// Simple `constexpr virtual` function only supported in C++20.
constexpr virtual int func1(bool b);
};

constexpr ConstexprCpp20Tester::ConstexprCpp20Tester() : d_value(-1)
{
}

constexpr int ConstexprCpp20Tester::call(bool b)
{
int r1;
try {
r1 = func1(b);
}
catch (...) {
}

// default trivial construction (not allowed in C++17)
ConstexprCpp20TrivialTypeForTest tt;
// assign a value to make this constexpr in C++20
tt = ConstexprCpp20TrivialTypeForTest{};

if (b) {
return 10 + r1 + tt.d_value; // RETURN
}
else {
return 20 + r1 + tt.d_value; // RETURN
}
}

constexpr int ConstexprCpp20Tester::func1(bool b)
{
return b ? 0 : 1;
}
#endif // BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20

#endif // BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR

} // close unnamed namespace
Expand Down Expand Up @@ -1589,6 +1667,13 @@ static void printFlags()
puts("UNDEFINED");
#endif

fputs("\n BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20: ", stdout);
#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20
puts(STRINGIFY(BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20));
#else
puts("UNDEFINED");
#endif

fputs("\n BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR: ", stdout);
#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR
puts(STRINGIFY(BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR));
Expand All @@ -1610,6 +1695,13 @@ static void printFlags()
puts("UNDEFINED");
#endif

fputs("\n BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20: ", stdout);
#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20
puts(STRINGIFY(BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20));
#else
puts("UNDEFINED");
#endif

fputs("\n BSLS_COMPILERFEATURES_SUPPORT_COROUTINE: ", stdout);
#ifdef BSLS_COMPILERFEATURES_SUPPORT_COROUTINE
puts(STRINGIFY(BSLS_COMPILERFEATURES_SUPPORT_COROUTINE));
Expand Down Expand Up @@ -2092,7 +2184,7 @@ int main(int argc, char *argv[])
}

switch (test) { case 0:
case 39: {
case 41: {
// --------------------------------------------------------------------
// USAGE EXAMPLE
//
Expand Down Expand Up @@ -2173,6 +2265,83 @@ int main(int argc, char *argv[])
// compilers) that further, more complicated or even indeterminate behaviors
// may arise.
#undef THATS_MY_LINE
} break;
case 40: {
// ------------------------------------------------------------------
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20
//
// Concerns:
// 1. `BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20` is defined only
// when the compiler understands the `consteval` keyword.
//
// Plan:
// 1. If `BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20` is defined
// then compile code that uses the `consteval` keyword.
//
// Testing:
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20
// ------------------------------------------------------------------

MACRO_TEST_TITLE("_SUPPORT_CONSTEVAL_CPP20",
"==================");

#ifndef BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20
VERBOSE_PUTS("The feature is not supported in this configuration.");
#else
ASSERT(__cpp_consteval >= 201811L);

static_assert(constEvalFunc(true) == 6,
"`consteval` is not supported");
#endif
} break;
case 39: {
// ------------------------------------------------------------------
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20
//
// Concerns:
// 1. `BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20` is defined only
// when the compiler is actually able to compile code with relaxed
// constexpr functions that may use try/catch blocks, call virtual
// functions, and perform trivial default initialization.
//
// Plan:
// 1. If `BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20` is defined
// then compile code that uses this feature to define relaxed
// constant expression functions.
//
// Testing:
// BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20
// ------------------------------------------------------------------

MACRO_TEST_TITLE("_SUPPORT_CONSTEXPR_CPP20",
"========================");

#ifndef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20
VERBOSE_PUTS("The feature is not supported in this configuration.");
#else
ASSERT(__cpp_constexpr >= 201907L);
ASSERT(__cpp_constexpr_dynamic_alloc >= 201907L);

if (sizeof(Sniffer::test<ConstexprCpp20Tester>(0)) ==
sizeof(FalseType)) {
ASSERT(0 == "C++17 did not detect more relaxed constexpr");
}

static_assert(moreRelaxedConstExprFunc(true) == 42,
"Relaxed (C++17) `constexpr` is not supported");

if (sizeof(Sniffer::test<Feature17>(0)) == sizeof(FalseType)) {
ASSERT(0 == "C++17 did not detect more relaxed constexpr");
}

if (sizeof(Sniffer::test<Feature14>(0)) == sizeof(FalseType)) {
ASSERT(0 == "C++17 did not detect relaxed constexpr");
}

if (sizeof(Sniffer::test<Feature11>(0)) == sizeof(FalseType)) {
ASSERT(0 == "C++17 did not detect original constexpr");
}
#endif
} break;
case 38: {
// --------------------------------------------------------------------
Expand Down
25 changes: 24 additions & 1 deletion groups/bsl/bsls/bsls_keyword.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ BSLS_IDENT("$Id: $")
//@CLASSES:
//
//@MACROS:
// BSLS_KEYWORD_CONSTEVAL_CPP20: C++20 `consteval` keyword
// BSLS_KEYWORD_CONSTEXPR: C++11 `constexpr` keyword
// BSLS_KEYWORD_CONSTEXPR_MEMBER: for `constexpr` data members (Deprecated)
// BSLS_KEYWORD_CONSTEXPR_RELAXED: C++14 `constexpr` keyword (Deprecated)
// BSLS_KEYWORD_CONSTEXPR_CPP14: C++14 `constexpr` keyword
// BSLS_KEYWORD_CONSTEXPR_CPP17: C++17 `constexpr` keyword
// BSLS_KEYWORD_CONSTEXPR_CPP20: C++20 `constexpr` keyword
// BSLS_KEYWORD_DELETED: C++11 `= delete` function definition
// BSLS_KEYWORD_EXPLICIT: C++11 `explicit` for conversion operators
// BSLS_KEYWORD_FINAL: C++11 `final` keyword
Expand All @@ -40,7 +42,11 @@ BSLS_IDENT("$Id: $")
///-------------
// The following are the macros provided by this component.
//
//: `BSLS_KEYWORD_CONSTEXPR`:
//: `BSLS_KEYWORD_CONSTEVAL_CPP20`:
//: This macro inserts the keyword `consteval` when compiling with C++20
//: or later mode and inserts nothing when compiling with earlier modes.
//:
// `BSLS_KEYWORD_CONSTEXPR`:
//: This macro inserts the keyword `constexpr` when compiling with C++11
//: or later mode and inserts nothing when compiling with C++03 mode.
//:
Expand All @@ -67,6 +73,11 @@ BSLS_IDENT("$Id: $")
//: mode. See Example 2 below for a better description of the differences
//: between `constexpr` between C++11, C++14, and C++17.
//:
//: `BSLS_KEYWORD_CONSTEXPR_CPP20`:
//: This macro inserts the keyword `constexpr` when compiling with C++20
//: or later mode and inserts nothing when compiling with
//: C++03/C++11/C++14/C++17 mode.
//:
//: `BSLS_KEYWORD_DELETED`:
//: This macro inserts the text `= delete` when compiling with C++11
//: or later mode and inserts nothing when compiling with C++03 mode.
Expand Down Expand Up @@ -529,6 +540,12 @@ BSLS_IDENT("$Id: $")

#include <bsls_compilerfeatures.h>

#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEVAL_CPP20
# define BSLS_KEYWORD_CONSTEVAL_CPP20 consteval
#else
# define BSLS_KEYWORD_CONSTEVAL_CPP20
#endif

#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR
# define BSLS_KEYWORD_CONSTEXPR constexpr
# define BSLS_KEYWORD_CONSTEXPR_MEMBER constexpr
Expand All @@ -551,6 +568,12 @@ BSLS_IDENT("$Id: $")
# define BSLS_KEYWORD_CONSTEXPR_CPP17
#endif

#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP20
#define BSLS_KEYWORD_CONSTEXPR_CPP20 constexpr
#else
#define BSLS_KEYWORD_CONSTEXPR_CPP20
#endif

#ifdef BSLS_COMPILERFEATURES_SUPPORT_DELETED_FUNCTIONS
# define BSLS_KEYWORD_DELETED = delete
#else
Expand Down
Loading

0 comments on commit e84a9dd

Please sign in to comment.