[clang-tidy][NFC] Improve compilation time of IntegralLiteralExpressionMatcher

When using agressive inlining -Xclang -mllvm -Xclang -inline-threshold=500,
this file takes 10-18 min to compile. This is caused by in-direct recursion.
Looks like transforming code to use templates and lambdas instead of
std::function and member function pointer reduces this time to 0.5s.

Fixes: #59658
This commit is contained in:
Piotr Zegar 2023-08-31 18:46:07 +00:00
parent 0c5c7b52f0
commit a199d8fac0
2 changed files with 41 additions and 36 deletions

View File

@ -10,7 +10,6 @@
#include <algorithm>
#include <cctype>
#include <stdexcept>
namespace clang::tidy::modernize {
@ -48,10 +47,10 @@ bool IntegralLiteralExpressionMatcher::consume(tok::TokenKind Kind) {
return false;
}
template <typename NonTerminalFunctor, typename IsKindFunctor>
bool IntegralLiteralExpressionMatcher::nonTerminalChainedExpr(
bool (IntegralLiteralExpressionMatcher::*NonTerminal)(),
const std::function<bool(Token)> &IsKind) {
if (!(this->*NonTerminal)())
const NonTerminalFunctor &NonTerminal, const IsKindFunctor &IsKind) {
if (!NonTerminal())
return false;
if (Current == End)
return true;
@ -63,13 +62,28 @@ bool IntegralLiteralExpressionMatcher::nonTerminalChainedExpr(
if (!advance())
return false;
if (!(this->*NonTerminal)())
if (!NonTerminal())
return false;
}
return true;
}
template <tok::TokenKind Kind, typename NonTerminalFunctor>
bool IntegralLiteralExpressionMatcher::nonTerminalChainedExpr(
const NonTerminalFunctor &NonTerminal) {
return nonTerminalChainedExpr(NonTerminal,
[](Token Tok) { return Tok.is(Kind); });
}
template <tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind... Ks,
typename NonTerminalFunctor>
bool IntegralLiteralExpressionMatcher::nonTerminalChainedExpr(
const NonTerminalFunctor &NonTerminal) {
return nonTerminalChainedExpr(
NonTerminal, [](Token Tok) { return Tok.isOneOf(K1, K2, Ks...); });
}
// Advance over unary operators.
bool IntegralLiteralExpressionMatcher::unaryOperator() {
if (Current->isOneOf(tok::TokenKind::minus, tok::TokenKind::plus,
@ -155,18 +169,18 @@ bool IntegralLiteralExpressionMatcher::unaryExpr() {
bool IntegralLiteralExpressionMatcher::multiplicativeExpr() {
return nonTerminalChainedExpr<tok::TokenKind::star, tok::TokenKind::slash,
tok::TokenKind::percent>(
&IntegralLiteralExpressionMatcher::unaryExpr);
[this] { return unaryExpr(); });
}
bool IntegralLiteralExpressionMatcher::additiveExpr() {
return nonTerminalChainedExpr<tok::plus, tok::minus>(
&IntegralLiteralExpressionMatcher::multiplicativeExpr);
[this] { return multiplicativeExpr(); });
}
bool IntegralLiteralExpressionMatcher::shiftExpr() {
return nonTerminalChainedExpr<tok::TokenKind::lessless,
tok::TokenKind::greatergreater>(
&IntegralLiteralExpressionMatcher::additiveExpr);
[this] { return additiveExpr(); });
}
bool IntegralLiteralExpressionMatcher::compareExpr() {
@ -190,38 +204,38 @@ bool IntegralLiteralExpressionMatcher::relationalExpr() {
return nonTerminalChainedExpr<tok::TokenKind::less, tok::TokenKind::greater,
tok::TokenKind::lessequal,
tok::TokenKind::greaterequal>(
&IntegralLiteralExpressionMatcher::compareExpr);
[this] { return compareExpr(); });
}
bool IntegralLiteralExpressionMatcher::equalityExpr() {
return nonTerminalChainedExpr<tok::TokenKind::equalequal,
tok::TokenKind::exclaimequal>(
&IntegralLiteralExpressionMatcher::relationalExpr);
[this] { return relationalExpr(); });
}
bool IntegralLiteralExpressionMatcher::andExpr() {
return nonTerminalChainedExpr<tok::TokenKind::amp>(
&IntegralLiteralExpressionMatcher::equalityExpr);
[this] { return equalityExpr(); });
}
bool IntegralLiteralExpressionMatcher::exclusiveOrExpr() {
return nonTerminalChainedExpr<tok::TokenKind::caret>(
&IntegralLiteralExpressionMatcher::andExpr);
[this] { return andExpr(); });
}
bool IntegralLiteralExpressionMatcher::inclusiveOrExpr() {
return nonTerminalChainedExpr<tok::TokenKind::pipe>(
&IntegralLiteralExpressionMatcher::exclusiveOrExpr);
[this] { return exclusiveOrExpr(); });
}
bool IntegralLiteralExpressionMatcher::logicalAndExpr() {
return nonTerminalChainedExpr<tok::TokenKind::ampamp>(
&IntegralLiteralExpressionMatcher::inclusiveOrExpr);
[this] { return inclusiveOrExpr(); });
}
bool IntegralLiteralExpressionMatcher::logicalOrExpr() {
return nonTerminalChainedExpr<tok::TokenKind::pipepipe>(
&IntegralLiteralExpressionMatcher::logicalAndExpr);
[this] { return logicalAndExpr(); });
}
bool IntegralLiteralExpressionMatcher::conditionalExpr() {
@ -263,12 +277,10 @@ bool IntegralLiteralExpressionMatcher::conditionalExpr() {
}
bool IntegralLiteralExpressionMatcher::commaExpr() {
auto Pred = CommaAllowed
? std::function<bool(Token)>(
[](Token Tok) { return Tok.is(tok::TokenKind::comma); })
: std::function<bool(Token)>([](Token) { return false; });
return nonTerminalChainedExpr(
&IntegralLiteralExpressionMatcher::conditionalExpr, Pred);
auto NonTerminal = [this] { return conditionalExpr(); };
if (CommaAllowed)
return nonTerminalChainedExpr<tok::TokenKind::comma>(NonTerminal);
return nonTerminalChainedExpr(NonTerminal, [](Token) { return false; });
}
bool IntegralLiteralExpressionMatcher::expr() { return commaExpr(); }

View File

@ -39,21 +39,14 @@ public:
private:
bool advance();
bool consume(tok::TokenKind Kind);
bool nonTerminalChainedExpr(
bool (IntegralLiteralExpressionMatcher::*NonTerminal)(),
const std::function<bool(Token)> &IsKind);
template <tok::TokenKind Kind>
bool nonTerminalChainedExpr(
bool (IntegralLiteralExpressionMatcher::*NonTerminal)()) {
return nonTerminalChainedExpr(NonTerminal,
[](Token Tok) { return Tok.is(Kind); });
}
template <tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind... Ks>
bool nonTerminalChainedExpr(
bool (IntegralLiteralExpressionMatcher::*NonTerminal)()) {
return nonTerminalChainedExpr(
NonTerminal, [](Token Tok) { return Tok.isOneOf(K1, K2, Ks...); });
}
template <typename NonTerminalFunctor, typename IsKindFunctor>
bool nonTerminalChainedExpr(const NonTerminalFunctor &NonTerminal,
const IsKindFunctor &IsKind);
template <tok::TokenKind Kind, typename NonTerminalFunctor>
bool nonTerminalChainedExpr(const NonTerminalFunctor &NonTerminal);
template <tok::TokenKind K1, tok::TokenKind K2, tok::TokenKind... Ks,
typename NonTerminalFunctor>
bool nonTerminalChainedExpr(const NonTerminalFunctor &NonTerminal);
bool unaryOperator();
bool unaryExpr();