Skip to content

Commit 5ff116d

Browse files
authored
fixed #13606/#13607 - consistently print (precise) float as such in ValueFlow debug output (danmar#7274)
1 parent 0593984 commit 5ff116d

File tree

6 files changed

+157
-5
lines changed

6 files changed

+157
-5
lines changed

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ TESTOBJ = test/fixture.o \
335335
test/testutils.o \
336336
test/testvaarg.o \
337337
test/testvalueflow.o \
338-
test/testvarid.o
338+
test/testvarid.o \
339+
test/testvfvalue.o
339340

340341
.PHONY: run-dmake tags
341342

@@ -900,6 +901,9 @@ test/testvalueflow.o: test/testvalueflow.cpp externals/simplecpp/simplecpp.h lib
900901
test/testvarid.o: test/testvarid.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h
901902
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvarid.cpp
902903

904+
test/testvfvalue.o: test/testvfvalue.cpp lib/addoninfo.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/utils.h lib/vfvalue.h test/fixture.h
905+
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvfvalue.cpp
906+
903907
externals/simplecpp/simplecpp.o: externals/simplecpp/simplecpp.cpp externals/simplecpp/simplecpp.h
904908
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ externals/simplecpp/simplecpp.cpp
905909

lib/token.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "astutils.h"
2222
#include "errortypes.h"
2323
#include "library.h"
24+
#include "mathlib.h"
2425
#include "settings.h"
2526
#include "simplecpp.h"
2627
#include "symboldatabase.h"
@@ -1801,7 +1802,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
18011802
break;
18021803
case ValueFlow::Value::ValueType::FLOAT:
18031804
outs += "floatvalue=\"";
1804-
outs += std::to_string(value.floatValue); // TODO: should this be MathLib::toString()?
1805+
outs += MathLib::toString(value.floatValue);
18051806
outs += '\"';
18061807
break;
18071808
case ValueFlow::Value::ValueType::MOVED:
@@ -1875,7 +1876,6 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
18751876

