From 0fcff9f5ea23425570848cff04915523457c0d4c Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Tue, 23 Aug 2022 12:09:51 -0700 Subject: [PATCH 1/2] cmake: Use C++20 for ImGui We use Dolphin code (specifically Common's ASSERT) from ImGui, and that will use C++20 features in the next commit, so ImGui needs to be built with C++20 for that to work properly. --- Externals/imgui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Externals/imgui/CMakeLists.txt b/Externals/imgui/CMakeLists.txt index 16e5ee486f..becebfbe65 100644 --- a/Externals/imgui/CMakeLists.txt +++ b/Externals/imgui/CMakeLists.txt @@ -1,5 +1,5 @@ if (NOT MSVC) - set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) endif() From 0cced44142049c286dbc1821e39703ff09cc03b9 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Tue, 23 Aug 2022 11:14:47 -0700 Subject: [PATCH 2/2] Use `__VA_OPT__(, ) __VA_ARGS__` instead of `##__VA_ARGS__` Per https://en.cppreference.com/w/cpp/preprocessor/replace#.23_and_.23.23_operators the `##` behavior is a nonstandard extension; this extension seems to be supported by all compilers we care about, but IntelliSense in visual studio doesn't correctly handle it, resulting in false errors in the IDE (but not when compiling). Per https://en.cppreference.com/w/cpp/preprocessor/replace#Function-like_macros C++20 introduced a workaround, where `__VA_OPT__(, )` generates a comma if and only if `__VA_ARGS__` is non-empty. This PR replaces all occurrences, with the exception of Externals, DSPSpy (which is not likely to be edited in MSVC and does not target C++20 currently), and JitArm64_Integer.cpp (which uses `Function(__VA_ARGS__)`, and thus does not ever need a comma). --- Source/Core/Common/Assert.h | 4 +-- Source/Core/Common/Logging/Log.h | 19 +++++++----- Source/Core/Common/MsgHandler.h | 30 ++++++++++--------- .../Core/VideoBackends/Vulkan/VulkanLoader.h | 2 +- Source/Core/VideoCommon/VideoCommon.h | 2 +- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Source/Core/Common/Assert.h b/Source/Core/Common/Assert.h index 865fdc8a18..dd9ce9b1ae 100644 --- a/Source/Core/Common/Assert.h +++ b/Source/Core/Common/Assert.h @@ -17,7 +17,7 @@ "An error occurred.\n\n" _fmt_ "\n\n" \ " Condition: {}\n File: {}\n Line: {}\n Function: {}\n\n" \ "Ignore and continue?", \ - ##__VA_ARGS__, #_a_, __FILE__, __LINE__, __func__)) \ + __VA_ARGS__ __VA_OPT__(, ) #_a_, __FILE__, __LINE__, __func__)) \ Crash(); \ } \ } while (0) @@ -26,7 +26,7 @@ do \ { \ if constexpr (Common::Log::MAX_LOGLEVEL >= Common::Log::LogLevel::LDEBUG) \ - ASSERT_MSG(_t_, _a_, _fmt_, ##__VA_ARGS__); \ + ASSERT_MSG(_t_, _a_, _fmt_ __VA_OPT__(, ) __VA_ARGS__); \ } while (0) #define ASSERT(_a_) \ diff --git a/Source/Core/Common/Logging/Log.h b/Source/Core/Common/Logging/Log.h index 00ac869ac8..29a65a972d 100644 --- a/Source/Core/Common/Logging/Log.h +++ b/Source/Core/Common/Logging/Log.h @@ -111,33 +111,38 @@ void GenericLogFmt(LogLevel level, LogType type, const char* file, int line, con { \ /* Use a macro-like name to avoid shadowing warnings */ \ constexpr auto GENERIC_LOG_FMT_N = Common::CountFmtReplacementFields(format); \ - Common::Log::GenericLogFmt(v, t, __FILE__, __LINE__, FMT_STRING(format), \ - ##__VA_ARGS__); \ + Common::Log::GenericLogFmt( \ + v, t, __FILE__, __LINE__, FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__); \ } \ } while (0) #define ERROR_LOG_FMT(t, ...) \ do \ { \ - GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LERROR, __VA_ARGS__); \ + GENERIC_LOG_FMT(Common::Log::LogType::t, \ + Common::Log::LogLevel::LERROR __VA_OPT__(, ) __VA_ARGS__); \ } while (0) #define WARN_LOG_FMT(t, ...) \ do \ { \ - GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LWARNING, __VA_ARGS__); \ + GENERIC_LOG_FMT(Common::Log::LogType::t, \ + Common::Log::LogLevel::LWARNING __VA_OPT__(, ) __VA_ARGS__); \ } while (0) #define NOTICE_LOG_FMT(t, ...) \ do \ { \ - GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LNOTICE, __VA_ARGS__); \ + GENERIC_LOG_FMT(Common::Log::LogType::t, \ + Common::Log::LogLevel::LNOTICE __VA_OPT__(, ) __VA_ARGS__); \ } while (0) #define INFO_LOG_FMT(t, ...) \ do \ { \ - GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LINFO, __VA_ARGS__); \ + GENERIC_LOG_FMT(Common::Log::LogType::t, \ + Common::Log::LogLevel::LINFO __VA_OPT__(, ) __VA_ARGS__); \ } while (0) #define DEBUG_LOG_FMT(t, ...) \ do \ { \ - GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LDEBUG, __VA_ARGS__); \ + GENERIC_LOG_FMT(Common::Log::LogType::t, \ + Common::Log::LogLevel::LDEBUG __VA_OPT__(, ) __VA_ARGS__); \ } while (0) diff --git a/Source/Core/Common/MsgHandler.h b/Source/Core/Common/MsgHandler.h index 1d6a467852..e3ed2c80db 100644 --- a/Source/Core/Common/MsgHandler.h +++ b/Source/Core/Common/MsgHandler.h @@ -84,46 +84,48 @@ std::string FmtFormatT(const char* string, Args&&... args) #define GenericAlertFmt(yes_no, style, log_type, format, ...) \ Common::MsgAlertFmt( \ - yes_no, style, Common::Log::LogType::log_type, __FILE__, __LINE__, FMT_STRING(format), \ - ##__VA_ARGS__) + yes_no, style, Common::Log::LogType::log_type, __FILE__, __LINE__, \ + FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__) #define GenericAlertFmtT(yes_no, style, log_type, format, ...) \ Common::MsgAlertFmtT( \ yes_no, style, Common::Log::LogType::log_type, __FILE__, __LINE__, FMT_STRING(format), \ - Common::GetStringT(format), ##__VA_ARGS__) + Common::GetStringT(format) __VA_OPT__(, ) __VA_ARGS__) #define SuccessAlertFmt(format, ...) \ - GenericAlertFmt(false, Common::MsgType::Information, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmt(false, Common::MsgType::Information, MASTER_LOG, \ + format __VA_OPT__(, ) __VA_ARGS__) #define PanicAlertFmt(format, ...) \ - GenericAlertFmt(false, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmt(false, Common::MsgType::Warning, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) #define PanicYesNoFmt(format, ...) \ - GenericAlertFmt(true, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmt(true, Common::MsgType::Warning, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) #define AskYesNoFmt(format, ...) \ - GenericAlertFmt(true, Common::MsgType::Question, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmt(true, Common::MsgType::Question, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) #define CriticalAlertFmt(format, ...) \ - GenericAlertFmt(false, Common::MsgType::Critical, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmt(false, Common::MsgType::Critical, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) // Use these macros (that do the same thing) if the message should be translated. #define SuccessAlertFmtT(format, ...) \ - GenericAlertFmtT(false, Common::MsgType::Information, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmtT(false, Common::MsgType::Information, MASTER_LOG, \ + format __VA_OPT__(, ) __VA_ARGS__) #define PanicAlertFmtT(format, ...) \ - GenericAlertFmtT(false, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmtT(false, Common::MsgType::Warning, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) #define PanicYesNoFmtT(format, ...) \ - GenericAlertFmtT(true, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmtT(true, Common::MsgType::Warning, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) #define AskYesNoFmtT(format, ...) \ - GenericAlertFmtT(true, Common::MsgType::Question, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmtT(true, Common::MsgType::Question, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) #define CriticalAlertFmtT(format, ...) \ - GenericAlertFmtT(false, Common::MsgType::Critical, MASTER_LOG, format, ##__VA_ARGS__) + GenericAlertFmtT(false, Common::MsgType::Critical, MASTER_LOG, format __VA_OPT__(, ) __VA_ARGS__) // Variant that takes a log type, used by the assert macros #define PanicYesNoFmtAssert(log_type, format, ...) \ - GenericAlertFmt(true, Common::MsgType::Warning, log_type, format, ##__VA_ARGS__) + GenericAlertFmt(true, Common::MsgType::Warning, log_type, format __VA_OPT__(, ) __VA_ARGS__) diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h index 8ac86668b8..c20ea698d3 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h +++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h @@ -51,6 +51,6 @@ void LogVulkanResult(Common::Log::LogLevel level, const char* func_name, VkResul const char* msg, ...); #define LOG_VULKAN_ERROR(res, ...) \ - LogVulkanResult(Common::Log::LogLevel::LERROR, __func__, res, __VA_ARGS__) + LogVulkanResult(Common::Log::LogLevel::LERROR, __func__, res __VA_OPT__(, ) __VA_ARGS__) } // namespace Vulkan diff --git a/Source/Core/VideoCommon/VideoCommon.h b/Source/Core/VideoCommon/VideoCommon.h index 3b6540c822..b827256730 100644 --- a/Source/Core/VideoCommon/VideoCommon.h +++ b/Source/Core/VideoCommon/VideoCommon.h @@ -24,7 +24,7 @@ constexpr u32 MAX_XFB_WIDTH = 720; // that are next to each other in memory (TODO: handle that situation). constexpr u32 MAX_XFB_HEIGHT = 576; -#define PRIM_LOG(...) DEBUG_LOG_FMT(VIDEO, ##__VA_ARGS__) +#define PRIM_LOG(t, ...) DEBUG_LOG_FMT(VIDEO, t __VA_OPT__(, ) __VA_ARGS__) // warning: mapping buffer should be disabled to use this // #define LOG_VTX() DEBUG_LOG_FMT(VIDEO, "vtx: {} {} {}, ",