Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions roofit/codegen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ if(NOT CMAKE_VERSION VERSION_LESS "3.23.0")
inc/RooFit/CodegenImpl.h
)
endif()

ROOT_ADD_TEST_SUBDIRECTORY(test)
4 changes: 4 additions & 0 deletions roofit/codegen/src/CodegenImpl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

#include <TInterpreter.h>

#include <locale>
#include <unordered_set>

namespace RooFit::Experimental {
Expand All @@ -76,6 +77,9 @@ namespace {
std::string doubleToString(double val)
{
std::stringstream ss;
// The formatting must not depend on the global locale: a comma decimal
// separator (e.g. from a German locale) would corrupt the generated C++.
ss.imbue(std::locale::classic());
ss << std::setprecision(std::numeric_limits<double>::max_digits10) << val;
return ss.str();
}
Expand Down
1 change: 1 addition & 0 deletions roofit/codegen/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ROOT_ADD_GTEST(testCodegen testCodegen.cxx LIBRARIES RooFitCore RooFit RooFitCodegen)
114 changes: 114 additions & 0 deletions roofit/codegen/test/testCodegen.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Tests for the C++ code that the RooFit codegen backend generates.
// Author: Jonas Rembser, CERN 2026

#include <RooFit/CodegenContext.h>

#include <RooChebychev.h>
#include <RooConstVar.h>
#include <RooGaussian.h>
#include <RooRealVar.h>

#include <gtest/gtest.h>

#include <locale>
#include <regex>
#include <sstream>
#include <string>

namespace {

/// Formats decimal points as ',' like a German locale does. Such a locale is
/// not installed on every test machine, so it is built from a custom facet
/// instead of requested by name. The resulting locale is unnamed, so making it
/// global does not also switch the C locale that std::strtod() uses.
struct CommaPunct : std::numpunct<char> {
char do_decimal_point() const override { return ','; }
};

/// Generate the code for `arg` with `loc` as the global locale, restoring the
/// previous global locale even if code generation throws.
std::string codeUnderLocale(RooAbsArg &arg, std::locale const &loc)
{
const std::locale old = std::locale::global(loc);
std::string code;
try {
RooFit::Experimental::CodegenContext ctx;
ctx.buildFunction(arg);
code = ctx.collectedCode();
} catch (...) {
std::locale::global(old);
throw;
}
std::locale::global(old);
return code;
}

/// Erase the global counter from the generated function name, which differs
/// between two code generations of the same model.
std::string normalized(std::string const &code)
{
return std::regex_replace(code, std::regex{"roo_codegen_[0-9]+"}, "roo_codegen_N");
}

/// How a plain stream formats 0.5 under `loc`, to verify that the facet is
/// actually in effect (otherwise the tests below would pass vacuously).
std::string formatWithStream(double val, std::locale const &loc)
{
const std::locale old = std::locale::global(loc);
std::stringstream ss;
ss << val;
std::locale::global(old);
return ss.str();
}

} // namespace

// The generated code is C++ source, so its number formatting must not follow
// the global locale: under a comma-decimal locale the literals came out as
// "0,5", which does not compile, and inside a function call argument list the
// comma even turns one argument into two.
TEST(RooFitCodegen, ValueLiteralsAreLocaleIndependent)
{
const std::locale comma{std::locale::classic(), new CommaPunct};
ASSERT_EQ(formatWithStream(0.5, comma), "0,5");

RooRealVar x{"x", "x", 0.5, -10, 10};
RooRealVar mean{"mean", "mean", 1.25};
RooConstVar sigma{"sigma", "sigma", 0.75};
RooGaussian gauss{"gauss", "gauss", x, mean, sigma};
x.setConstant(true);
mean.setConstant(true);

const std::string code = codeUnderLocale(gauss, comma);

EXPECT_EQ(normalized(code), normalized(codeUnderLocale(gauss, std::locale::classic())));
for (std::string const &literal : {"0.5", "1.25", "0.75"}) {

Check failure on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / debian13 dev=ON, CMAKE_CXX_FLAGS=-Wsuggest-override

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Werror=range-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 benchmark build CMAKE_CXX_STANDARD=20

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2604

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora43

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 modules_off CMAKE_CXX_STANDARD=20

loop variable ‘literal’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / opensuse16 march_native

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora44

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / rawhide Fedora pydebug no GIL CMAKE_CXX_STANDARD=23

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 arm64 CMAKE_BUILD_TYPE=RelWithDebInfo, builtin_zlib=ON, builtin_zstd=ON, CMAKE_CXX_STANDARD=20

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu22 imt=Off, CMAKE_BUILD_TYPE=Debug

loop variable ‘literal’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 CMAKE_BUILD_TYPE=Debug

loop variable ‘literal’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 85 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2404 CMAKE_BUILD_TYPE=Debug

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]
EXPECT_NE(code.find(literal), std::string::npos) << literal << " missing from:\n" << code;
}
for (std::string const &corrupted : {"0,5", "1,25", "0,75"}) {

Check failure on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / debian13 dev=ON, CMAKE_CXX_FLAGS=-Wsuggest-override

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Werror=range-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 benchmark build CMAKE_CXX_STANDARD=20

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2604

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora43

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 modules_off CMAKE_CXX_STANDARD=20

loop variable ‘corrupted’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / opensuse16 march_native

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora44

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / rawhide Fedora pydebug no GIL CMAKE_CXX_STANDARD=23

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 arm64 CMAKE_BUILD_TYPE=RelWithDebInfo, builtin_zlib=ON, builtin_zstd=ON, CMAKE_CXX_STANDARD=20

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu22 imt=Off, CMAKE_BUILD_TYPE=Debug

loop variable ‘corrupted’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 CMAKE_BUILD_TYPE=Debug

loop variable ‘corrupted’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 88 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2404 CMAKE_BUILD_TYPE=Debug

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]
EXPECT_EQ(code.find(corrupted), std::string::npos) << corrupted << " emitted in:\n" << code;
}
}

