diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 05fc23089..303c8915e 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -890,10 +890,18 @@ static void simplifyVarMap(std::map &variables) // TODO: 1. tokenize the value, replace each token like this. // TODO: 2. handle function-macros too. + std::set seenVariables; std::map::iterator it = variables.find(varValue); - while (it != variables.end() && it->first != it->second && it != i) { - varValue = it->second; - it = variables.find(varValue); + while (it != variables.end() && it->first != it->second) { + if (seenVariables.find(it->first) != seenVariables.end()) { + // We have already seen this variable. there is a cycle of #define that we can't process at + // this time. Stop trying to simplify the current variable and leave it as is. + break; + } else { + seenVariables.insert(it->first); + varValue = it->second; + it = variables.find(varValue); + } } } } diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index cddf6e19e..0c2363198 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -132,6 +132,7 @@ private: TEST_CASE(if_macro_eq_macro); // #3536 TEST_CASE(ticket_3675); + TEST_CASE(ticket_3699); TEST_CASE(multiline1); TEST_CASE(multiline2); @@ -1550,6 +1551,24 @@ private: // There's nothing to assert. It just needs to not hang. } + void ticket_3699() { + const std::string code("#define INLINE __forceinline\n" + "#define inline __forceinline\n" + "#define __forceinline inline\n" + "#if !defined(_WIN32)\n" + "#endif\n" + "INLINE inline __forceinline\n" + ); + Settings settings; + Preprocessor preprocessor(&settings, this); + std::istringstream istr(code); + std::map actual; + preprocessor.preprocess(istr, actual, "file.c"); + + // First, it must not hang. Second, inline must becomes inline, and __forceinline must become __forceinline. + ASSERT_EQUALS("\n\n\n\n\n$$$__forceinline $$inline $$__forceinline\n", actual[""]); + } + void multiline1() { const char filedata[] = "#define str \"abc\" \\\n" " \"def\" \n"