18761877
outs += "/>\n";
18771878
}
1878-
18791879
else {
18801880
if (&value != &values->front())
18811881
outs += ",";

lib/vfvalue.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "vfvalue.h"
2020

2121
#include "errortypes.h"
22+
#include "mathlib.h"
2223
#include "token.h"
2324

2425
#include <sstream>
@@ -58,7 +59,7 @@ namespace ValueFlow {
5859
ss << this->tokvalue->str();
5960
break;
6061
case ValueType::FLOAT:
61-
ss << this->floatValue;
62+
ss << MathLib::toString(this->floatValue);
6263
break;
6364
case ValueType::MOVED:
6465
ss << toString(this->moveKind);

test/cli/other_test.py

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3064,4 +3064,102 @@ def test_file_ignore_2(tmp_path): # #13570
30643064
'cppcheck: error: could not find or open any of the paths given.',
30653065
'cppcheck: Maybe all paths were ignored?'
30663066
]
3067-
assert stderr.splitlines() == []
3067+
assert stderr.splitlines() == []
3068+
3069+
3070+
def test_debug_valueflow(tmp_path):
3071+
test_file = tmp_path / 'test.c'
3072+
with open(test_file, "w") as f:
3073+
f.write(
3074+
"""int f()
3075+
{
3076+
double d = 1.0 / 0.5;
3077+
return d;
3078+
}
3079+
""")
3080+
3081+
args = [
3082+
'-q',
3083+
'--debug', # TODO: limit to valueflow output
3084+
str(test_file)
3085+
]
3086+
3087+
exitcode, stdout, stderr = cppcheck(args)
3088+
assert exitcode == 0, stdout
3089+
3090+
# check sections in output
3091+
assert stdout.find('##file ') != -1
3092+
assert stdout.find('##Value flow') != -1
3093+
assert stdout.find('### Symbol database ###') == -1
3094+
assert stdout.find('##AST') == -1
3095+
assert stdout.find('### Template Simplifier pass ') == -1
3096+
assert stderr.splitlines() == []
3097+
3098+
# check precision in output - #13607
3099+
valueflow = stdout[stdout.find('##Value flow'):]
3100+
assert valueflow.splitlines() == [
3101+
'##Value flow',
3102+
'File {}'.format(str(test_file).replace('\\', '/')),
3103+
'Line 3',
3104+
' = always 2.0',
3105+
' 1.0 always 1.0',
3106+
' / always 2.0',
3107+
' 0.5 always 0.5',
3108+
'Line 4',
3109+
' d always {symbolic=(1.0/0.5),2.0}'
3110+
]
3111+
3112+
3113+
def test_debug_valueflow_xml(tmp_path): # #13606
3114+
test_file = tmp_path / 'test.c'
3115+
with open(test_file, "w") as f:
3116+
f.write(
3117+
"""double f()
3118+
{
3119+
double d = 0.0000001;
3120+
return d;
3121+
}
3122+
""")
3123+
3124+
args = [
3125+
'-q',
3126+
'--debug', # TODO: limit to valueflow output
3127+
'--xml',
3128+
str(test_file)
3129+
]
3130+
3131+
exitcode, stdout, stderr = cppcheck(args)
3132+
assert exitcode == 0, stdout
3133+
3134+
assert stderr
3135+
assert ElementTree.fromstring(stderr) is not None
3136+
3137+
# check sections in output
3138+
assert stdout.find('##file ') != -1 # also exists in CDATA
3139+
assert stdout.find('##Value flow') == -1
3140+
assert stdout.find('### Symbol database ###') == -1
3141+
assert stdout.find('##AST') == -1
3142+
assert stdout.find('### Template Simplifier pass ') == -1
3143+
3144+
# check XML nodes in output
3145+
debug_xml = ElementTree.fromstring(stdout)
3146+
assert debug_xml is not None
3147+
assert debug_xml.tag == 'debug'
3148+
file_elem = debug_xml.findall('file')
3149+
assert len(file_elem) == 1
3150+
valueflow_elem = debug_xml.findall('valueflow')
3151+
assert len(valueflow_elem) == 1
3152+
scopes_elem = debug_xml.findall('scopes')
3153+
assert len(scopes_elem) == 1
3154+
ast_elem = debug_xml.findall('ast')
3155+
assert len(ast_elem) == 0
3156+
3157+
# check precision in output - #13606
3158+
value_elem = valueflow_elem[0].findall('values/value')
3159+
assert len(value_elem) == 3
3160+
assert 'floatvalue' in value_elem[0].attrib
3161+
assert value_elem[0].attrib['floatvalue'] == '1e-07'
3162+
assert 'floatvalue' in value_elem[1].attrib
3163+
assert value_elem[1].attrib['floatvalue'] == '1e-07'
3164+
assert 'floatvalue' in value_elem[2].attrib
3165+
assert value_elem[2].attrib['floatvalue'] == '1e-07'

test/testrunner.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
<ClCompile Include="testvaarg.cpp" />
112112
<ClCompile Include="testvalueflow.cpp" />
113113
<ClCompile Include="testvarid.cpp" />
114+
<ClCompile Include="testvfvalue.cpp" />
114115
</ItemGroup>
115116
<ItemGroup Label="HeaderFiles">
116117
<ClInclude Include="..\cli\cmdlineparser.h" />

test/testvfvalue.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Cppcheck - A tool for static C/C++ code analysis
3+
* Copyright (C) 2007-2024 Cppcheck team.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#include "fixture.h"
20+
#include "vfvalue.h"
21+
22+
class TestValueFlowValue : public TestFixture {
23+
public:
24+
TestValueFlowValue() : TestFixture("TestValueFlowValue") {}
25+
26+
private:
27+
void run() override {
28+
TEST_CASE(toString);
29+
}
30+
31+
void toString() const {
32+
{
33+
ValueFlow::Value v;
34+
ASSERT_EQUALS("0", v.toString());
35+
v.intvalue = -1;
36+
ASSERT_EQUALS("-1", v.toString());
37+
}
38+
{
39+
ValueFlow::Value v;
40+
v.valueType = ValueFlow::Value::ValueType::FLOAT;
41+
ASSERT_EQUALS("0.0", v.toString());
42+
v.floatValue = 0.0000000000001;
43+
ASSERT_EQUALS("1e-13", v.toString());
44+
}
45+
}
46+
};
47+
48+
REGISTER_TEST(TestValueFlowValue)

0 commit comments

Comments
 (0)