Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 1 addition & 1 deletion .github/workflows/selfcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:

- name: Self check (unusedFunction / no test / no gui)
run: |
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1671 --suppress=unusedFunction:lib/importproject.cpp:1695"
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1695 --suppress=unusedFunction:lib/importproject.cpp:1719"
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs
env:
DISABLE_VALUEFLOW: 1
Expand Down
46 changes: 35 additions & 11 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,27 +529,51 @@ bool ImportProject::importSlnx(const std::string& filename, const std::vector<st
return false;
}

if (std::strcmp(rootnode->Name(), "Solution") != 0) {
errors.emplace_back("Invalid Visual Studio solution file format");
return false;
}

std::map<std::string, std::string, cppcheck::stricmp> variables;
variables["SolutionDir"] = Path::simplifyPath(Path::getPathFromFilename(filename));

bool found = false;
std::vector<SharedItemsProject> sharedItemsProjects;

auto processProject = [&](const tinyxml2::XMLElement* projectNode) {
const char* pathAttribute = projectNode->Attribute("Path");
if (pathAttribute == nullptr)
return true;

std::string vcxproj(pathAttribute);
vcxproj = Path::toNativeSeparators(std::move(vcxproj));

if (Path::getFilenameExtensionInLowerCase(vcxproj) != ".vcxproj")
return true; // skip other project types

if (!Path::isAbsolute(vcxproj))
vcxproj = variables["SolutionDir"] + vcxproj;

vcxproj = Path::fromNativeSeparators(std::move(vcxproj));
if (!importVcxproj(vcxproj, variables, "", fileFilters, sharedItemsProjects)) {
errors.emplace_back("failed to load '" + vcxproj + "' from Visual Studio solution");
return false;
}
found = true;
return true;
};

