diff options
Diffstat (limited to 'flang/lib/Parser/preprocessor.cpp')
-rw-r--r-- | flang/lib/Parser/preprocessor.cpp | 88 |
1 files changed, 56 insertions, 32 deletions
diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp index 9197906..d755605 100644 --- a/flang/lib/Parser/preprocessor.cpp +++ b/flang/lib/Parser/preprocessor.cpp @@ -147,12 +147,14 @@ TokenSequence Definition::Apply( CharBlock token{replacement_.TokenAt(j)}; std::size_t bytes{token.size()}; if (skipping) { - if (bytes == 1) { - if (token[0] == '(') { - ++parenthesesNesting; - } else if (token[0] == ')') { - skipping = --parenthesesNesting > 0; + char ch{token.OnlyNonBlank()}; + if (ch == '(') { + ++parenthesesNesting; + } else if (ch == ')') { + if (parenthesesNesting > 0) { + --parenthesesNesting; } + skipping = parenthesesNesting > 0; } continue; } @@ -207,18 +209,21 @@ TokenSequence Definition::Apply( result.Put(args[k]); } } else if (bytes == 10 && isVariadic_ && token.ToString() == "__VA_OPT__" && - j + 2 < tokens && replacement_.TokenAt(j + 1).ToString() == "(" && + j + 2 < tokens && replacement_.TokenAt(j + 1).OnlyNonBlank() == '(' && parenthesesNesting == 0) { parenthesesNesting = 1; skipping = args.size() == argumentCount_; ++j; } else { - if (bytes == 1 && parenthesesNesting > 0 && token[0] == '(') { - ++parenthesesNesting; - } else if (bytes == 1 && parenthesesNesting > 0 && token[0] == ')') { - if (--parenthesesNesting == 0) { - skipping = false; - continue; + if (parenthesesNesting > 0) { + char ch{token.OnlyNonBlank()}; + if (ch == '(') { + ++parenthesesNesting; + } else if (ch == ')') { + if (--parenthesesNesting == 0) { + skipping = false; + continue; + } } } result.Put(replacement_, j); @@ -361,18 +366,16 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement( std::vector<std::size_t> argStart{++k}; for (int nesting{0}; k < tokens; ++k) { CharBlock token{input.TokenAt(k)}; - if (token.size() == 1) { - char ch{token[0]}; - if (ch == '(') { - ++nesting; - } else if (ch == ')') { - if (nesting == 0) { - break; - } - --nesting; - } else if (ch == ',' && nesting == 0) { - argStart.push_back(k + 1); + char ch{token.OnlyNonBlank()}; + if (ch == '(') { + ++nesting; + } else if (ch == ')') { + if (nesting == 0) { + break; } + --nesting; + } else if (ch == ',' && nesting == 0) { + argStart.push_back(k + 1); } } if (argStart.size() == 1 && k == argStart[0] && def->argumentCount() == 0) { @@ -454,12 +457,11 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) { } nameToken = SaveTokenAsName(nameToken); definitions_.erase(nameToken); - if (++j < tokens && dir.TokenAt(j).size() == 1 && - dir.TokenAt(j)[0] == '(') { + if (++j < tokens && dir.TokenAt(j).OnlyNonBlank() == '(') { j = dir.SkipBlanks(j + 1); std::vector<std::string> argName; bool isVariadic{false}; - if (dir.TokenAt(j).ToString() != ")") { + if (dir.TokenAt(j).OnlyNonBlank() != ')') { while (true) { std::string an{dir.TokenAt(j).ToString()}; if (an == "...") { @@ -478,11 +480,11 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) { "#define: malformed argument list"_err_en_US); return; } - std::string punc{dir.TokenAt(j).ToString()}; - if (punc == ")") { + char punc{dir.TokenAt(j).OnlyNonBlank()}; + if (punc == ')') { break; } - if (isVariadic || punc != ",") { + if (isVariadic || punc != ',') { prescanner.Say(dir.GetTokenProvenanceRange(j), "#define: malformed argument list"_err_en_US); return; @@ -502,10 +504,12 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) { } } j = dir.SkipBlanks(j + 1); + CheckForUnbalancedParentheses(dir, j, tokens - j); definitions_.emplace(std::make_pair( nameToken, Definition{argName, dir, j, tokens - j, isVariadic})); } else { j = dir.SkipBlanks(j + 1); + CheckForUnbalancedParentheses(dir, j, tokens - j); definitions_.emplace( std::make_pair(nameToken, Definition{dir, j, tokens - j})); } @@ -883,7 +887,7 @@ static std::int64_t ExpressionValue(const TokenSequence &token, } switch (op) { case PARENS: - if (*atToken < tokens && token.TokenAt(*atToken).ToString() == ")") { + if (*atToken < tokens && token.TokenAt(*atToken).OnlyNonBlank() == ')') { ++*atToken; break; } @@ -1085,8 +1089,8 @@ bool Preprocessor::IsIfPredicateTrue(const TokenSequence &expr, if (ToLowerCaseLetters(expr1.TokenAt(j).ToString()) == "defined") { CharBlock name; if (j + 3 < expr1.SizeInTokens() && - expr1.TokenAt(j + 1).ToString() == "(" && - expr1.TokenAt(j + 3).ToString() == ")") { + expr1.TokenAt(j + 1).OnlyNonBlank() == '(' && + expr1.TokenAt(j + 3).OnlyNonBlank() == ')') { name = expr1.TokenAt(j + 2); j += 3; } else if (j + 1 < expr1.SizeInTokens() && @@ -1176,4 +1180,24 @@ void Preprocessor::LineDirective( sourceFile->LineDirective(pos->trueLineNumber + 1, *linePath, *lineNumber); } } + +void Preprocessor::CheckForUnbalancedParentheses( + const TokenSequence &tokens, std::size_t j, std::size_t n) { + if (!anyMacroWithUnbalancedParentheses_) { + int nesting{0}; + for (; n-- > 0; ++j) { + char ch{tokens.TokenAt(j).OnlyNonBlank()}; + if (ch == '(') { + ++nesting; + } else if (ch == ')') { + if (nesting-- == 0) { + break; + } + } + } + if (nesting != 0) { + anyMacroWithUnbalancedParentheses_ = true; + } + } +} } // namespace Fortran::parser |