// Same for the doubles that the codegen implementations pass to the generated
// function calls directly (here the observable range of RooChebychev), which
// are formatted by CodegenContext::buildArg() and not by codegen's
// doubleToString().
TEST(RooFitCodegen, CallArgumentsAreLocaleIndependent)
{
const std::locale comma{std::locale::classic(), new CommaPunct};

RooRealVar x{"x", "x", 0.125, -0.5, 2.25};
RooRealVar a1{"a1", "a1", 0.375};
RooChebychev cheby{"cheby", "cheby", x, a1};

const std::string code = codeUnderLocale(cheby, comma);

EXPECT_EQ(normalized(code), normalized(codeUnderLocale(cheby, std::locale::classic())));
for (std::string const &literal : {"-0.5", "2.25", "0.375"}) {

Check failure on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / debian13 dev=ON, CMAKE_CXX_FLAGS=-Wsuggest-override

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Werror=range-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 benchmark build CMAKE_CXX_STANDARD=20

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2604

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora43

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 modules_off CMAKE_CXX_STANDARD=20

loop variable ‘literal’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / opensuse16 march_native

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora44

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / rawhide Fedora pydebug no GIL CMAKE_CXX_STANDARD=23

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 arm64 CMAKE_BUILD_TYPE=RelWithDebInfo, builtin_zlib=ON, builtin_zstd=ON, CMAKE_CXX_STANDARD=20

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu22 imt=Off, CMAKE_BUILD_TYPE=Debug

loop variable ‘literal’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 CMAKE_BUILD_TYPE=Debug

loop variable ‘literal’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 108 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2404 CMAKE_BUILD_TYPE=Debug

loop variable ‘literal’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]
EXPECT_NE(code.find(literal), std::string::npos) << literal << " missing from:\n" << code;
}
for (std::string const &corrupted : {"0,5", "2,25", "0,375"}) {

Check failure on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / debian13 dev=ON, CMAKE_CXX_FLAGS=-Wsuggest-override

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Werror=range-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 benchmark build CMAKE_CXX_STANDARD=20

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2604

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora43

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 modules_off CMAKE_CXX_STANDARD=20

loop variable ‘corrupted’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / opensuse16 march_native

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / fedora44

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / rawhide Fedora pydebug no GIL CMAKE_CXX_STANDARD=23

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma10 arm64 CMAKE_BUILD_TYPE=RelWithDebInfo, builtin_zlib=ON, builtin_zstd=ON, CMAKE_CXX_STANDARD=20

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu22 imt=Off, CMAKE_BUILD_TYPE=Debug

loop variable ‘corrupted’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / alma9 CMAKE_BUILD_TYPE=Debug

loop variable ‘corrupted’ of type ‘const string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]

Check warning on line 111 in roofit/codegen/test/testCodegen.cxx

View workflow job for this annotation

GitHub Actions / ubuntu2404 CMAKE_BUILD_TYPE=Debug

loop variable ‘corrupted’ of type ‘const std::string&’ {aka ‘const std::__cxx11::basic_string<char>&’} binds to a temporary constructed from type ‘const char* const’ [-Wrange-loop-construct]
EXPECT_EQ(code.find(corrupted), std::string::npos) << corrupted << " emitted in:\n" << code;
}
}
3 changes: 3 additions & 0 deletions roofit/roofitcore/inc/RooFit/CodegenContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <cstddef>
#include <iomanip>
#include <locale>
#include <sstream>
#include <string>
#include <type_traits>
Expand Down Expand Up @@ -139,6 +140,7 @@ class CodegenContext {
std::string buildArg(T x)
{
std::stringstream ss;
ss.imbue(std::locale::classic()); // the generated code is C++, not locale-dependent text
ss << std::setprecision(std::numeric_limits<double>::max_digits10) << x;
return ss.str();
}
Expand Down Expand Up @@ -215,6 +217,7 @@ std::string CodegenContext::buildArgSpanImpl(std::span<const T> arr)
unsigned int n = arr.size();
std::string arrName = getTmpVarName();
std::stringstream ss;
ss.imbue(std::locale::classic()); // the generated code is C++, not locale-dependent text
ss << typeName<T>() << " " << arrName << "[" << n << "] = {";
for (unsigned int i = 0; i < n; i++) {
ss << " " << arr[i] << ",";
Expand Down
2 changes: 2 additions & 0 deletions roofit/roofitcore/src/RooFit/CodegenContext.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cctype>
#include <charconv>
#include <fstream>
#include <locale>
#include <type_traits>
#include <unordered_map>

Expand Down Expand Up @@ -285,6 +286,7 @@ std::string CodegenContext::buildArg(std::span<const double> arr)
CodegenContext::ScopeRAII::ScopeRAII(RooAbsArg const *arg, CodegenContext &ctx) : _ctx(ctx), _arg(arg)
{
std::ostringstream os;
os.imbue(std::locale::classic()); // the generated code is C++, not locale-dependent text
Option_t *opts = nullptr;
arg->printStream(os, _arg->defaultPrintContents(opts), _arg->defaultPrintStyle(opts));
_fn = os.str();
Expand Down
Loading