for (const tinyxml2::XMLElement* node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
const char* name = node->Name();
if (std::strcmp(name, "Project") == 0) {
const char* labelAttribute = node->Attribute("Path");
if (labelAttribute) {
std::string vcxproj(labelAttribute);
vcxproj = Path::toNativeSeparators(std::move(vcxproj));
if (!Path::isAbsolute(vcxproj))
vcxproj = variables["SolutionDir"] + vcxproj;
vcxproj = Path::fromNativeSeparators(std::move(vcxproj));
if (!importVcxproj(vcxproj, variables, "", fileFilters, sharedItemsProjects)) {
errors.emplace_back("failed to load '" + vcxproj + "' from Visual Studio solution");
return false;
if (!processProject(node))
return false;
} else if (std::strcmp(name, "Folder") == 0) {
for (const tinyxml2::XMLElement* childNode = node->FirstChildElement(); childNode; childNode = childNode->NextSiblingElement()) {
if (std::strcmp(childNode->Name(), "Project") == 0) {
if (!processProject(childNode))
return false;
}
found = true;
}
}
}
Expand Down
46 changes: 46 additions & 0 deletions test/cli/project_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,16 @@ def test_slnx_no_xml_root(tmpdir):
__test_project_error(tmpdir, "slnx", content, expected)


def test_slnx_invalid_xml_root(tmpdir):
content = '<?xml version="1.0" encoding="UTF-8"?>\r\n' \
"<Invalid>\r\n" \
"</Invalid>\r\n"

expected = "Invalid Visual Studio solution file format"

__test_project_error(tmpdir, "slnx", content, expected)


def test_slnx_no_projects(tmpdir):
content = '<?xml version="1.0" encoding="UTF-8"?>\r\n' \
"<Solution>\r\n" \
Expand All @@ -161,6 +171,22 @@ def test_slnx_no_projects(tmpdir):
__test_project_error(tmpdir, "slnx", content, expected)


def test_slnx_no_projects_in_folder(tmpdir):
content = '<?xml version="1.0" encoding="UTF-8"?>\r\n' \
"<Solution>\r\n" \
" <Configurations>\r\n" \
' <Platform Name="x64" />\r\n' \
' <Platform Name="x86" />\r\n' \
" </Configurations>\r\n" \
' <Folder Name="/common/">\r\n' \
' </Folder>\r\n' \
"</Solution>\r\n"

expected = "no projects found in Visual Studio solution file"

__test_project_error(tmpdir, "slnx", content, expected)


def test_slnx_project_file_not_found(tmpdir):
content = '<?xml version="1.0" encoding="UTF-8"?>\r\n' \
"<Solution>\r\n" \
Expand All @@ -179,6 +205,26 @@ def test_slnx_project_file_not_found(tmpdir):
__test_project_error(tmpdir, "slnx", content, expected)


def test_slnx_project_file_in_folder_not_found(tmpdir):
content = '<?xml version="1.0" encoding="UTF-8"?>\r\n' \
"<Solution>\r\n" \
" <Configurations>\r\n" \
' <Platform Name="x64" />\r\n' \
' <Platform Name="x86" />\r\n' \
" </Configurations>\r\n" \
' <Folder Name="/common/">\r\n' \
' <Project Path="common/test.vcxproj" />\r\n' \
' </Folder>\r\n' \
"</Solution>\r\n"

expected = "Visual Studio project file is not a valid XML - XML_ERROR_FILE_NOT_FOUND\n" \
"cppcheck: error: failed to load '{}' from Visual Studio solution".format(os.path.join(tmpdir, "common/test.vcxproj"))
if sys.platform == "win32":
expected = expected.replace('\\', '/')

__test_project_error(tmpdir, "slnx", content, expected)


def test_vcxproj_no_xml_root(tmpdir):
content = '<?xml version="1.0" encoding="utf-8"?>'

Expand Down
7 changes: 7 additions & 0 deletions test/cli/slnx-folders/app/app.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "../lib/lib.h"

int main(int argc, char *argv[])
{
int x = 3 / 0; (void)x; // ERROR
return foo();
}
102 changes: 102 additions & 0 deletions test/cli/slnx-folders/app/app.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?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>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>18.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{0de77c38-881a-4f9f-bdfa-2c429968985e}</ProjectGuid>
<RootNamespace>unused</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>..\x64\Debug\</OutDir>
<IntDir>x64\Debug\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>..\x64\Release\</OutDir>
<IntDir>x64\Release\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>../lib</AdditionalLibraryDirectories>
</Link>
<Manifest>
<EnableSegmentHeap>true</EnableSegmentHeap>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Manifest>
<EnableSegmentHeap>true</EnableSegmentHeap>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="app.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\lib\lib.vcxproj">
<Project>{93BE1430-BE74-35DF-1882-AF70E49C9898}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
9 changes: 9 additions & 0 deletions test/cli/slnx-folders/lib/lib.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <iostream>
#include "lib.h"

int foo()
{
std::cout << "hello world\n";
int x = 3 / 0; (void)x; // ERROR
return 0;
}
1 change: 1 addition & 0 deletions test/cli/slnx-folders/lib/lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extern int foo();
97 changes: 97 additions & 0 deletions test/cli/slnx-folders/lib/lib.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?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>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>18.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{93BE1430-BE74-35DF-1882-AF70E49C9898}</ProjectGuid>
<RootNamespace>unused</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>..\x64\Debug\</OutDir>
<IntDir>x64\Debug\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>..\x64\Release\</OutDir>
<IntDir>x64\Release\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>../lib</AdditionalLibraryDirectories>
</Link>
<Manifest>
<EnableSegmentHeap>true</EnableSegmentHeap>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Manifest>
<EnableSegmentHeap>true</EnableSegmentHeap>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="lib.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
17 changes: 17 additions & 0 deletions test/cli/slnx-folders/slnx-folders.cppcheck
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="1">
<builddir>slnx-folders-cppcheck-build-dir</builddir>
<importproject>slnx-folders.slnx</importproject>
<analyze-all-vs-configs>false</analyze-all-vs-configs>
<check-headers>true</check-headers>
<check-unused-templates>true</check-unused-templates>
<inline-suppression>true</inline-suppression>
<max-ctu-depth>2</max-ctu-depth>
<max-template-recursion>100</max-template-recursion>
<vs-configurations>
<config>Debug</config>
<config>Release</config>
</vs-configurations>
<check-level-normal/>
<project-name>slnx-folders</project-name>
</project>
12 changes: 12 additions & 0 deletions test/cli/slnx-folders/slnx-folders.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Solution>
<Configurations>
<Platform Name="x64" />
</Configurations>
<Folder Name="/Lib/">
<File Path="lib/lib.h" />
<Project Path="lib\lib.vcxproj" />
</Folder>
<Folder Name="/App/">
<Project Path="app\app.vcxproj" Id="0de77c38-881a-4f9f-bdfa-2c429968985e" />
</Folder>
</Solution>
Loading
Loading