Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed #13606/#13607 - consistently print (precise) float as such in ValueFlow debug output #7274

Merged
merged 3 commits into from
Feb 13, 2025
Merged
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
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,8 @@ TESTOBJ = test/fixture.o \
test/testutils.o \
test/testvaarg.o \
test/testvalueflow.o \
test/testvarid.o
test/testvarid.o \
test/testvfvalue.o

.PHONY: run-dmake tags

Expand Down Expand Up @@ -900,6 +901,9 @@ test/testvalueflow.o: test/testvalueflow.cpp externals/simplecpp/simplecpp.h lib
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
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvarid.cpp

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
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testvfvalue.cpp

externals/simplecpp/simplecpp.o: externals/simplecpp/simplecpp.cpp externals/simplecpp/simplecpp.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ externals/simplecpp/simplecpp.cpp

Expand Down
4 changes: 2 additions & 2 deletions lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "astutils.h"
#include "errortypes.h"
#include "library.h"
#include "mathlib.h"
#include "settings.h"
#include "simplecpp.h"
#include "symboldatabase.h"
Expand Down Expand Up @@ -1801,7 +1802,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
break;
case ValueFlow::Value::ValueType::FLOAT:
outs += "floatvalue=\"";
outs += std::to_string(value.floatValue); // TODO: should this be MathLib::toString()?
outs += MathLib::toString(value.floatValue);
outs += '\"';
break;
case ValueFlow::Value::ValueType::MOVED:
Expand Down Expand Up @@ -1875,7 +1876,6 @@ void Token::printValueFlow(bool xml, std::ostream &out) const

outs += "/>\n";
}

else {
if (&value != &values->front())
outs += ",";
Expand Down
3 changes: 2 additions & 1 deletion lib/vfvalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "vfvalue.h"

#include "errortypes.h"
#include "mathlib.h"
#include "token.h"

#include <sstream>
Expand Down Expand Up @@ -58,7 +59,7 @@ namespace ValueFlow {
ss << this->tokvalue->str();
break;
case ValueType::FLOAT:
ss << this->floatValue;
ss << MathLib::toString(this->floatValue);
break;
case ValueType::MOVED:
ss << toString(this->moveKind);
Expand Down
100 changes: 99 additions & 1 deletion test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3064,4 +3064,102 @@ def test_file_ignore_2(tmp_path): # #13570
'cppcheck: error: could not find or open any of the paths given.',
'cppcheck: Maybe all paths were ignored?'
]
assert stderr.splitlines() == []
assert stderr.splitlines() == []


def test_debug_valueflow(tmp_path):
test_file = tmp_path / 'test.c'
with open(test_file, "w") as f:
f.write(
"""int f()
{
double d = 1.0 / 0.5;
return d;
}
""")

args = [
'-q',
'--debug', # TODO: limit to valueflow output
str(test_file)
]

exitcode, stdout, stderr = cppcheck(args)
assert exitcode == 0, stdout

# check sections in output
assert stdout.find('##file ') != -1
assert stdout.find('##Value flow') != -1
assert stdout.find('### Symbol database ###') == -1
assert stdout.find('##AST') == -1
assert stdout.find('### Template Simplifier pass ') == -1
assert stderr.splitlines() == []

# check precision in output - #13607
valueflow = stdout[stdout.find('##Value flow'):]
assert valueflow.splitlines() == [
'##Value flow',
'File {}'.format(str(test_file).replace('\\', '/')),
'Line 3',
' = always 2.0',
' 1.0 always 1.0',
' / always 2.0',
' 0.5 always 0.5',
'Line 4',
' d always {symbolic=(1.0/0.5),2.0}'
]


def test_debug_valueflow_xml(tmp_path): # #13606
test_file = tmp_path / 'test.c'
with open(test_file, "w") as f:
f.write(
"""double f()
{
double d = 0.0000001;
return d;
}
""")

args = [
'-q',
'--debug', # TODO: limit to valueflow output
'--xml',
str(test_file)
]

exitcode, stdout, stderr = cppcheck(args)
assert exitcode == 0, stdout

assert stderr
assert ElementTree.fromstring(stderr) is not None

# check sections in output
assert stdout.find('##file ') != -1 # also exists in CDATA
assert stdout.find('##Value flow') == -1
assert stdout.find('### Symbol database ###') == -1
assert stdout.find('##AST') == -1
assert stdout.find('### Template Simplifier pass ') == -1

# check XML nodes in output
debug_xml = ElementTree.fromstring(stdout)
assert debug_xml is not None
assert debug_xml.tag == 'debug'
file_elem = debug_xml.findall('file')
assert len(file_elem) == 1
valueflow_elem = debug_xml.findall('valueflow')
assert len(valueflow_elem) == 1
scopes_elem = debug_xml.findall('scopes')
assert len(scopes_elem) == 1
ast_elem = debug_xml.findall('ast')
assert len(ast_elem) == 0

# check precision in output - #13606
value_elem = valueflow_elem[0].findall('values/value')
assert len(value_elem) == 3
assert 'floatvalue' in value_elem[0].attrib
assert value_elem[0].attrib['floatvalue'] == '1e-07'
assert 'floatvalue' in value_elem[1].attrib
assert value_elem[1].attrib['floatvalue'] == '1e-07'
assert 'floatvalue' in value_elem[2].attrib
assert value_elem[2].attrib['floatvalue'] == '1e-07'
1 change: 1 addition & 0 deletions test/testrunner.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
<ClCompile Include="testvaarg.cpp" />
<ClCompile Include="testvalueflow.cpp" />
<ClCompile Include="testvarid.cpp" />
<ClCompile Include="testvfvalue.cpp" />
</ItemGroup>
<ItemGroup Label="HeaderFiles">
<ClInclude Include="..\cli\cmdlineparser.h" />
Expand Down
48 changes: 48 additions & 0 deletions test/testvfvalue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2024 Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "fixture.h"
#include "vfvalue.h"

class TestValueFlowValue : public TestFixture {
public:
TestValueFlowValue() : TestFixture("TestValueFlowValue") {}

private:
void run() override {
TEST_CASE(toString);
}

void toString() const {
{
ValueFlow::Value v;
ASSERT_EQUALS("0", v.toString());
v.intvalue = -1;
ASSERT_EQUALS("-1", v.toString());
}
{
ValueFlow::Value v;
v.valueType = ValueFlow::Value::ValueType::FLOAT;
ASSERT_EQUALS("0.0", v.toString());
v.floatValue = 0.0000000000001;
ASSERT_EQUALS("1e-13", v.toString());
}
}
};

REGISTER_TEST(TestValueFlowValue)
Loading