Skip to content
Open
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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ $(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/analyzer.h lib/astut
$(libcppdir)/fwdanalysis.o: lib/fwdanalysis.cpp lib/astutils.h lib/checkers.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/fwdanalysis.cpp

$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/checkers.h lib/config.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/smallvector.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h
$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/checkers.h lib/config.h lib/filesettings.h lib/importproject.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/importproject.cpp

$(libcppdir)/infer.o: lib/infer.cpp lib/calculate.h lib/config.h lib/errortypes.h lib/infer.h lib/mathlib.h lib/smallvector.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueptr.h lib/vfvalue.h
Expand Down Expand Up @@ -819,7 +819,7 @@ test/testfunctions.o: test/testfunctions.cpp lib/check.h lib/checkers.h lib/chec
test/testgarbage.o: test/testgarbage.cpp lib/check.h lib/checkers.h lib/checks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.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} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testgarbage.cpp

test/testimportproject.o: test/testimportproject.cpp externals/tinyxml2/tinyxml2.h lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h test/fixture.h test/redirect.h
test/testimportproject.o: test/testimportproject.cpp lib/check.h lib/checkers.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h test/redirect.h
$(CXX) ${INCLUDE_FOR_TEST} ${CFLAGS_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testimportproject.cpp

test/testincompletestatement.o: test/testincompletestatement.cpp lib/check.h lib/checkers.h lib/checkimpl.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h
Expand Down
1,853 changes: 1,297 additions & 556 deletions lib/importproject.cpp

Large diffs are not rendered by default.

83 changes: 67 additions & 16 deletions lib/importproject.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
#include <map>
#include <set>
#include <string>
#include <unordered_set>
#include <vector>

class Settings;
struct Suppressions;

namespace tinyxml2 {
class XMLDocument;
class XMLElement;
}

/// @addtogroup Core
Expand All @@ -56,11 +58,14 @@ namespace cppcheck {
}
}

using VariablesMap = std::map<std::string, std::string, cppcheck::stricmp>;

