diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index c0fec7e2f..b3491c238 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -335,14 +335,8 @@ unsigned int CppCheck::check(const std::string &path) #endif std::string flags(lang + " "); - if (Path::isCPP(path)) { - if (mSettings.standards.cpp == Standards::CPP14) - flags += "-std=c++14 "; - else if (mSettings.standards.cpp == Standards::CPP17) - flags += "-std=c++17 "; - else if (mSettings.standards.cpp == Standards::CPP20) - flags += "-std=c++20 "; - } + if (Path::isCPP(path) && !mSettings.standards.stdValue.empty()) + flags += "-std=" + mSettings.standards.stdValue + " "; for (const std::string &i: mSettings.includePaths) flags += "-I" + i + " "; @@ -413,12 +407,10 @@ unsigned int CppCheck::check(const ImportProject::FileSettings &fs) temp.mSettings.userDefines += fs.cppcheckDefines(); temp.mSettings.includePaths = fs.includePaths; temp.mSettings.userUndefs = fs.undefs; - if (fs.standard == "c++14") - temp.mSettings.standards.cpp = Standards::CPP14; - else if (fs.standard == "c++17") - temp.mSettings.standards.cpp = Standards::CPP17; - else if (fs.standard == "c++20") - temp.mSettings.standards.cpp = Standards::CPP20; + if (fs.standard.find("++") != std::string::npos) + temp.mSettings.standards.setCPP(fs.standard); + else if (!fs.standard.empty()) + temp.mSettings.standards.setC(fs.standard); if (fs.platformType != Settings::Unspecified) temp.mSettings.platform(fs.platformType); if (mSettings.clang) { diff --git a/lib/standards.h b/lib/standards.h index 00ef313d8..e598b9b6f 100644 --- a/lib/standards.h +++ b/lib/standards.h @@ -38,10 +38,14 @@ struct Standards { /** C++ code standard */ enum cppstd_t { CPP03, CPP11, CPP14, CPP17, CPP20, CPPLatest=CPP20 } cpp; + /** --std value given on command line */ + std::string stdValue; + /** This constructor clear all the variables **/ Standards() : c(C11), cpp(CPPLatest) {} bool setC(const std::string& str) { + stdValue = str; if (str == "c89" || str == "C89") { c = C89; return true; @@ -68,6 +72,7 @@ struct Standards { return ""; } bool setCPP(const std::string& str) { + stdValue = str; if (str == "c++03" || str == "C++03") { cpp = CPP03; return true; @@ -90,7 +95,7 @@ struct Standards { } return false; } - const std::string getCPP() const { + std::string getCPP() const { switch (cpp) { case CPP03: return "c++03"; diff --git a/test/cli/test-clang-import.py b/test/cli/test-clang-import.py new file mode 100644 index 000000000..f1bdbf3de --- /dev/null +++ b/test/cli/test-clang-import.py @@ -0,0 +1,53 @@ + +# python -m pytest test-clang-import.py + +import os +import re +import subprocess +from testutils import create_gui_project_file, cppcheck + + +def get_debug_section(title, stdout): + s = re.sub(r'0x[0-9a-fA-F]+', '0x12345678', stdout) + s = re.sub(r'nestedIn: Struct', 'nestedIn: Class', s) + s = re.sub(r'classDef: struct', 'classDef: class', s) + s = re.sub(r'isInline: [a-z]+', 'isInline: ---', s) + s = re.sub(r'definedType: .*', 'definedType: ---', s) + s = re.sub(r'needInitialization: .*', 'needInitialization: ---', s) + s = re.sub(r'functionOf: .*', 'functionOf: ---', s) + s = re.sub(r'0x12345678 Struct', '0x12345678 Class', s) + pos1 = s.find(title) + assert pos1 > 0 + pos1 = s.find('\n', pos1) + 1 + assert pos1 > 0 + pos2 = s.find("\n##", pos1) + if pos2 < 0: + return s[pos1:] + return s[pos1:pos2-1] + + +def check_symbol_database(code): + # Only compare symboldatabases if clang is found in PATH + try: + subprocess.call(['clang', '--version']) + except OSError: + return + + testfile = 'test.cpp' + with open(testfile, 'w+t') as f: + f.write(code) + ret1, stdout1, stderr1 = cppcheck(['--clang', '--debug', '-v', testfile]) + ret2, stdout2, stderr2 = cppcheck(['--debug', '-v', testfile]) + os.remove(testfile) + assert get_debug_section('### Symbol database', stdout1) == get_debug_section('### Symbol database', stdout2) + + +def test1(): + check_symbol_database('int main(){return 0;}') + +def test2(): + code = 'struct Foo { void f(); }; void Foo::f() {}' + check_symbol_database(code) + + +