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 += 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
|
||||
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"
|
||||
" checking is limited to the given configuration.\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"
|
||||
" * all\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::string data;
|
||||
preprocess(istr, data, configs, filename, includePaths);
|
||||
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it)
|
||||
result[ *it ] = Preprocessor::getcode(data, *it, filename, _settings, _errorLogger);
|
||||
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) {
|
||||
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)
|
||||
|
@ -1539,6 +1541,24 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
|||
|
||||
if (line.compare(0, 8, "#define ") == 0) {
|
||||
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)
|
||||
match &= bool(*it);
|
||||
|
||||
|
|
|
@ -150,6 +150,9 @@ public:
|
|||
/** @brief defines given by the user */
|
||||
std::string userDefines;
|
||||
|
||||
/** @brief undefines given by the user */
|
||||
std::set<std::string> userUndefs;
|
||||
|
||||
/** @brief Experimental 2 pass checking of files */
|
||||
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>--check-config</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>--error-exitcode=<n></option></arg>
|
||||
<arg choice="opt"><option>--errorlist</option></arg>
|
||||
|
@ -171,7 +172,14 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
|
|||
Example: -DDEBUG=1 -D__cplusplus</para>
|
||||
</listitem>
|
||||
</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>
|
||||
<listitem>
|
||||
<para>Enable additional checks. The available ids are:
|
||||
|
|
|
@ -120,6 +120,12 @@ private:
|
|||
|
||||
TEST_CASE(checkconfig);
|
||||
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);
|
||||
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)
|
||||
|
|
|
@ -235,6 +235,16 @@ private:
|
|||
// Defines are given: test Preprocessor::handleIncludes
|
||||
TEST_CASE(def_handleIncludes);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue