diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 9a896eb9e..010f15e2c 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -438,15 +438,16 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) // --std else if (strcmp(argv[i], "--std=posix") == 0) { _settings->standards.posix = true; - } - - // --C99 - else if (strcmp(argv[i], "--std=c99") == 0) { - _settings->standards.c99 = true; - } - - else if (strcmp(argv[i], "--std=c++11") == 0) { - _settings->standards.cpp11 = true; + } else if (strcmp(argv[i], "--std=c89") == 0) { + _settings->standards.c = Standards::C89; + } else if (strcmp(argv[i], "--std=c99") == 0) { + _settings->standards.c = Standards::C99; + } else if (strcmp(argv[i], "--std=c11") == 0) { + _settings->standards.c = Standards::C11; + } else if (strcmp(argv[i], "--std=c++03") == 0) { + _settings->standards.cpp = Standards::CPP03; + } else if (strcmp(argv[i], "--std=c++11") == 0) { + _settings->standards.cpp = Standards::CPP11; } // Output formatter @@ -792,16 +793,22 @@ void CmdLineParser::PrintHelp() const " --rule-file= Use given rule file. For more information, see: \n" " https://sourceforge.net/projects/cppcheck/files/Articles/\n" #endif - " --std= Enable some standard related checks.\n" + " --std= Set standard.\n" " The available options are:\n" " * posix\n" - " Checks related to POSIX-specific functionality\n" + " POSIX compatible code\n" + " * c89\n" + " C code is C89 compatible\n" " * c99\n" - " C99 standard related checks\n" + " C code is C99 compatible\n" + " * c11\n" + " C code is C11 compatible (default)\n" + " * c++03\n" + " C++ code is C++03 compatible\n" " * c++11\n" - " C++11 standard related checks\n" - " Example to enable more than one checks:\n" - " 'cppcheck --std=c99 --std=posix file.cpp'\n" + " C++ code is C++11 compatible (default)\n" + " More than one --std can be used:\n" + " 'cppcheck --std=c99 --std=posix file.c'\n" " --suppress= Suppress warnings that match . The format of\n" " is:\n" " [error id]:[filename]:[line]\n" @@ -830,7 +837,7 @@ void CmdLineParser::PrintHelp() const " cppcheck --quiet ../myproject/\n" "\n" " # Check test.cpp, enable all checks:\n" - " cppcheck --enable=all --inconclusive --std=c++11 test.cpp\n" + " cppcheck --enable=all --inconclusive test.cpp\n" "\n" " # Check f.cpp and search include files from inc1/ and inc2/:\n" " cppcheck -I inc1/ -I inc2/ f.cpp\n" diff --git a/lib/checkobsoletefunctions.cpp b/lib/checkobsoletefunctions.cpp index bd5dceea5..eafc89fec 100644 --- a/lib/checkobsoletefunctions.cpp +++ b/lib/checkobsoletefunctions.cpp @@ -73,7 +73,7 @@ void CheckObsoleteFunctions::obsoleteFunctions() reportError(tok->next(), Severity::style, "obsoleteFunctions"+it->first, it->second); } } - if (_settings->standards.c99) { + if (_settings->standards.c >= Standards::C99) { it = _obsoleteC99Functions.find(tok->str()); if (it != _obsoleteC99Functions.end()) { reportError(tok->next(), Severity::style, "obsoleteFunctions"+it->first, it->second); diff --git a/lib/checkobsoletefunctions.h b/lib/checkobsoletefunctions.h index 5520e9ca0..26a687c45 100644 --- a/lib/checkobsoletefunctions.h +++ b/lib/checkobsoletefunctions.h @@ -117,9 +117,8 @@ private: _obsoleteStandardFunctions["gets"] = "Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n" "The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun if the input data exceeds the size of the buffer. It is recommended to use the function 'fgets' instead."; - _obsoleteC99Functions["alloca"] = "Obsolete function 'alloca' called. It is recommended to use a variable length array.\n" - "The obsolete function 'alloca' is called. It is recommended to use a variable length array or a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons (http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca)."; - + _obsoleteC99Functions["alloca"] = "Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n" + "The obsolete function 'alloca' is called. In C99 and later it is recommended to use a variable length array or a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons (http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca)."; } void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { diff --git a/lib/standards.h b/lib/standards.h index e0bfa2725..aa0b62014 100644 --- a/lib/standards.h +++ b/lib/standards.h @@ -27,17 +27,17 @@ * This struct contains all possible standards that cppcheck recognize. */ struct Standards { - /** Code is C99 standard */ - bool c99; + /** C code C89/C99/C11 standard */ + enum cstd_t { C89, C99, C11 } c; + + /** C++ code standard */ + enum cppstd_t { CPP03, CPP11 } cpp; /** Code is posix */ bool posix; - /** Code follows C++11 standard */ - bool cpp11; - /** This constructor clear all the variables **/ - Standards() : c99(false), posix(false), cpp11(false) {}; + Standards() : c(C11), cpp(CPP11), posix(false) {}; }; /// @} diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 37b6c1441..65aec0782 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2106,7 +2106,7 @@ void Tokenizer::simplifyNull() } // nullptr.. - if (isCPP()) { + if (isCPP() && _settings->standards.cpp == Standards::CPP11) { for (Token *tok = list.front(); tok; tok = tok->next()) { if (tok->str() == "nullptr") tok->str("0"); @@ -8396,7 +8396,7 @@ void Tokenizer::simplifyKeyword() { const char *pattern; - if (_settings->standards.c99) + if (_settings->standards.c >= Standards::C99) pattern = "volatile|inline|__inline|__forceinline|register|restrict|__restrict|__restrict__"; else pattern = "volatile|inline|__inline|__forceinline|register|__restrict|__restrict__"; @@ -8639,12 +8639,12 @@ void Tokenizer::simplifyNamespaceStd() tok->previous()->insertToken("::"); } - else if (_settings->standards.cpp11 && Token::Match(tok, "!!:: tr1 ::")) + else if (_settings->standards.cpp == Standards::CPP11 && Token::Match(tok, "!!:: tr1 ::")) tok->next()->str("std"); } for (Token* tok = list.front(); tok; tok = tok->next()) { - if (_settings->standards.cpp11 && Token::Match(tok, "std :: tr1 ::")) + if (_settings->standards.cpp == Standards::CPP11 && Token::Match(tok, "std :: tr1 ::")) Token::eraseTokens(tok, tok->tokAt(3)); else if (Token::Match(tok, "using namespace std ;")) { diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 3a74ca158..8a8091d3e 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -681,7 +681,7 @@ private: Settings settings; CmdLineParser parser(&settings); ASSERT(parser.ParseFromArgs(3, argv)); - ASSERT(settings.standards.c99); + ASSERT(settings.standards.c == Standards::C99); } void stdcpp11() { @@ -690,7 +690,7 @@ private: Settings settings; CmdLineParser parser(&settings); ASSERT(parser.ParseFromArgs(3, argv)); - ASSERT(settings.standards.cpp11); + ASSERT(settings.standards.cpp == Standards::CPP11); } void suppressionsOld() { diff --git a/test/testobsoletefunctions.cpp b/test/testobsoletefunctions.cpp index 7a6b1a7cf..93c2724b0 100644 --- a/test/testobsoletefunctions.cpp +++ b/test/testobsoletefunctions.cpp @@ -75,7 +75,7 @@ private: Settings settings; settings.addEnabled("style"); settings.standards.posix = true; - settings.standards.c99 = true; + settings.standards.c = Standards::C11; // Tokenize.. Tokenizer tokenizer(&settings, this); @@ -221,7 +221,7 @@ private: "{\n" " char *x = alloca(10);\n" "}\n"); - ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'alloca' called. It is recommended to use a variable length array.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n", errout.str()); } // ticket #3121 diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index e1785cb65..80e1e703b 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -446,8 +446,6 @@ private: errout.str(""); Settings settings; - if (Path::isC(filename)) - settings.standards.c99 = true; Tokenizer tokenizer(&settings, this); std::istringstream istr(code); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 6d3789fa9..bab83cd9f 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -437,13 +437,13 @@ private: TEST_CASE(platformUnix64); } - std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp", bool cpp11 = false) { + std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp", bool cpp11 = true) { errout.str(""); Settings settings; settings.debugwarnings = true; settings.platform(platform); - settings.standards.cpp11 = cpp11; + settings.standards.cpp = cpp11 ? Standards::CPP11 : Standards::CPP03; // tokenize.. Tokenizer tokenizer(&settings, this); @@ -2630,6 +2630,8 @@ private: errout.str(""); Settings settings; + settings.standards.c = Standards::C89; + settings.standards.cpp = Standards::CPP03; Tokenizer tokenizer(&settings, this); std::istringstream istr(code); @@ -4920,7 +4922,7 @@ private: void vardecl14() { const char code[] = "::std::tr1::shared_ptr pNum1, pNum2;\n"; - ASSERT_EQUALS(":: std :: tr1 :: shared_ptr < int > pNum1 ; :: std :: tr1 :: shared_ptr < int > pNum2 ;", tokenizeAndStringify(code)); + ASSERT_EQUALS(":: std :: tr1 :: shared_ptr < int > pNum1 ; :: std :: tr1 :: shared_ptr < int > pNum2 ;", tokenizeAndStringify(code, false, false, Settings::Unspecified, "test.cpp", false)); } void vardecl15() {