Fixed #7700 (Using -D to force a configuration still checks the configuration as well as configurations that are not relevant)
This commit is contained in:
parent
19c105cdf9
commit
ff036c8742
|
@ -215,7 +215,22 @@ static std::string readcondition(const simplecpp::Token *iftok, const std::set<s
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string cfg(const std::vector<std::string> &configs)
|
static bool hasDefine(const std::string &userDefines, const std::string &cfg)
|
||||||
|
{
|
||||||
|
std::string::size_type pos = 0;
|
||||||
|
while (pos < userDefines.size()) {
|
||||||
|
pos = userDefines.find(cfg, pos);
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
break;
|
||||||
|
const std::string::size_type pos2 = pos + cfg.size();
|
||||||
|
if ((pos == 0 || userDefines[pos-1U] == ';') && (pos2 == userDefines.size() || userDefines[pos2] == '='))
|
||||||
|
return true;
|
||||||
|
pos = pos2;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string cfg(const std::vector<std::string> &configs, const std::string &userDefines)
|
||||||
{
|
{
|
||||||
std::set<std::string> configs2(configs.begin(), configs.end());
|
std::set<std::string> configs2(configs.begin(), configs.end());
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
@ -224,6 +239,8 @@ static std::string cfg(const std::vector<std::string> &configs)
|
||||||
continue;
|
continue;
|
||||||
if (*it == "0")
|
if (*it == "0")
|
||||||
return "";
|
return "";
|
||||||
|
if (hasDefine(userDefines, *it))
|
||||||
|
continue;
|
||||||
if (!ret.empty())
|
if (!ret.empty())
|
||||||
ret += ';';
|
ret += ';';
|
||||||
ret += *it;
|
ret += *it;
|
||||||
|
@ -248,7 +265,33 @@ static bool isUndefined(const std::string &cfg, const std::set<std::string> &und
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getConfigs(const simplecpp::TokenList &tokens, std::set<std::string> &defined, const std::set<std::string> &undefined, std::set<std::string> &ret)
|
static bool getConfigsElseIsFalse(const std::vector<std::string> &configs_if, const std::string &userDefines)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < configs_if.size(); ++i) {
|
||||||
|
if (hasDefine(userDefines, configs_if[i]))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const simplecpp::Token *gotoEndIf(const simplecpp::Token *cmdtok)
|
||||||
|
{
|
||||||
|
int level = 0;
|
||||||
|
while (nullptr != (cmdtok = cmdtok->next)) {
|
||||||
|
if (cmdtok->op == '#' && !sameline(cmdtok->previous,cmdtok) && sameline(cmdtok, cmdtok->next)) {
|
||||||
|
if (cmdtok->next->str.compare(0,2,"if")==0)
|
||||||
|
++level;
|
||||||
|
else if (cmdtok->next->str == "endif") {
|
||||||
|
--level;
|
||||||
|
if (level < 0)
|
||||||
|
return cmdtok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getConfigs(const simplecpp::TokenList &tokens, std::set<std::string> &defined, const std::string &userDefines, const std::set<std::string> &undefined, std::set<std::string> &ret)
|
||||||
{
|
{
|
||||||
std::vector<std::string> configs_if;
|
std::vector<std::string> configs_if;
|
||||||
std::vector<std::string> configs_ifndef;
|
std::vector<std::string> configs_ifndef;
|
||||||
|
@ -277,21 +320,26 @@ static void getConfigs(const simplecpp::TokenList &tokens, std::set<std::string>
|
||||||
|
|
||||||
configs_if.push_back((cmdtok->str == "ifndef") ? std::string() : config);
|
configs_if.push_back((cmdtok->str == "ifndef") ? std::string() : config);
|
||||||
configs_ifndef.push_back((cmdtok->str == "ifndef") ? config : std::string());
|
configs_ifndef.push_back((cmdtok->str == "ifndef") ? config : std::string());
|
||||||
ret.insert(cfg(configs_if));
|
ret.insert(cfg(configs_if,userDefines));
|
||||||
} else if (cmdtok->str == "elif") {
|
} else if (cmdtok->str == "elif" || cmdtok->str == "else") {
|
||||||
|
if (getConfigsElseIsFalse(configs_if,userDefines)) {
|
||||||
|
tok = gotoEndIf(tok);
|
||||||
|
if (!tok)
|
||||||
|
break;
|
||||||
|
tok = tok->previous;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!configs_if.empty())
|
if (!configs_if.empty())
|
||||||
configs_if.pop_back();
|
configs_if.pop_back();
|
||||||
|
if (cmdtok->str == "elif") {
|
||||||
std::string config = readcondition(cmdtok, defined);
|
std::string config = readcondition(cmdtok, defined);
|
||||||
if (undefined.find(config) != undefined.end())
|
if (isUndefined(config,undefined))
|
||||||
config.clear();
|
config.clear();
|
||||||
configs_if.push_back(config);
|
configs_if.push_back(config);
|
||||||
ret.insert(cfg(configs_if));
|
ret.insert(cfg(configs_if, userDefines));
|
||||||
} else if (cmdtok->str == "else") {
|
} else if (!configs_ifndef.empty()) {
|
||||||
if (!configs_if.empty())
|
|
||||||
configs_if.pop_back();
|
|
||||||
if (!configs_ifndef.empty()) {
|
|
||||||
configs_if.push_back(configs_ifndef.back());
|
configs_if.push_back(configs_ifndef.back());
|
||||||
ret.insert(cfg(configs_if));
|
ret.insert(cfg(configs_if, userDefines));
|
||||||
}
|
}
|
||||||
} else if (cmdtok->str == "endif" && !sameline(tok, cmdtok->next)) {
|
} else if (cmdtok->str == "endif" && !sameline(tok, cmdtok->next)) {
|
||||||
if (!configs_if.empty())
|
if (!configs_if.empty())
|
||||||
|
@ -315,10 +363,10 @@ std::set<std::string> Preprocessor::getConfigs(const simplecpp::TokenList &token
|
||||||
std::set<std::string> defined;
|
std::set<std::string> defined;
|
||||||
defined.insert("__cplusplus");
|
defined.insert("__cplusplus");
|
||||||
|
|
||||||
::getConfigs(tokens, defined, _settings.userUndefs, ret);
|
::getConfigs(tokens, defined, _settings.userDefines, _settings.userUndefs, ret);
|
||||||
|
|
||||||
for (std::map<std::string, simplecpp::TokenList*>::const_iterator it = tokenlists.begin(); it != tokenlists.end(); ++it)
|
for (std::map<std::string, simplecpp::TokenList*>::const_iterator it = tokenlists.begin(); it != tokenlists.end(); ++it)
|
||||||
::getConfigs(*(it->second), defined, _settings.userUndefs, ret);
|
::getConfigs(*(it->second), defined, _settings.userDefines, _settings.userUndefs, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "simplecpp.h"
|
#include "simplecpp.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -215,6 +216,8 @@ private:
|
||||||
TEST_CASE(getConfigs8); // #if A==1 => cfg: A=1
|
TEST_CASE(getConfigs8); // #if A==1 => cfg: A=1
|
||||||
TEST_CASE(getConfigs10); // #5139
|
TEST_CASE(getConfigs10); // #5139
|
||||||
|
|
||||||
|
TEST_CASE(getConfigsD1);
|
||||||
|
|
||||||
TEST_CASE(getConfigsU1);
|
TEST_CASE(getConfigsU1);
|
||||||
TEST_CASE(getConfigsU2);
|
TEST_CASE(getConfigsU2);
|
||||||
TEST_CASE(getConfigsU3);
|
TEST_CASE(getConfigsU3);
|
||||||
|
@ -255,10 +258,12 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getConfigsStr(const char filedata[], const char *u1=NULL) {
|
std::string getConfigsStr(const char filedata[], const char *arg=NULL) {
|
||||||
Settings settings;
|
Settings settings;
|
||||||
if (u1)
|
if (arg && std::strncmp(arg,"-D",2)==0)
|
||||||
settings.userUndefs.insert(u1);
|
settings.userDefines = arg + 2;
|
||||||
|
if (arg && std::strncmp(arg,"-U",2)==0)
|
||||||
|
settings.userUndefs.insert(arg+2);
|
||||||
Preprocessor preprocessor(settings, this);
|
Preprocessor preprocessor(settings, this);
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
|
@ -2060,17 +2065,27 @@ private:
|
||||||
ASSERT_EQUALS("\n", getConfigsStr(filedata));
|
ASSERT_EQUALS("\n", getConfigsStr(filedata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getConfigsD1() {
|
||||||
|
const char filedata[] = "#ifdef X\n"
|
||||||
|
"#else\n"
|
||||||
|
"#ifdef Y\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#endif\n";
|
||||||
|
ASSERT_EQUALS("\n", getConfigsStr(filedata, "-DX"));
|
||||||
|
ASSERT_EQUALS("\nX\nY\n", getConfigsStr(filedata));
|
||||||
|
}
|
||||||
|
|
||||||
void getConfigsU1() {
|
void getConfigsU1() {
|
||||||
const char filedata[] = "#ifdef X\n"
|
const char filedata[] = "#ifdef X\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
ASSERT_EQUALS("\n", getConfigsStr(filedata, "X"));
|
ASSERT_EQUALS("\n", getConfigsStr(filedata, "-UX"));
|
||||||
ASSERT_EQUALS("\nX\n", getConfigsStr(filedata));
|
ASSERT_EQUALS("\nX\n", getConfigsStr(filedata));
|
||||||
}
|
}
|
||||||
|
|
||||||
void getConfigsU2() {
|
void getConfigsU2() {
|
||||||
const char filedata[] = "#ifndef X\n"
|
const char filedata[] = "#ifndef X\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
ASSERT_EQUALS("\n", getConfigsStr(filedata, "X"));
|
ASSERT_EQUALS("\n", getConfigsStr(filedata, "-UX"));
|
||||||
ASSERT_EQUALS("\n", getConfigsStr(filedata)); // no #else
|
ASSERT_EQUALS("\n", getConfigsStr(filedata)); // no #else
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2080,7 +2095,7 @@ private:
|
||||||
"#else\n"
|
"#else\n"
|
||||||
"Barney & Betty\n"
|
"Barney & Betty\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
ASSERT_EQUALS("\n", getConfigsStr(filedata, "X"));
|
ASSERT_EQUALS("\n", getConfigsStr(filedata, "-UX"));
|
||||||
ASSERT_EQUALS("\nX\n", getConfigsStr(filedata));
|
ASSERT_EQUALS("\nX\n", getConfigsStr(filedata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2088,21 +2103,21 @@ private:
|
||||||
const char filedata[] = "#if defined(X) || defined(Y) || defined(Z)\n"
|
const char filedata[] = "#if defined(X) || defined(Y) || defined(Z)\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
ASSERT_EQUALS("\n", getConfigsStr(filedata, "X"));
|
ASSERT_EQUALS("\n", getConfigsStr(filedata, "-UX"));
|
||||||
ASSERT_EQUALS("\nX;Y;Z\n", getConfigsStr(filedata));
|
ASSERT_EQUALS("\nX;Y;Z\n", getConfigsStr(filedata));
|
||||||
}
|
}
|
||||||
|
|
||||||
void getConfigsU5() {
|
void getConfigsU5() {
|
||||||
const char filedata[] = "#if X==1\n"
|
const char filedata[] = "#if X==1\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
ASSERT_EQUALS("\n", getConfigsStr(filedata, "X"));
|
ASSERT_EQUALS("\n", getConfigsStr(filedata, "-UX"));
|
||||||
ASSERT_EQUALS("\nX=1\n", getConfigsStr(filedata));
|
ASSERT_EQUALS("\nX=1\n", getConfigsStr(filedata));
|
||||||
}
|
}
|
||||||
|
|
||||||
void getConfigsU6() {
|
void getConfigsU6() {
|
||||||
const char filedata[] = "#if X==0\n"
|
const char filedata[] = "#if X==0\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
ASSERT_EQUALS("\nX=0\n", getConfigsStr(filedata, "X"));
|
ASSERT_EQUALS("\nX=0\n", getConfigsStr(filedata, "-UX"));
|
||||||
ASSERT_EQUALS("\nX=0\n", getConfigsStr(filedata));
|
ASSERT_EQUALS("\nX=0\n", getConfigsStr(filedata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue