Bug Summary

File:out/../deps/icu-small/source/i18n/double-conversion-double-to-string.cpp
Warning:line 447, column 7
Value stored to 'fast_worked' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name double-conversion-double-to-string.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D U_COMMON_IMPLEMENTATION=1 -D U_I18N_IMPLEMENTATION=1 -D U_IO_IMPLEMENTATION=1 -D U_TOOLUTIL_IMPLEMENTATION=1 -D U_ATTRIBUTE_DEPRECATED= -D _CRT_SECURE_NO_DEPRECATE= -D U_STATIC_IMPLEMENTATION=1 -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/icu-small/source/common -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/tools/toolutil -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-deprecated-declarations -Wno-strict-aliasing -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/icu-small/source/i18n/double-conversion-double-to-string.cpp
1// © 2018 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3//
4// From the double-conversion library. Original license:
5//
6// Copyright 2010 the V8 project authors. All rights reserved.
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met:
10//
11// * Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13// * Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following
15// disclaimer in the documentation and/or other materials provided
16// with the distribution.
17// * Neither the name of Google Inc. nor the names of its
18// contributors may be used to endorse or promote products derived
19// from this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING
34#include "unicode/utypes.h"
35#if !UCONFIG_NO_FORMATTING0
36
37#include <algorithm>
38#include <climits>
39#include <cmath>
40
41// ICU PATCH: Customize header file paths for ICU.
42// The file fixed-dtoa.h is not needed.
43
44#include "double-conversion-double-to-string.h"
45
46#include "double-conversion-bignum-dtoa.h"
47#include "double-conversion-fast-dtoa.h"
48#include "double-conversion-ieee.h"
49#include "double-conversion-utils.h"
50
51// ICU PATCH: Wrap in ICU namespace
52U_NAMESPACE_BEGINnamespace icu_71 {
53
54namespace double_conversion {
55
56#if 0 // not needed for ICU
57const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
58 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
59 static DoubleToStringConverter converter(flags,
60 "Infinity",
61 "NaN",
62 'e',
63 -6, 21,
64 6, 0);
65 return converter;
66}
67
68
69bool DoubleToStringConverter::HandleSpecialValues(
70 double value,
71 StringBuilder* result_builder) const {
72 Double double_inspect(value);
73 if (double_inspect.IsInfinite()) {
74 if (infinity_symbol_ == NULL__null) return false;
75 if (value < 0) {
76 result_builder->AddCharacter('-');
77 }
78 result_builder->AddString(infinity_symbol_);
79 return true;
80 }
81 if (double_inspect.IsNan()) {
82 if (nan_symbol_ == NULL__null) return false;
83 result_builder->AddString(nan_symbol_);
84 return true;
85 }
86 return false;
87}
88
89
90void DoubleToStringConverter::CreateExponentialRepresentation(
91 const char* decimal_digits,
92 int length,
93 int exponent,
94 StringBuilder* result_builder) const {
95 DOUBLE_CONVERSION_ASSERT(length != 0)(void)0;
96 result_builder->AddCharacter(decimal_digits[0]);
97 if (length != 1) {
98 result_builder->AddCharacter('.');
99 result_builder->AddSubstring(&decimal_digits[1], length-1);
100 }
101 result_builder->AddCharacter(exponent_character_);
102 if (exponent < 0) {
103 result_builder->AddCharacter('-');
104 exponent = -exponent;
105 } else {
106 if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
107 result_builder->AddCharacter('+');
108 }
109 }
110 DOUBLE_CONVERSION_ASSERT(exponent < 1e4)(void)0;
111 // Changing this constant requires updating the comment of DoubleToStringConverter constructor
112 const int kMaxExponentLength = 5;
113 char buffer[kMaxExponentLength + 1];
114 buffer[kMaxExponentLength] = '\0';
115 int first_char_pos = kMaxExponentLength;
116 if (exponent == 0) {
117 buffer[--first_char_pos] = '0';
118 } else {
119 while (exponent > 0) {
120 buffer[--first_char_pos] = '0' + (exponent % 10);
121 exponent /= 10;
122 }
123 }
124 // Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength)
125 // For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2
126 while(kMaxExponentLength - first_char_pos < std::min(min_exponent_width_, kMaxExponentLength)) {
127 buffer[--first_char_pos] = '0';
128 }
129 result_builder->AddSubstring(&buffer[first_char_pos],
130 kMaxExponentLength - first_char_pos);
131}
132
133
134void DoubleToStringConverter::CreateDecimalRepresentation(
135 const char* decimal_digits,
136 int length,
137 int decimal_point,
138 int digits_after_point,
139 StringBuilder* result_builder) const {
140 // Create a representation that is padded with zeros if needed.
141 if (decimal_point <= 0) {
142 // "0.00000decimal_rep" or "0.000decimal_rep00".
143 result_builder->AddCharacter('0');
144 if (digits_after_point > 0) {
145 result_builder->AddCharacter('.');
146 result_builder->AddPadding('0', -decimal_point);
147 DOUBLE_CONVERSION_ASSERT(length <= digits_after_point - (-decimal_point))(void)0;
148 result_builder->AddSubstring(decimal_digits, length);
149 int remaining_digits = digits_after_point - (-decimal_point) - length;
150 result_builder->AddPadding('0', remaining_digits);
151 }
152 } else if (decimal_point >= length) {
153 // "decimal_rep0000.00000" or "decimal_rep.0000".
154 result_builder->AddSubstring(decimal_digits, length);
155 result_builder->AddPadding('0', decimal_point - length);
156 if (digits_after_point > 0) {
157 result_builder->AddCharacter('.');
158 result_builder->AddPadding('0', digits_after_point);
159 }
160 } else {
161 // "decima.l_rep000".
162 DOUBLE_CONVERSION_ASSERT(digits_after_point > 0)(void)0;
163 result_builder->AddSubstring(decimal_digits, decimal_point);
164 result_builder->AddCharacter('.');
165 DOUBLE_CONVERSION_ASSERT(length - decimal_point <= digits_after_point)(void)0;
166 result_builder->AddSubstring(&decimal_digits[decimal_point],
167 length - decimal_point);
168 int remaining_digits = digits_after_point - (length - decimal_point);
169 result_builder->AddPadding('0', remaining_digits);
170 }
171 if (digits_after_point == 0) {
172 if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
173 result_builder->AddCharacter('.');
174 }
175 if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
176 result_builder->AddCharacter('0');
177 }
178 }
179}
180
181
182bool DoubleToStringConverter::ToShortestIeeeNumber(
183 double value,
184 StringBuilder* result_builder,
185 DoubleToStringConverter::DtoaMode mode) const {
186 DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE)(void)0;
187 if (Double(value).IsSpecial()) {
188 return HandleSpecialValues(value, result_builder);
189 }
190
191 int decimal_point;
192 bool sign;
193 const int kDecimalRepCapacity = kBase10MaximalLength + 1;
194 char decimal_rep[kDecimalRepCapacity];
195 int decimal_rep_length;
196
197 DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
198 &sign, &decimal_rep_length, &decimal_point);
199
200 bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
201 if (sign && (value != 0.0 || !unique_zero)) {
202 result_builder->AddCharacter('-');
203 }
204
205 int exponent = decimal_point - 1;
206 if ((decimal_in_shortest_low_ <= exponent) &&
207 (exponent < decimal_in_shortest_high_)) {
208 CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
209 decimal_point,
210 (std::max)(0, decimal_rep_length - decimal_point),
211 result_builder);
212 } else {
213 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
214 result_builder);
215 }
216 return true;
217}
218
219
220bool DoubleToStringConverter::ToFixed(double value,
221 int requested_digits,
222 StringBuilder* result_builder) const {
223 DOUBLE_CONVERSION_ASSERT(kMaxFixedDigitsBeforePoint == 60)(void)0;
224 const double kFirstNonFixed = 1e60;
225
226 if (Double(value).IsSpecial()) {
227 return HandleSpecialValues(value, result_builder);
228 }
229
230 if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
231 if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
232
233 // Find a sufficiently precise decimal representation of n.
234 int decimal_point;
235 bool sign;
236 // Add space for the '\0' byte.
237 const int kDecimalRepCapacity =
238 kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
239 char decimal_rep[kDecimalRepCapacity];
240 int decimal_rep_length;
241 DoubleToAscii(value, FIXED, requested_digits,
242 decimal_rep, kDecimalRepCapacity,
243 &sign, &decimal_rep_length, &decimal_point);
244
245 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
246 if (sign && (value != 0.0 || !unique_zero)) {
247 result_builder->AddCharacter('-');
248 }
249
250 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
251 requested_digits, result_builder);
252 return true;
253}
254
255
256bool DoubleToStringConverter::ToExponential(
257 double value,
258 int requested_digits,
259 StringBuilder* result_builder) const {
260 if (Double(value).IsSpecial()) {
261 return HandleSpecialValues(value, result_builder);
262 }
263
264 if (requested_digits < -1) return false;
265 if (requested_digits > kMaxExponentialDigits) return false;
266
267 int decimal_point;
268 bool sign;
269 // Add space for digit before the decimal point and the '\0' character.
270 const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
271 DOUBLE_CONVERSION_ASSERT(kDecimalRepCapacity > kBase10MaximalLength)(void)0;
272 char decimal_rep[kDecimalRepCapacity];
273#ifndef NDEBUG
274 // Problem: there is an assert in StringBuilder::AddSubstring() that
275 // will pass this buffer to strlen(), and this buffer is not generally
276 // null-terminated.
277 memset(decimal_rep, 0, sizeof(decimal_rep));
278#endif
279 int decimal_rep_length;
280
281 if (requested_digits == -1) {
282 DoubleToAscii(value, SHORTEST, 0,
283 decimal_rep, kDecimalRepCapacity,
284 &sign, &decimal_rep_length, &decimal_point);
285 } else {
286 DoubleToAscii(value, PRECISION, requested_digits + 1,
287 decimal_rep, kDecimalRepCapacity,
288 &sign, &decimal_rep_length, &decimal_point);
289 DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= requested_digits + 1)(void)0;
290
291 for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
292 decimal_rep[i] = '0';
293 }
294 decimal_rep_length = requested_digits + 1;
295 }
296
297 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
298 if (sign && (value != 0.0 || !unique_zero)) {
299 result_builder->AddCharacter('-');
300 }
301
302 int exponent = decimal_point - 1;
303 CreateExponentialRepresentation(decimal_rep,
304 decimal_rep_length,
305 exponent,
306 result_builder);
307 return true;
308}
309
310
311bool DoubleToStringConverter::ToPrecision(double value,
312 int precision,
313 StringBuilder* result_builder) const {
314 if (Double(value).IsSpecial()) {
315 return HandleSpecialValues(value, result_builder);
316 }
317
318 if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
319 return false;
320 }
321
322 // Find a sufficiently precise decimal representation of n.
323 int decimal_point;
324 bool sign;
325 // Add one for the terminating null character.
326 const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
327 char decimal_rep[kDecimalRepCapacity];
328 int decimal_rep_length;
329
330 DoubleToAscii(value, PRECISION, precision,
331 decimal_rep, kDecimalRepCapacity,
332 &sign, &decimal_rep_length, &decimal_point);
333 DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= precision)(void)0;
334
335 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
336 if (sign && (value != 0.0 || !unique_zero)) {
337 result_builder->AddCharacter('-');
338 }
339
340 // The exponent if we print the number as x.xxeyyy. That is with the
341 // decimal point after the first digit.
342 int exponent = decimal_point - 1;
343
344 int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
345 bool as_exponential =
346 (-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
347 (decimal_point - precision + extra_zero >
348 max_trailing_padding_zeroes_in_precision_mode_);
349 if ((flags_ & NO_TRAILING_ZERO) != 0) {
350 // Truncate trailing zeros that occur after the decimal point (if exponential,
351 // that is everything after the first digit).
352 int stop = as_exponential ? 1 : std::max(1, decimal_point);
353 while (decimal_rep_length > stop && decimal_rep[decimal_rep_length - 1] == '0') {
354 --decimal_rep_length;
355 }
356 // Clamp precision to avoid the code below re-adding the zeros.
357 precision = std::min(precision, decimal_rep_length);
358 }
359 if (as_exponential) {
360 // Fill buffer to contain 'precision' digits.
361 // Usually the buffer is already at the correct length, but 'DoubleToAscii'
362 // is allowed to return less characters.
363 for (int i = decimal_rep_length; i < precision; ++i) {
364 decimal_rep[i] = '0';
365 }
366
367 CreateExponentialRepresentation(decimal_rep,
368 precision,
369 exponent,
370 result_builder);
371 } else {
372 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
373 (std::max)(0, precision - decimal_point),
374 result_builder);
375 }
376 return true;
377}
378#endif // not needed for ICU
379
380
381static BignumDtoaMode DtoaToBignumDtoaMode(
382 DoubleToStringConverter::DtoaMode dtoa_mode) {
383 switch (dtoa_mode) {
384 case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
385 case DoubleToStringConverter::SHORTEST_SINGLE:
386 return BIGNUM_DTOA_SHORTEST_SINGLE;
387 case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
388 case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
389 default:
390 DOUBLE_CONVERSION_UNREACHABLE()(abort());
391 }
392}
393
394
395void DoubleToStringConverter::DoubleToAscii(double v,
396 DtoaMode mode,
397 int requested_digits,
398 char* buffer,
399 int buffer_length,
400 bool* sign,
401 int* length,
402 int* point) {
403 Vector<char> vector(buffer, buffer_length);
404 DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial())(void)0;
405 DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0)(void)0;
406
407 if (Double(v).Sign() < 0) {
408 *sign = true;
409 v = -v;
410 } else {
411 *sign = false;
412 }
413
414 if (mode == PRECISION && requested_digits == 0) {
415 vector[0] = '\0';
416 *length = 0;
417 return;
418 }
419
420 if (v == 0) {
421 vector[0] = '0';
422 vector[1] = '\0';
423 *length = 1;
424 *point = 1;
425 return;
426 }
427
428 bool fast_worked;
429 switch (mode) {
430 case SHORTEST:
431 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
432 break;
433#if 0 // not needed for ICU
434 case SHORTEST_SINGLE:
435 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
436 vector, length, point);
437 break;
438 case FIXED:
439 fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
440 break;
441 case PRECISION:
442 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
443 vector, length, point);
444 break;
445#endif // not needed for ICU
446 default:
447 fast_worked = false;
Value stored to 'fast_worked' is never read
448 DOUBLE_CONVERSION_UNREACHABLE()(abort());
449 }
450 if (fast_worked) return;
451
452 // If the fast dtoa didn't succeed use the slower bignum version.
453 BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
454 BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
455 vector[*length] = '\0';
456}
457
458} // namespace double_conversion
459
460// ICU PATCH: Close ICU namespace
461U_NAMESPACE_END}
462#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING