diff options
author | Jakub Szewczyk <git@kubasz.xyz> | 2022-03-18 22:10:04 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-18 15:10:04 -0700 |
commit | 88c2e4377df7dbe65bc8ef629ea409cd9df6a860 (patch) | |
tree | 0fe699c08ef55ed5902304e55851cdb1796c6881 | |
parent | 967245fbc75217d257eeba15ede4aeb56e3c0d89 (diff) | |
download | binaryen-88c2e4377df7dbe65bc8ef629ea409cd9df6a860.tar.gz binaryen-88c2e4377df7dbe65bc8ef629ea409cd9df6a860.tar.bz2 binaryen-88c2e4377df7dbe65bc8ef629ea409cd9df6a860.zip |
Fix errors when building in C++20 mode (#4528)
* use [[noreturn]] available since C++11 instead of compiler-specific attributes
* replace deprecated std::is_pod with is_trivial&&is_standard_layout (also available since C++11/14)
* explicitly capture this in [=] lambdas
* extra const functions in FeatureSet, fix implicit cast warning by using the features field directly
* Use CMAKE_CXX_STANDARD to ensure the C++ standard parameter is set on all targets, remove manual compiler flag workaround.
-rw-r--r-- | CMakeLists.txt | 20 | ||||
-rw-r--r-- | src/compiler-support.h | 8 | ||||
-rw-r--r-- | src/support/utilities.cpp | 5 | ||||
-rw-r--r-- | src/support/utilities.h | 15 | ||||
-rw-r--r-- | src/tools/tool-options.h | 4 | ||||
-rw-r--r-- | src/wasm-features.h | 6 |
6 files changed, 26 insertions, 32 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 97a90f8f5..7eae4d3c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,15 @@ include(GNUInstallDirs) # The C++ standard whose features are required to build Binaryen. # Keep in sync with scripts/test/shared.py cxx_standard -set(CXX_STANDARD 17) +# The if condition allows embedding in a project with a higher default C++ standard set +set(REQUIRED_CXX_STANDARD 17) +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD ${REQUIRED_CXX_STANDARD}) +elseif(CMAKE_CXX_STANDARD LESS ${REQUIRED_CXX_STANDARD}) + message(SEND_ERROR "Building with C++ standards older than C++${REQUIRED_CXX_STANDARD} is not supported, change CMAKE_CXX_STANDARD to ${REQUIRED_CXX_STANDARD} or later") +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) if(NOT CMAKE_BUILD_TYPE) message(STATUS "No build type selected, default to Release") @@ -109,8 +117,6 @@ function(binaryen_add_executable name sources) add_executable(${name} ${sources}) target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(${name} binaryen) - set_property(TARGET ${name} PROPERTY CXX_STANDARD ${CXX_STANDARD}) - set_property(TARGET ${name} PROPERTY CXX_STANDARD_REQUIRED ON) binaryen_setup_rpath(${name}) install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR}) endfunction() @@ -175,12 +181,11 @@ if(MSVC) add_compile_flag("/arch:sse2") endif() endif() - add_compile_flag("/std:c++${CXX_STANDARD}") add_compile_flag("/wd4146") # Ignore warning "warning C4146: unary minus operator applied to unsigned type, result still unsigned", this pattern is used somewhat commonly in the code. # 4267 and 4244 are conversion/truncation warnings. We might want to fix these but they are currently pervasive. add_compile_flag("/wd4267") add_compile_flag("/wd4244") - # 4722 warns that destructors never return, even with WASM_NORETURN. + # 4722 warns that destructors never return, even with [[noreturn]]. add_compile_flag("/wd4722") # "destructor was implicitly defined as deleted" caused by LLVM headers. add_compile_flag("/wd4624") @@ -233,7 +238,6 @@ else() set(THREADS_PREFER_PTHREAD_FLAG ON) set(CMAKE_THREAD_PREFER_PTHREAD ON) find_package(Threads REQUIRED) - add_cxx_flag("-std=c++${CXX_STANDARD}") if(NOT EMSCRIPTEN) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$") # wasm doesn't allow for x87 floating point math @@ -384,8 +388,6 @@ if(EMSCRIPTEN) target_link_libraries(binaryen_wasm optimized "--closure-args \"--language_in=ECMASCRIPT6 --language_out=ECMASCRIPT6\"") target_link_libraries(binaryen_wasm optimized "-flto") target_link_libraries(binaryen_wasm debug "--profiling") - set_property(TARGET binaryen_wasm PROPERTY CXX_STANDARD ${CXX_STANDARD}) - set_property(TARGET binaryen_wasm PROPERTY CXX_STANDARD_REQUIRED ON) install(TARGETS binaryen_wasm DESTINATION ${CMAKE_INSTALL_BINDIR}) # binaryen.js JavaScript variant @@ -409,8 +411,6 @@ if(EMSCRIPTEN) target_link_libraries(binaryen_js optimized "-flto") target_link_libraries(binaryen_js debug "--profiling") target_link_libraries(binaryen_js debug "-s ASSERTIONS") - set_property(TARGET binaryen_js PROPERTY CXX_STANDARD ${CXX_STANDARD}) - set_property(TARGET binaryen_js PROPERTY CXX_STANDARD_REQUIRED ON) install(TARGETS binaryen_js DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/src/compiler-support.h b/src/compiler-support.h index 5f3edacea..eddb2d7f0 100644 --- a/src/compiler-support.h +++ b/src/compiler-support.h @@ -31,14 +31,6 @@ #define WASM_BUILTIN_UNREACHABLE __assume(false) #endif -#ifdef __GNUC__ -#define WASM_NORETURN __attribute__((noreturn)) -#elif defined(_MSC_VER) -#define WASM_NORETURN __declspec(noreturn) -#else -#define WASM_NORETURN -#endif - // The code might contain TODOs or stubs that read some values but do nothing // with them. The compiler might fail with [-Werror,-Wunused-variable]. // The WASM_UNUSED(varible) is a wrapper that helps to suppress the error. diff --git a/src/support/utilities.cpp b/src/support/utilities.cpp index ea426df9c..f051a1871 100644 --- a/src/support/utilities.cpp +++ b/src/support/utilities.cpp @@ -24,9 +24,8 @@ #include "sanitizer/common_interface_defs.h" #endif -void wasm::handle_unreachable(const char* msg, - const char* file, - unsigned line) { +[[noreturn]] void +wasm::handle_unreachable(const char* msg, const char* file, unsigned line) { #ifndef NDEBUG if (msg) { std::cerr << msg << "\n"; diff --git a/src/support/utilities.h b/src/support/utilities.h index 38fe6fd73..57d170269 100644 --- a/src/support/utilities.h +++ b/src/support/utilities.h @@ -36,8 +36,11 @@ template<class Destination, class Source> inline Destination bit_cast(const Source& source) { static_assert(sizeof(Destination) == sizeof(Source), "bit_cast needs to be between types of the same size"); - static_assert(std::is_pod<Destination>::value, "non-POD bit_cast undefined"); - static_assert(std::is_pod<Source>::value, "non-POD bit_cast undefined"); + static_assert(std::is_trivial_v<Destination> && + std::is_standard_layout_v<Destination>, + "non-POD bit_cast undefined"); + static_assert(std::is_trivial_v<Source> && std::is_standard_layout_v<Source>, + "non-POD bit_cast undefined"); Destination destination; std::memcpy(&destination, &source, sizeof(destination)); return destination; @@ -65,7 +68,7 @@ public: std::cerr << arg; return *this; } - WASM_NORETURN ~Fatal() { + [[noreturn]] ~Fatal() { std::cerr << "\n"; // Use _Exit here to avoid calling static destructors. This avoids deadlocks // in (for example) the thread worker pool, where workers hold a lock while @@ -74,9 +77,9 @@ public: } }; -WASM_NORETURN void handle_unreachable(const char* msg = nullptr, - const char* file = nullptr, - unsigned line = 0); +[[noreturn]] void handle_unreachable(const char* msg = nullptr, + const char* file = nullptr, + unsigned line = 0); // If control flow reaches the point of the WASM_UNREACHABLE(), the program is // undefined. diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 0ed0f27fb..f8278e950 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -155,7 +155,7 @@ struct ToolOptions : public Options { std::string("Enable ") + description, ToolOptionsCategory, Arguments::Zero, - [=](Options*, const std::string&) { + [this, feature](Options*, const std::string&) { enabledFeatures.set(feature, true); disabledFeatures.set(feature, false); }) @@ -165,7 +165,7 @@ struct ToolOptions : public Options { std::string("Disable ") + description, ToolOptionsCategory, Arguments::Zero, - [=](Options*, const std::string&) { + [this, feature](Options*, const std::string&) { enabledFeatures.set(feature, false); disabledFeatures.set(feature, true); }); diff --git a/src/wasm-features.h b/src/wasm-features.h index 7311aadd3..02e1660bb 100644 --- a/src/wasm-features.h +++ b/src/wasm-features.h @@ -82,7 +82,7 @@ struct FeatureSet { } } - std::string toString() { + std::string toString() const { std::string ret; uint32_t x = 1; while (x & Feature::All) { @@ -102,7 +102,7 @@ struct FeatureSet { operator uint32_t() const { return features; } bool isMVP() const { return features == MVP; } - bool has(FeatureSet f) { return (features & f) == f; } + bool has(FeatureSet f) const { return (features & f) == f.features; } bool hasAtomics() const { return (features & Atomics) != 0; } bool hasMutableGlobals() const { return (features & MutableGlobals) != 0; } bool hasTruncSat() const { return (features & TruncSat) != 0; } @@ -165,7 +165,7 @@ struct FeatureSet { features = features & ~other.features & All; } - template<typename F> void iterFeatures(F f) { + template<typename F> void iterFeatures(F f) const { for (uint32_t feature = MVP + 1; feature < All; feature <<= 1) { if (has(feature)) { f(static_cast<Feature>(feature)); |