llvm.org GIT mirror llvm / 6952476
[Support] PR33388 - Fix formatv_object move constructor formatv_object currently uses the implicitly defined move constructor, but it is buggy. In typical use-cases, the problem doesn't show-up because all calls to the move constructor are elided. Thus, the buggy constructors are never invoked. The issue especially shows-up when code is compiled using the -fno-elide-constructors compiler flag. For instance, this is useful when attempting to collect accurate code coverage statistics. The exact issue is the following: The Parameters data member is correctly moved, thus making the parameters occupy a new memory location in the target object. Unfortunately, the default copying of the Adapters blindly copies the vector of pointers, leaving each of these pointers referencing the parameters in the original object instead of the copied one. These pointers quickly become dangling when the original object is deleted. This quickly leads to crashes. The solution is to update the Adapters pointers when performing a move. The copy constructor isn't useful for format objects and can thus be deleted. This resolves PR33388. Differential Revision: https://reviews.llvm.org/D34463 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310475 91177308-0d34-0410-b5e6-96231b3b80d8 Benoit Belley 2 years ago
2 changed file(s) with 23 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
9393 Adapters.reserve(ParamCount);
9494 }
9595
96 formatv_object_base(formatv_object_base const &rhs) = delete;
97
98 formatv_object_base(formatv_object_base &&rhs)
99 : Fmt(std::move(rhs.Fmt)),
100 Adapters(), // Adapters are initialized by formatv_object
101 Replacements(std::move(rhs.Replacements)) {
102 Adapters.reserve(rhs.Adapters.size());
103 };
104
96105 void format(raw_ostream &S) const {
97106 for (auto &R : Replacements) {
98107 if (R.Type == ReplacementType::Empty)
146155 formatv_object(StringRef Fmt, Tuple &&Params)
147156 : formatv_object_base(Fmt, std::tuple_size::value),
148157 Parameters(std::move(Params)) {
158 Adapters = apply_tuple(create_adapters(), Parameters);
159 }
160
161 formatv_object(formatv_object const &rhs) = delete;
162
163 formatv_object(formatv_object &&rhs)
164 : formatv_object_base(std::move(rhs)),
165 Parameters(std::move(rhs.Parameters)) {
149166 Adapters = apply_tuple(create_adapters(), Parameters);
150167 }
151168 };
552552 formatv("{0,=34:X-}", fmt_repeat(fmt_pad(N, 1, 3), 5)).str());
553553 }
554554
555 TEST(FormatVariadicTest, MoveConstructor) {
556 auto fmt = formatv("{0} {1}", 1, 2);
557 auto fmt2 = std::move(fmt);
558 std::string S = fmt2;
559 EXPECT_EQ("1 2", S);
560 }
555561 TEST(FormatVariadicTest, ImplicitConversions) {
556562 std::string S = formatv("{0} {1}", 1, 2);
557563 EXPECT_EQ("1 2", S);