/**
* @brief Importing project settings.
*/
class CPPCHECKLIB WARN_UNUSED ImportProject {
public:

enum class Type : std::uint8_t {
NONE,
UNKNOWN,
Expand All @@ -73,14 +78,22 @@ class CPPCHECKLIB WARN_UNUSED ImportProject {
BORLAND,
CPPCHECK_GUI
};
enum class ImportResult : std::uint8_t {
Ok,
NotResolvable,
NotFound,
NotValid,
Cycle
};

protected:
static void fsSetDefines(FileSettings& fs, std::string defs);
static void fsSetIncludePaths(FileSettings& fs, const std::string &basepath, const std::list<std::string> &in, std::map<std::string, std::string, cppcheck::stricmp> &variables);
void fsSetIncludePaths(FileSettings& fs, const std::string &basepath, const std::list<std::string> &in, VariablesMap &variables);

public:
std::list<FileSettings> fileSettings;
std::vector<std::string> errors;
std::vector<std::string> debugs;

ImportProject() = default;
virtual ~ImportProject() = default;
Expand All @@ -106,29 +119,71 @@ class CPPCHECKLIB WARN_UNUSED ImportProject {
void ignoreOtherConfigs(const std::string &cfg);

Type import(const std::string &filename, Settings *settings=nullptr, Suppressions *supprs=nullptr);

static const std::string &importResultStr(ImportResult result);

protected:
bool importCompileCommands(std::istream &istr);
bool importCppcheckGuiProject(std::istream &istr, Settings &settings, Suppressions &supprs);
static std::string collectArgs(const std::string &cmd, std::vector<std::string> &args);
void setRelativePaths(const std::string &filename);

struct SharedItemsProject {
bool successful = false;
std::string pathToProjectFile;
std::vector<std::string> includePaths;
std::vector<std::string> sourceFiles;
};
VariablesMap mVariables;

bool importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters, std::vector<SharedItemsProject> &cache);
bool importVcxproj(const std::string &filename, const tinyxml2::XMLDocument &doc, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters, std::vector<SharedItemsProject> &cache);

private:
static void parseArgs(FileSettings &fs, const std::vector<std::string> &args);

bool importBcb6Prj(const std::string &projectFilename);

struct ProjectConfiguration {
explicit ProjectConfiguration(const tinyxml2::XMLElement *cfg);

std::string name;
std::string configuration;
enum : std::uint8_t { Win32, x64, Unknown } platform = Unknown;
std::string platformStr;
};

struct ItemGroupClCompile {
explicit ItemGroupClCompile(std::string filename) : filename(std::move(filename)) {}
std::string filename;
std::string additionalIncludeDirectories;
std::string forcedIncludeFiles;
std::string preprocessorDefinitions;
std::string languageStandard;
};

bool importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters);
bool importSlnx(const std::string& filename, const std::vector<std::string>& fileFilters);
SharedItemsProject importVcxitems(const std::string &filename, const std::vector<std::string> &fileFilters, std::vector<SharedItemsProject> &cache);
bool importBcb6Prj(const std::string &projectFilename);
bool importVcxproj(const std::string &filename, VariablesMap &variables, const std::vector<std::string> &fileFilters);

ImportResult importPropsOrTargets(const std::string &file,
VariablesMap &variables,
std::list<ProjectConfiguration> &projectConfigurationList,
std::unordered_set<std::string> &importStack);
ImportResult importVcxitems(const std::string &items,
VariablesMap &variables,
std::list<ItemGroupClCompile> &compileList,
std::list<ProjectConfiguration> &projectConfigurationList,
std::unordered_set<std::string> &importStack);
ImportResult importProject(const tinyxml2::XMLElement *node,
const std::string &projectDir,
VariablesMap &variables,
std::list<ProjectConfiguration> &projectConfigurationList,
std::unordered_set<std::string> &importStack);
ImportResult importCompile(const tinyxml2::XMLElement *node,
const std::string &projectDir,
VariablesMap &variables,
std::list<ItemGroupClCompile> &compileList);
void checkUnexpandedExpressions(const std::string &text, const char *context);
bool simplifyPathWithVariables(std::string &s, VariablesMap &variables);
void addProperty(const tinyxml2::XMLElement *node, VariablesMap &variables);
std::string getProperty(const tinyxml2::XMLElement *node, VariablesMap &variables, const std::string &original);
std::string toAbsolute(const std::string &filename, const std::string &baseDir, VariablesMap &variables);
static std::string toAbsolute(const std::string &path);
static void setSolution(const std::string &filename, VariablesMap &variables);


std::string mPath;
std::set<std::string> mAllVSConfigs;
Expand Down Expand Up @@ -201,10 +256,6 @@ namespace CppcheckXml {
static constexpr char ProjectNameElementName[] = "project-name";
}

namespace testing
{
CPPCHECKLIB bool evaluateVcxprojCondition(const std::string& condition, const std::string& configuration, const std::string& platform);
}
/// @}
//---------------------------------------------------------------------------
#endif // importprojectH
2 changes: 1 addition & 1 deletion oss-fuzz/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ $(libcppdir)/forwardanalyzer.o: ../lib/forwardanalyzer.cpp ../lib/analyzer.h ../
$(libcppdir)/fwdanalysis.o: ../lib/fwdanalysis.cpp ../lib/astutils.h ../lib/checkers.h ../lib/config.h ../lib/errortypes.h ../lib/fwdanalysis.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/utils.h ../lib/vfvalue.h
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/fwdanalysis.cpp

$(libcppdir)/importproject.o: ../lib/importproject.cpp ../externals/picojson/picojson.h ../externals/tinyxml2/tinyxml2.h ../lib/checkers.h ../lib/config.h ../lib/errortypes.h ../lib/filesettings.h ../lib/importproject.h ../lib/json.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/pathmatch.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/standards.h ../lib/suppressions.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h
$(libcppdir)/importproject.o: ../lib/importproject.cpp ../externals/picojson/picojson.h ../externals/tinyxml2/tinyxml2.h ../lib/checkers.h ../lib/config.h ../lib/filesettings.h ../lib/importproject.h ../lib/json.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/pathmatch.h ../lib/platform.h ../lib/settings.h ../lib/standards.h ../lib/suppressions.h ../lib/utils.h ../lib/xml.h
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/importproject.cpp

$(libcppdir)/infer.o: ../lib/infer.cpp ../lib/calculate.h ../lib/config.h ../lib/errortypes.h ../lib/infer.h ../lib/mathlib.h ../lib/smallvector.h ../lib/templatesimplifier.h ../lib/token.h ../lib/utils.h ../lib/valueptr.h ../lib/vfvalue.h
Expand Down
9 changes: 7 additions & 2 deletions test/cli/proj2_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
'x = 3 / 0;\n' +
' ^\n') % os.path.join('b', 'b.c')

def __get_lines(s):
# file order is not guaranteed when multiple jobs are used (TEST_CPPCHECK_INJECT_J) so
# compare output order-independently
return sorted(s.split('\n'))

