From 9b2dd8c7eb91e24e2d09c2f1fa98c5bddca6f536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 22 Jul 2009 20:11:27 +0200 Subject: [PATCH] Preprocessor: Better evaluation of conditions such as '#if defined A || defined B' (#469) --- src/preprocessor.cpp | 28 ++++++++++++++++++++++++++++ test/testpreprocessor.cpp | 19 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/preprocessor.cpp b/src/preprocessor.cpp index 9f25627ca..9c6e0f37c 100644 --- a/src/preprocessor.cpp +++ b/src/preprocessor.cpp @@ -519,6 +519,31 @@ void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, st // Remove space characters that are after or before new line character processedFile = removeSpaceNearNL(processedFile); + // Replace "defined A" with "defined(A)" + { + std::istringstream istr(processedFile.c_str()); + std::ostringstream ostr; + std::string line; + while (std::getline(istr, line)) + { + if (line.substr(0, 4) == "#if " || line.substr(0, 6) == "#elif ") + { + std::string::size_type pos = 0; + while ((pos = line.find(" defined ")) != std::string::npos) + { + line[pos+8] = '('; + pos = line.find_first_of(" |&", pos + 8); + if (pos == std::string::npos) + line += ")"; + else + line.insert(pos, ")"); + } + } + ostr << line << "\n"; + } + processedFile = ostr.str(); + } + handleIncludes(processedFile, filename, includePaths); processedFile = replaceIfDefined(processedFile); @@ -771,6 +796,9 @@ bool Preprocessor::match_cfg_def(std::string cfg, std::string def) def.insert(pos, isdefined ? "1" : "0"); } + if (def.find("1||") != std::string::npos || def.find("||1") != std::string::npos) + return true; + while (def.find("1&&") != std::string::npos) { def.erase(def.find("1&&"), 3); diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index f528e4a09..22536c870 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -89,6 +89,7 @@ private: TEST_CASE(if_cond1); TEST_CASE(if_cond2); TEST_CASE(if_cond3); + TEST_CASE(if_cond4); TEST_CASE(multiline1); TEST_CASE(multiline2); @@ -582,6 +583,24 @@ private: ASSERT_EQUALS("\na\n\nabc\n\n\n", actual["A;B;C"]); } + void if_cond4() + { + const char filedata[] = "#define A\n" + "#define B\n" + "#if defined A || defined B\n" + "ab\n" + "#endif\n"; + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + Preprocessor preprocessor; + preprocessor.preprocess(istr, actual, "file.c"); + + // Compare results.. + ASSERT_EQUALS(1, static_cast(actual.size())); + ASSERT_EQUALS("\n\n\nab\n\n", actual[""]); + }