Skip to content

Commit

Permalink
added --debug-lookup to log library loading (#6436)
Browse files Browse the repository at this point in the history
  • Loading branch information
firewave committed Jun 11, 2024
1 parent ea2c390 commit 20472f5
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/asan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
# TODO: disable all warnings
- name: CMake
run: |
cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off -DUSE_MATCHCOMPILER=Verify -DANALYZE_ADDRESS=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off -DUSE_MATCHCOMPILER=Verify -DANALYZE_ADDRESS=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
env:
CC: clang-18
CXX: clang++-18
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tsan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
- name: CMake
run: |
cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off -DUSE_MATCHCOMPILER=Verify -DANALYZE_THREAD=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off -DUSE_MATCHCOMPILER=Verify -DANALYZE_THREAD=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
env:
CC: clang-18
CXX: clang++-18
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ubsan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
# TODO: disable warnings
- name: CMake
run: |
cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=ON -DWITH_QCHART=ON -DUSE_MATCHCOMPILER=Verify -DANALYZE_UNDEFINED=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=ON -DWITH_QCHART=ON -DUSE_MATCHCOMPILER=Verify -DANALYZE_UNDEFINED=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DFILESDIR= -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
env:
CC: clang-18
CXX: clang++-18
Expand Down
12 changes: 8 additions & 4 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,10 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
std::strcmp(argv[i], "--debug-normal") == 0)
mSettings.debugnormal = true;

// Show debug warnings for lookup for configuration files
else if (std::strcmp(argv[i], "--debug-lookup") == 0)
mSettings.debuglookup = true;

// Flag used for various purposes during debugging
else if (std::strcmp(argv[i], "--debug-simplified") == 0)
mSettings.debugSimplified = true;
Expand Down Expand Up @@ -1810,9 +1814,9 @@ bool CmdLineParser::isCppcheckPremium() const {
return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium");
}

bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename)
bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename, bool debug)
{
const Library::Error err = destination.load(basepath.c_str(), filename);
const Library::Error err = destination.load(basepath.c_str(), filename, debug);

if (err.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT)
mLogger.printMessage("Found unknown elements in configuration file '" + std::string(filename) + "': " + err.reason); // TODO: print as errors
Expand Down Expand Up @@ -1859,7 +1863,7 @@ bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& base

bool CmdLineParser::loadLibraries(Settings& settings)
{
if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg")) {
if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg", settings.debuglookup)) {
const std::string msg("Failed to load std.cfg. Your Cppcheck installation is broken, please re-install.");
#ifdef FILESDIR
const std::string details("The Cppcheck binary was compiled with FILESDIR set to \""
Expand All @@ -1877,7 +1881,7 @@ bool CmdLineParser::loadLibraries(Settings& settings)

bool result = true;
for (const auto& lib : settings.libraries) {
if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str())) {
if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str(), settings.debuglookup)) {
result = false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmdlineparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class CmdLineParser {
* Tries to load a library and prints warning/error messages
* @return false, if an error occurred (except unknown XML elements)
*/
bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename);
bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename, bool debug);

/**
* @brief Load libraries
Expand Down
40 changes: 32 additions & 8 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,35 +836,50 @@ void MainWindow::addIncludeDirs(const QStringList &includeDirs, Settings &result
}
}

Library::Error MainWindow::loadLibrary(Library &library, const QString &filename)
Library::Error MainWindow::loadLibrary(Library &library, const QString &filename, bool debug)
{
Library::Error ret;

// Try to load the library from the project folder..
if (mProjectFile) {
QString path = QFileInfo(mProjectFile->getFilename()).canonicalPath();
ret = library.load(nullptr, (path+"/"+filename).toLatin1());
QString libpath = path+"/"+filename;
if (debug)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
}

// Try to load the library from the application folder..
const QString appPath = QFileInfo(QCoreApplication::applicationFilePath()).canonicalPath();
ret = library.load(nullptr, (appPath+"/"+filename).toLatin1());
QString libpath = appPath+"/"+filename;
if (debug)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
ret = library.load(nullptr, (appPath+"/cfg/"+filename).toLatin1());
libpath = appPath+"/cfg/"+filename;
if (debug)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;

#ifdef FILESDIR
// Try to load the library from FILESDIR/cfg..
const QString filesdir = FILESDIR;
if (!filesdir.isEmpty()) {
ret = library.load(nullptr, (filesdir+"/cfg/"+filename).toLatin1());
libpath = filesdir+"/cfg/"+filename;
if (debug)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
ret = library.load(nullptr, (filesdir+filename).toLatin1());
libpath = filesdir+filename;
if (debug)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
}
Expand All @@ -873,14 +888,23 @@ Library::Error MainWindow::loadLibrary(Library &library, const QString &filename
// Try to load the library from the cfg subfolder..
const QString datadir = getDataDir();
if (!datadir.isEmpty()) {
ret = library.load(nullptr, (datadir+"/"+filename).toLatin1());
libpath = datadir+"/"+filename;
if (debug)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
ret = library.load(nullptr, (datadir+"/cfg/"+filename).toLatin1());
libpath = datadir+"/cfg/"+filename;
if (debug)
std::cout << "looking for library '" + libpath.toStdString() + "'" << std::endl;
ret = library.load(nullptr, libpath.toLatin1());
if (ret.errorcode != Library::ErrorCode::FILE_NOT_FOUND)
return ret;
}

if (debug)
std::cout << "library not found: '" + filename.toStdString() + "'" << std::endl;

return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion gui/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ private slots:
* @param filename filename (no path)
* @return error code
*/
Library::Error loadLibrary(Library &library, const QString &filename);
Library::Error loadLibrary(Library &library, const QString &filename, bool debug = false);

/**
* @brief Tries to load library file, prints message on error
Expand Down
19 changes: 17 additions & 2 deletions lib/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <cctype>
#include <climits>
#include <cstring>
#include <iostream>
#include <list>
#include <memory>
#include <sstream>
Expand Down Expand Up @@ -65,9 +66,12 @@ static void gettokenlistfromvalid(const std::string& valid, bool cpp, TokenList&
}
}

Library::Error Library::load(const char exename[], const char path[])
Library::Error Library::load(const char exename[], const char path[], bool debug)
{
// TODO: remove handling of multiple libraries at once?
if (std::strchr(path,',') != nullptr) {
if (debug)
std::cout << "handling multiple libraries '" + std::string(path) + "'" << std::endl;
std::string p(path);
for (;;) {
const std::string::size_type pos = p.find(',');
Expand All @@ -86,15 +90,21 @@ Library::Error Library::load(const char exename[], const char path[])
std::string absolute_path;
// open file..
tinyxml2::XMLDocument doc;
if (debug)
std::cout << "looking for library '" + std::string(path) + "'" << std::endl;
tinyxml2::XMLError error = doc.LoadFile(path);
if (error == tinyxml2::XML_ERROR_FILE_READ_ERROR && Path::getFilenameExtension(path).empty())
{
// Reading file failed, try again...
error = tinyxml2::XML_ERROR_FILE_NOT_FOUND;
}
if (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND) {
// failed to open file.. is there no extension?
std::string fullfilename(path);
if (Path::getFilenameExtension(fullfilename).empty()) {
fullfilename += ".cfg";
if (debug)
std::cout << "looking for library '" + std::string(fullfilename) + "'" << std::endl;
error = doc.LoadFile(fullfilename.c_str());
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
absolute_path = Path::getAbsoluteFilePath(fullfilename);
Expand All @@ -116,6 +126,8 @@ Library::Error Library::load(const char exename[], const char path[])
cfgfolders.pop_back();
const char *sep = (!cfgfolder.empty() && endsWith(cfgfolder,'/') ? "" : "/");
const std::string filename(cfgfolder + sep + fullfilename);
if (debug)
std::cout << "looking for library '" + std::string(filename) + "'" << std::endl;
error = doc.LoadFile(filename.c_str());
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
absolute_path = Path::getAbsoluteFilePath(filename);
Expand All @@ -134,10 +146,13 @@ Library::Error Library::load(const char exename[], const char path[])
return Error(ErrorCode::OK); // ignore duplicates
}

if (debug)
std::cout << "library not found: '" + std::string(path) + "'" << std::endl;

if (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND)
return Error(ErrorCode::FILE_NOT_FOUND);

doc.PrintError();
doc.PrintError(); // TODO: do not print stray messages
return Error(ErrorCode::BAD_XML);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class CPPCHECKLIB Library {
std::string reason;
};

Error load(const char exename[], const char path[]);
Error load(const char exename[], const char path[], bool debug = false);

struct AllocFunc {
int groupId;
Expand Down
3 changes: 3 additions & 0 deletions lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {
/** @brief Are we running from DACA script? */
bool daca{};

/** @brief Internal: Is --debug-lookup given? */
bool debuglookup{};

/** @brief Is --debug-normal given? */
bool debugnormal{};

Expand Down
98 changes: 76 additions & 22 deletions test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,24 @@
import pytest
import json

from testutils import cppcheck, assert_cppcheck
from testutils import cppcheck, assert_cppcheck, cppcheck_ex


def __remove_std_lookup_log(l : list, exepath):
print(l)
l.remove("looking for library 'std.cfg'")
l.remove("looking for library '{}/std.cfg'".format(exepath))
l.remove("looking for library '{}/../cfg/std.cfg'".format(exepath))
l.remove("looking for library '{}/cfg/std.cfg'".format(exepath))
return l


def __remove_verbose_log(l : list):
l.remove('Defines:')
l.remove('Undefines:')
l.remove('Includes:')
l.remove('Platform:native')
return l


def test_missing_include(tmpdir): # #11283
Expand Down Expand Up @@ -452,13 +469,9 @@ class _clz {

exitcode, stdout, stderr = cppcheck(args)
assert exitcode == 0
lines = stdout.splitlines()
lines = __remove_verbose_log(stdout.splitlines())
assert lines == [
'Checking {} ...'.format(test_file),
'Defines:',
'Undefines:',
'Includes:',
'Platform:native'
'Checking {} ...'.format(test_file)
]
lines = [line for line in stderr.splitlines() if line != '']
expect = [
Expand Down Expand Up @@ -585,13 +598,9 @@ def test_addon_namingng_config(tmpdir):
exitcode, stdout, stderr = cppcheck(args)
assert exitcode == 0

lines = stdout.splitlines()
lines = __remove_verbose_log(stdout.splitlines())
assert lines == [
'Checking {} ...'.format(test_file),
'Defines:',
'Undefines:',
'Includes:',
'Platform:native'
'Checking {} ...'.format(test_file)
]
lines = stderr.splitlines()
# ignore the first line, stating that the addon failed to run properly
Expand Down Expand Up @@ -725,13 +734,9 @@ def test_invalid_addon_py_verbose(tmpdir):

exitcode, stdout, stderr = cppcheck(args)
assert exitcode == 0 # TODO: needs to be 1
lines = stdout.splitlines()
lines = __remove_verbose_log(stdout.splitlines())
assert lines == [
'Checking {} ...'.format(test_file),
'Defines:',
'Undefines:',
'Includes:',
'Platform:native'
'Checking {} ...'.format(test_file)
]
"""
/tmp/pytest-of-user/pytest-11/test_invalid_addon_py_20/file.cpp:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon 'addon1' - exitcode is 1: python3 /home/user/CLionProjects/cppcheck/addons/runaddon.py /tmp/pytest-of-user/pytest-11/test_invalid_addon_py_20/addon1.py --cli /tmp/pytest-of-user/pytest-11/test_invalid_addon_py_20/file.cpp.24762.dump
Expand Down Expand Up @@ -1497,13 +1502,17 @@ def test_cpp_probe(tmpdir):
])

args = ['-q', '--template=simple', '--cpp-header-probe', '--verbose', test_file]
err_lines = [

exitcode, stdout, stderr = cppcheck(args)
assert exitcode == 0, stdout
lines = stdout.splitlines()
assert lines == []
lines = stderr.splitlines()
assert lines == [
# TODO: fix that awkward format
"{}:1:1: error: Code 'classA{{' is invalid C code.: Use --std, -x or --language to enforce C++. Or --cpp-header-probe to identify C++ headers via the Emacs marker. [syntaxError]".format(test_file)
]

assert_cppcheck(args, ec_exp=0, err_exp=err_lines, out_exp=[])


def test_cpp_probe_2(tmpdir):
test_file = os.path.join(tmpdir, 'test.h')
Expand All @@ -1516,3 +1525,48 @@ def test_cpp_probe_2(tmpdir):
args = ['-q', '--template=simple', '--cpp-header-probe', test_file]

assert_cppcheck(args, ec_exp=0, err_exp=[], out_exp=[])


# TODO: test with FILESDIR
def test_lib_lookup(tmpdir):
test_file = os.path.join(tmpdir, 'test.c')
with open(test_file, 'wt'):
pass

exitcode, stdout, _, exe = cppcheck_ex(['--library=gnu', '--debug-lookup', test_file])
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 0, stdout
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
assert lines == [
"looking for library 'gnu'",
"looking for library 'gnu.cfg'",
"looking for library '{}/gnu.cfg'".format(exepath),
"looking for library '{}/../cfg/gnu.cfg'".format(exepath),
"looking for library '{}/cfg/gnu.cfg'".format(exepath),
'Checking {} ...'.format(test_file)
]


# TODO: test with FILESDIR
def test_lib_lookup_notfound(tmpdir):
test_file = os.path.join(tmpdir, 'test.c')
with open(test_file, 'wt'):
pass

exitcode, stdout, _, exe = cppcheck_ex(['--library=none', '--debug-lookup', test_file])
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 1, stdout
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
assert lines == [
"looking for library 'none'",
"looking for library 'none.cfg'",
"looking for library '{}/none.cfg'".format(exepath),
"looking for library '{}/../cfg/none.cfg'".format(exepath),
"looking for library '{}/cfg/none.cfg'".format(exepath),
"library not found: 'none'",
"cppcheck: Failed to load library configuration file 'none'. File not found"
]
Loading

0 comments on commit 20472f5

Please sign in to comment.