From 167ec541407c7207b5a527a537cb057c85afb756 Mon Sep 17 00:00:00 2001 From: Dean Glazeski Date: Sat, 22 Feb 2025 09:39:29 -0700 Subject: [PATCH] Report error on duplicate named arg names #4282 --- include/fmt/base.h | 10 ++++++++++ test/compile-error-test/CMakeLists.txt | 8 ++++++++ test/format-test.cc | 2 ++ 3 files changed, 20 insertions(+) diff --git a/include/fmt/base.h b/include/fmt/base.h index a37858a843c5..7be57f09ce2a 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1071,6 +1071,11 @@ void init_named_arg(named_arg_info*, int& arg_index, int&, const T&) { template ::value)> void init_named_arg(named_arg_info* named_args, int& arg_index, int& named_arg_index, const T& arg) { + for (auto i = 0; i < named_arg_index; ++i) { + if (basic_string_view(named_args[i].name) == basic_string_view(arg.name)) { + report_error("duplicate named args found"); + } + } named_args[named_arg_index++] = {arg.name, arg_index++}; } @@ -1084,6 +1089,11 @@ template ::value)> FMT_CONSTEXPR void init_static_named_arg(named_arg_info* named_args, int& arg_index, int& named_arg_index) { + for (auto i = 0; i < named_arg_index; ++i) { + if (basic_string_view(named_args[i].name) == basic_string_view(T::name)) { + report_error("duplicate named args found"); + } + } named_args[named_arg_index++] = {T::name, arg_index++}; } diff --git a/test/compile-error-test/CMakeLists.txt b/test/compile-error-test/CMakeLists.txt index a86996e21f95..b2586a76af27 100644 --- a/test/compile-error-test/CMakeLists.txt +++ b/test/compile-error-test/CMakeLists.txt @@ -209,6 +209,14 @@ if (CMAKE_CXX_STANDARD GREATER_EQUAL 20) #error #endif " ERROR) + expect_compile(format-string-duplicate-name-error " + #if defined(FMT_HAS_CONSTEVAL) && FMT_USE_NONTYPE_TEMPLATE_ARGS + using namespace fmt::literals; + fmt::print(\"{bar}\", \"bar\"_a=42, \"bar\"_a=43); + #else + #error + #endif + " ERROR) endif () # Run all tests diff --git a/test/format-test.cc b/test/format-test.cc index c16f895bed29..ce5db19ec39f 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -582,6 +582,8 @@ TEST(format_test, named_arg) { EXPECT_EQ("1/a/A", fmt::format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'), fmt::arg("A_", "A"), fmt::arg("_1", 1))); EXPECT_EQ(fmt::format("{0:{width}}", -42, fmt::arg("width", 4)), " -42"); + EXPECT_THROW_MSG(fmt::format("{enum}", fmt::arg("enum", 1), fmt::arg("enum", 10)), + format_error, "duplicate named args found"); EXPECT_EQ("st", fmt::format("{0:.{precision}}", "str", fmt::arg("precision", 2))); EXPECT_EQ(fmt::format("{} {two}", 1, fmt::arg("two", 2)), "1 2");