def __create_compile_commands(proj_dir):
proj_dir = str(proj_dir)
j = [{'directory': os.path.join(proj_dir, 'a'), 'command': 'gcc -c a.c', 'file': 'a.c'},
Expand Down Expand Up @@ -152,7 +157,7 @@ def test_gui_project_loads_relative_vs_solution_2(tmp_path):
create_gui_project_file(os.path.join(tmp_path, 'test.cppcheck'), root_path='proj2', import_project='proj2/proj2.sln')
ret, stdout, stderr = cppcheck(['--project=test.cppcheck'], cwd=tmp_path)
assert ret == 0, stdout
assert stderr == __ERR_A + __ERR_B
assert __get_lines(stderr) == __get_lines(__ERR_A + __ERR_B)

def test_gui_project_loads_relative_vs_solution_with_exclude(tmp_path):
proj_dir = tmp_path / 'proj2'
Expand All @@ -170,4 +175,4 @@ def test_gui_project_loads_absolute_vs_solution_2(tmp_path):
import_project=os.path.join(proj_dir, 'proj2.sln'))
ret, stdout, stderr = cppcheck(['--project=test.cppcheck'], cwd=tmp_path)
assert ret == 0, stdout
assert stderr == __ERR_A + __ERR_B
assert __get_lines(stderr) == __get_lines(__ERR_A + __ERR_B)
32 changes: 32 additions & 0 deletions test/cli/props-dirs/ProjA/ProjA.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{a1a1a1a1-a1a1-a1a1-a1a1-a1a1a1a1a1a1}</ProjectGuid>
<RootNamespace>ProjA</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<!-- Pulls in shared/shared.props, which itself pulls in common/common.props -->
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(MSBuildThisFileDirectory)..\shared\shared.props" />
</ImportGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>PROJA_DEFINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="a.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
11 changes: 11 additions & 0 deletions test/cli/props-dirs/ProjA/a.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "common.h"

#ifndef COMMON_H_INCLUDED_MARKER
#error "common.h was not found - AdditionalIncludeDirectories from common.props did not resolve"
#endif

int main()
{
int x = 1;
return x / 0;
}
29 changes: 29 additions & 0 deletions test/cli/props-dirs/ProjB/ProjB.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{b2b2b2b2-b2b2-b2b2-b2b2-b2b2b2b2b2b2}</ProjectGuid>
<RootNamespace>ProjB</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<!-- Imports common/common.props DIRECTLY - does NOT go through shared/shared.props.
Must NOT see PROJA_DEFINE or SHARED_DEFINE from ProjA, which is processed first
in the same solution (regression coverage for the mVariables cross-project leak). -->
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(MSBuildThisFileDirectory)..\common\common.props" />
</ImportGroup>
<ItemGroup>
<ClCompile Include="b.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
11 changes: 11 additions & 0 deletions test/cli/props-dirs/ProjB/b.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "common.h"

#ifndef COMMON_H_INCLUDED_MARKER
#error "common.h was not found - AdditionalIncludeDirectories from common.props did not resolve"
#endif

int main()
{
int y = 2;
return y / 0;
}
3 changes: 3 additions & 0 deletions test/cli/props-dirs/common/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#ifndef COMMON_H_INCLUDED_MARKER
#define COMMON_H_INCLUDED_MARKER
#endif
13 changes: 13 additions & 0 deletions test/cli/props-dirs/common/common.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Imported from both ProjA (indirectly, via shared/shared.props) and ProjB (directly).
AdditionalIncludeDirectories uses $(MSBuildThisFileDirectory) to prove it resolves to
this file's own directory (common/) rather than to whichever project imported it. -->
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>COMMON_DEFINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
</Project>
7 changes: 7 additions & 0 deletions test/cli/props-dirs/props-dirs.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Solution>
<Configurations>
<Platform Name="x64" />
</Configurations>
<Project Path="ProjA/ProjA.vcxproj" Id="a1a1a1a1-a1a1-a1a1-a1a1-a1a1a1a1a1a1" />
<Project Path="ProjB/ProjB.vcxproj" Id="b2b2b2b2-b2b2-b2b2-b2b2-b2b2b2b2b2b2" />
</Solution>
14 changes: 14 additions & 0 deletions test/cli/props-dirs/shared/shared.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Only imported by ProjA. Chains into common/common.props via a relative,
$(MSBuildThisFileDirectory)-based path - this is the cross-directory nested
props-importing-props case (ProjA/ -> shared/ -> common/). -->
<ImportGroup Label="PropertySheets">
<Import Project="$(MSBuildThisFileDirectory)..\common\common.props" />
</ImportGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>SHARED_DEFINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>
Loading
Loading