From 6c7dd30c78b5b0d1ccd9d06631448e4f8fea43f2 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sat, 3 Jan 2026 08:49:12 +0100 Subject: [PATCH] fix(parser): macros only parse parameters if define specified them --- .../Parsing/Impl/DefinesStreamProxy.cpp | 30 ++++++++++++------- src/Parser/Parsing/Impl/DefinesStreamProxy.h | 3 ++ .../Parsing/Impl/DefinesStreamProxyTests.cpp | 24 +++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp index 407fe327..6cf2bde5 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp @@ -52,9 +52,15 @@ DefinesStreamProxy::Define::Define() : m_contains_token_pasting_operators(false) {}; DefinesStreamProxy::Define::Define(std::string name, std::string value) + : Define(std::move(name), std::move(value), false) +{ +} + +DefinesStreamProxy::Define::Define(std::string name, std::string value, const bool parameterized) : m_name(std::move(name)), m_value(std::move(value)), - m_contains_token_pasting_operators(false) + m_contains_token_pasting_operators(false), + m_parameterized(parameterized) { } @@ -253,9 +259,11 @@ void DefinesStreamProxy::ContinueParameters(const ParserLine& line, size_t& curr void DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, size_t& currentPos) { m_current_define_parameters = std::vector(); + m_current_define_parameterized = false; if (line.m_line[currentPos] != '(') return; + m_current_define_parameterized = true; m_parameter_state = ParameterState::AFTER_OPEN; currentPos++; @@ -285,7 +293,7 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const size SkipWhitespace(line, currentPos); m_in_define = true; - m_current_define = Define(name, std::string()); + m_current_define = Define(name, std::string(), m_current_define_parameterized); m_current_define_value.str(std::string()); ContinueDefine(line, currentPos); @@ -1002,12 +1010,15 @@ void DefinesStreamProxy::ProcessNestedMacros(ParserLine& line, unsigned& linePos ss << std::string(input, lastDefineEnd, defineStart - (lastDefineEnd)); } - callstack.push_back(nestedMacro); + callstack.emplace_back(nestedMacro); MacroParameterState nestedMacroState; - ExtractParametersFromMacroUsage(line, linePos, nestedMacroState, input, pos); - if (nestedMacroState.m_parameter_state != ParameterState::NOT_IN_PARAMETERS) - throw ParsingException(CreatePos(line, linePos), "Unbalanced brackets in macro parameters"); + if (nestedMacro->m_parameterized) + { + ExtractParametersFromMacroUsage(line, linePos, nestedMacroState, input, pos); + if (nestedMacroState.m_parameter_state != ParameterState::NOT_IN_PARAMETERS) + throw ParsingException(CreatePos(line, linePos), "Unbalanced brackets in macro parameters"); + } ExpandMacro(line, linePos, ss, callstack, nestedMacro, nestedMacroState.m_parameters); callstack.pop_back(); @@ -1053,15 +1064,14 @@ void DefinesStreamProxy::ProcessMacrosMultiLine(ParserLine& line) str << std::string(line.m_line, lastDefineEnd, defineStart - (lastDefineEnd)); } - callstack.push_back(m_current_macro); + callstack.emplace_back(m_current_macro); - ExtractParametersFromMacroUsage(line, pos, m_multi_line_macro_parameters, line.m_line, pos); + if (m_current_macro->m_parameterized) + ExtractParametersFromMacroUsage(line, pos, m_multi_line_macro_parameters, line.m_line, pos); // If still in parameters they continue on the next line if (m_multi_line_macro_parameters.m_parameter_state == ParameterState::NOT_IN_PARAMETERS) - { ExpandMacro(line, pos, str, callstack, m_current_macro, m_multi_line_macro_parameters.m_parameters); - } callstack.pop_back(); diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.h b/src/Parser/Parsing/Impl/DefinesStreamProxy.h index 2195529c..0daeafbb 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.h +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.h @@ -30,11 +30,13 @@ public: public: Define(); Define(std::string name, std::string value); + Define(std::string name, std::string value, bool parameterized); void IdentifyParameters(const std::vector& parameterNames); std::string m_name; std::string m_value; std::vector m_parameter_positions; + bool m_parameterized; bool m_contains_token_pasting_operators; private: @@ -132,6 +134,7 @@ private: Define m_current_define; std::ostringstream m_current_define_value; std::vector m_current_define_parameters; + bool m_current_define_parameterized; const Define* m_current_macro; MacroParameterState m_multi_line_macro_parameters; diff --git a/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp b/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp index a41e8b84..268a23ae 100644 --- a/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp +++ b/test/ParserTests/Parsing/Impl/DefinesStreamProxyTests.cpp @@ -1226,4 +1226,28 @@ namespace test::parsing::impl::defines_stream_proxy REQUIRE(proxy.Eof()); } + + TEST_CASE("DefinesStreamProxy: Only macros with args parse parenthesis", "[parsing][parsingstream]") + { + const std::vector lines{ + "#define ONE result", + "#define TWO() result", + "#define THREE(f) result", + "ONE()", + "TWO()", + "THREE(f)", + }; + + MockParserLineStream mockStream(lines); + DefinesStreamProxy proxy(&mockStream); + + ExpectLine(&proxy, 1, ""); + ExpectLine(&proxy, 2, ""); + ExpectLine(&proxy, 3, ""); + ExpectLine(&proxy, 4, "result()"); + ExpectLine(&proxy, 5, "result"); + ExpectLine(&proxy, 6, "result"); + + REQUIRE(proxy.Eof()); + } } // namespace test::parsing::impl::defines_stream_proxy