Merge pull request #65 from makulik/master
Solution for ticket #3353 'Allow explicit undef's for configuration'
This commit is contained in:
commit
0bf17213ec
|
@ -324,6 +324,28 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
||||||
_settings->userDefines += ";";
|
_settings->userDefines += ";";
|
||||||
_settings->userDefines += define;
|
_settings->userDefines += define;
|
||||||
}
|
}
|
||||||
|
// User undef
|
||||||
|
else if (strncmp(argv[i], "-U", 2) == 0) {
|
||||||
|
std::string undef;
|
||||||
|
|
||||||
|
// "-U undef"
|
||||||
|
if (strcmp(argv[i], "-U") == 0) {
|
||||||
|
++i;
|
||||||
|
if (i >= argc || strncmp(argv[i], "-", 1) == 0 ||
|
||||||
|
strncmp(argv[i], "--", 2) == 0) {
|
||||||
|
PrintMessage("cppcheck: argument to '-U' is missing.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
undef = argv[i];
|
||||||
|
}
|
||||||
|
// "-Uundef"
|
||||||
|
else {
|
||||||
|
undef = 2 + argv[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
_settings->userUndefs.insert(undef);
|
||||||
|
}
|
||||||
|
|
||||||
// Include paths
|
// Include paths
|
||||||
else if (strncmp(argv[i], "-I", 2) == 0) {
|
else if (strncmp(argv[i], "-I", 2) == 0) {
|
||||||
|
@ -676,6 +698,10 @@ void CmdLineParser::PrintHelp()
|
||||||
" Use '-D' to limit the checking. When '-D' is used the\n"
|
" Use '-D' to limit the checking. When '-D' is used the\n"
|
||||||
" checking is limited to the given configuration.\n"
|
" checking is limited to the given configuration.\n"
|
||||||
" Example: '-DDEBUG=1 -D__cplusplus'.\n"
|
" Example: '-DDEBUG=1 -D__cplusplus'.\n"
|
||||||
|
" -U<ID> By default Cppcheck checks all configurations.\n"
|
||||||
|
" Use '-U' to explicitely hide certain #ifdef <ID> code\n"
|
||||||
|
" paths from checking.\n"
|
||||||
|
" Example: '-UDEBUG'\n"
|
||||||
" --enable=<id> Enable additional checks. The available ids are:\n"
|
" --enable=<id> Enable additional checks. The available ids are:\n"
|
||||||
" * all\n"
|
" * all\n"
|
||||||
" Enable all checks\n"
|
" Enable all checks\n"
|
||||||
|
|
|
@ -739,8 +739,10 @@ void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::str
|
||||||
std::list<std::string> configs;
|
std::list<std::string> configs;
|
||||||
std::string data;
|
std::string data;
|
||||||
preprocess(istr, data, configs, filename, includePaths);
|
preprocess(istr, data, configs, filename, includePaths);
|
||||||
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it)
|
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) {
|
||||||
result[ *it ] = Preprocessor::getcode(data, *it, filename, _settings, _errorLogger);
|
if (_settings && (_settings->userUndefs.find(*it) == _settings->userUndefs.end()))
|
||||||
|
result[ *it ] = Preprocessor::getcode(data, *it, filename, _settings, _errorLogger);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Preprocessor::removeSpaceNearNL(const std::string &str)
|
std::string Preprocessor::removeSpaceNearNL(const std::string &str)
|
||||||
|
@ -1539,6 +1541,24 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
||||||
|
|
||||||
if (line.compare(0, 8, "#define ") == 0) {
|
if (line.compare(0, 8, "#define ") == 0) {
|
||||||
match = true;
|
match = true;
|
||||||
|
|
||||||
|
if (settings) {
|
||||||
|
typedef std::set<std::string>::iterator It;
|
||||||
|
for (It it = settings->userUndefs.begin(); it != settings->userUndefs.end(); ++it) {
|
||||||
|
std::string::size_type pos = line.find_first_not_of(' ',8);
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
std::string::size_type pos2 = line.find(*it,pos);
|
||||||
|
if ((pos2 != std::string::npos) &&
|
||||||
|
((line.size() == pos2 + (*it).size()) ||
|
||||||
|
(line[pos2 + (*it).size()] == ' ') ||
|
||||||
|
(line[pos2 + (*it).size()] == '('))) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it)
|
for (std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it)
|
||||||
match &= bool(*it);
|
match &= bool(*it);
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,9 @@ public:
|
||||||
/** @brief defines given by the user */
|
/** @brief defines given by the user */
|
||||||
std::string userDefines;
|
std::string userDefines;
|
||||||
|
|
||||||
|
/** @brief undefines given by the user */
|
||||||
|
std::set<std::string> userUndefs;
|
||||||
|
|
||||||
/** @brief Experimental 2 pass checking of files */
|
/** @brief Experimental 2 pass checking of files */
|
||||||
bool test_2_pass;
|
bool test_2_pass;
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
|
||||||
<arg choice="opt"><option>--append=<file></option></arg>
|
<arg choice="opt"><option>--append=<file></option></arg>
|
||||||
<arg choice="opt"><option>--check-config</option></arg>
|
<arg choice="opt"><option>--check-config</option></arg>
|
||||||
<arg choice="opt"><option>-D<id></option></arg>
|
<arg choice="opt"><option>-D<id></option></arg>
|
||||||
|
<arg choice="opt"><option>-U<id></option></arg>
|
||||||
<arg choice="opt"><option>--enable=<id></option></arg>
|
<arg choice="opt"><option>--enable=<id></option></arg>
|
||||||
<arg choice="opt"><option>--error-exitcode=<n></option></arg>
|
<arg choice="opt"><option>--error-exitcode=<n></option></arg>
|
||||||
<arg choice="opt"><option>--errorlist</option></arg>
|
<arg choice="opt"><option>--errorlist</option></arg>
|
||||||
|
@ -170,8 +171,15 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
|
||||||
<para>By default Cppcheck checks all configurations. Use -D to limit the checking. When -D is used the checking is limited to the given configuration.
|
<para>By default Cppcheck checks all configurations. Use -D to limit the checking. When -D is used the checking is limited to the given configuration.
|
||||||
Example: -DDEBUG=1 -D__cplusplus</para>
|
Example: -DDEBUG=1 -D__cplusplus</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
<term><option>-U<id></option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>By default Cppcheck checks all configurations. Use '-U' to explicitely hide certain #ifdef <id> code paths from checking.
|
||||||
|
Example: '-UDEBUG'</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
<term><option>--enable=<id></option></term>
|
<term><option>--enable=<id></option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Enable additional checks. The available ids are:
|
<para>Enable additional checks. The available ids are:
|
||||||
|
|
|
@ -120,6 +120,12 @@ private:
|
||||||
|
|
||||||
TEST_CASE(checkconfig);
|
TEST_CASE(checkconfig);
|
||||||
TEST_CASE(unknownParam);
|
TEST_CASE(unknownParam);
|
||||||
|
|
||||||
|
TEST_CASE(undefs_noarg);
|
||||||
|
TEST_CASE(undefs_noarg2);
|
||||||
|
TEST_CASE(undefs_noarg3);
|
||||||
|
TEST_CASE(undefs);
|
||||||
|
TEST_CASE(undefs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -923,6 +929,54 @@ private:
|
||||||
CmdLineParser parser(&settings);
|
CmdLineParser parser(&settings);
|
||||||
ASSERT(!parser.ParseFromArgs(3, argv));
|
ASSERT(!parser.ParseFromArgs(3, argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void undefs() {
|
||||||
|
REDIRECT;
|
||||||
|
const char *argv[] = {"cppcheck", "-U_WIN32", "file.cpp"};
|
||||||
|
Settings settings;
|
||||||
|
CmdLineParser parser(&settings);
|
||||||
|
ASSERT(parser.ParseFromArgs(3, argv));
|
||||||
|
ASSERT_EQUALS(1, settings.userUndefs.size());
|
||||||
|
ASSERT(settings.userUndefs.find("_WIN32") != settings.userUndefs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefs2() {
|
||||||
|
REDIRECT;
|
||||||
|
const char *argv[] = {"cppcheck", "-U_WIN32", "-UNODEBUG", "file.cpp"};
|
||||||
|
Settings settings;
|
||||||
|
CmdLineParser parser(&settings);
|
||||||
|
ASSERT(parser.ParseFromArgs(4, argv));
|
||||||
|
ASSERT_EQUALS(2, settings.userUndefs.size());
|
||||||
|
ASSERT(settings.userUndefs.find("_WIN32") != settings.userUndefs.end());
|
||||||
|
ASSERT(settings.userUndefs.find("NODEBUG") != settings.userUndefs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefs_noarg() {
|
||||||
|
REDIRECT;
|
||||||
|
const char *argv[] = {"cppcheck", "-U"};
|
||||||
|
Settings settings;
|
||||||
|
CmdLineParser parser(&settings);
|
||||||
|
// Fails since -U has no param
|
||||||
|
ASSERT_EQUALS(false, parser.ParseFromArgs(2, argv));
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefs_noarg2() {
|
||||||
|
REDIRECT;
|
||||||
|
const char *argv[] = {"cppcheck", "-U", "-v", "file.cpp"};
|
||||||
|
Settings settings;
|
||||||
|
CmdLineParser parser(&settings);
|
||||||
|
// Fails since -U has no param
|
||||||
|
ASSERT_EQUALS(false, parser.ParseFromArgs(4, argv));
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefs_noarg3() {
|
||||||
|
REDIRECT;
|
||||||
|
const char *argv[] = {"cppcheck", "-U", "--quiet", "file.cpp"};
|
||||||
|
Settings settings;
|
||||||
|
CmdLineParser parser(&settings);
|
||||||
|
// Fails since -U has no param
|
||||||
|
ASSERT_EQUALS(false, parser.ParseFromArgs(4, argv));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestCmdlineParser)
|
REGISTER_TEST(TestCmdlineParser)
|
||||||
|
|
|
@ -235,6 +235,16 @@ private:
|
||||||
// Defines are given: test Preprocessor::handleIncludes
|
// Defines are given: test Preprocessor::handleIncludes
|
||||||
TEST_CASE(def_handleIncludes);
|
TEST_CASE(def_handleIncludes);
|
||||||
TEST_CASE(def_missingInclude);
|
TEST_CASE(def_missingInclude);
|
||||||
|
|
||||||
|
// Using -U to undefine symbols
|
||||||
|
TEST_CASE(undef1);
|
||||||
|
TEST_CASE(undef2);
|
||||||
|
TEST_CASE(undef3);
|
||||||
|
TEST_CASE(undef4);
|
||||||
|
TEST_CASE(undef5);
|
||||||
|
TEST_CASE(undef6);
|
||||||
|
TEST_CASE(undef7);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3031,6 +3041,151 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void undef1() {
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
|
const char filedata[] = "#ifdef X\n"
|
||||||
|
"Fred & Wilma\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
settings.userUndefs.insert("X");
|
||||||
|
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, (int)actual.size());
|
||||||
|
ASSERT_EQUALS("\n\n\n", actual[""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undef2() {
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
|
const char filedata[] = "#ifndef X\n"
|
||||||
|
"Fred & Wilma\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
settings.userUndefs.insert("X");
|
||||||
|
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, (int)actual.size());
|
||||||
|
ASSERT_EQUALS("\nFred & Wilma\n\n", actual[""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undef3() {
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
|
const char filedata[] = "#define X\n"
|
||||||
|
"#ifdef X\n"
|
||||||
|
"Fred & Wilma\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
settings.userUndefs.insert("X"); // User undefs should override internal defines
|
||||||
|
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, (int)actual.size());
|
||||||
|
ASSERT_EQUALS("\n\n\n\n", actual[""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undef4() {
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
|
const char filedata[] = "#define X Y\n"
|
||||||
|
"#ifdef X\n"
|
||||||
|
"Fred & Wilma\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
settings.userUndefs.insert("X"); // User undefs should override internal defines
|
||||||
|
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, (int)actual.size());
|
||||||
|
ASSERT_EQUALS("\n\n\n\n", actual[""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undef5() {
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
|
const char filedata[] = "#define X() Y\n"
|
||||||
|
"#ifdef X\n"
|
||||||
|
"Fred & Wilma\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
settings.userUndefs.insert("X"); // User undefs should override internal defines
|
||||||
|
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, (int)actual.size());
|
||||||
|
ASSERT_EQUALS("\n\n\n\n", actual[""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undef6() {
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
|
const char filedata[] = "#define X Y\n"
|
||||||
|
"#ifdef X\n"
|
||||||
|
"Fred & Wilma\n"
|
||||||
|
"#else"
|
||||||
|
"Barney & Betty\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
settings.userUndefs.insert("X"); // User undefs should override internal defines
|
||||||
|
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, (int)actual.size());
|
||||||
|
TODO_ASSERT_EQUALS("\n\n\nBarney & Betty\n\n","\n\n\n\n\n", actual[""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undef7() {
|
||||||
|
Settings settings;
|
||||||
|
|
||||||
|
const char filedata[] = "#define X XDefined\n"
|
||||||
|
"X;\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
settings.userUndefs.insert("X"); // User undefs should override internal defines
|
||||||
|
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, (int)actual.size());
|
||||||
|
TODO_ASSERT_EQUALS("\n;\n","\nXDefined;\n", actual[""]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestPreprocessor)
|
REGISTER_TEST(TestPreprocessor)
|
||||||
|
|
Loading…
Reference in New Issue