Skip to content

Commit b411d91

Browse files
author
wangmi
committed
[ASTMatcher] Fix redundant macro expansion checks in getExpansionLocOfMacro
When dealing with macro parameters, getExpansionLocOfMacro ecursively calls itself to check the expansion of macro arguments. This recursive logic redundantly checks previous macro expansions, leading to significant performance degradation when macros are heavily nested. This fix tracks already processed macros during recursion.
1 parent e9c561e commit b411d91

File tree

1 file changed

+42
-7
lines changed

1 file changed

+42
-7
lines changed

clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <cstddef>
3737
#include <optional>
3838
#include <string>
39+
#include <unordered_set>
3940
#include <utility>
4041
#include <vector>
4142

@@ -697,27 +698,61 @@ static bool isTokenAtLoc(const SourceManager &SM, const LangOptions &LangOpts,
697698
return !Invalid && Text == TokenText;
698699
}
699700

700-
std::optional<SourceLocation>
701-
getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
702-
const ASTContext &Context) {
701+
namespace {
702+
struct SourceLocationHash {
703+
std::size_t operator()(const SourceLocation &Loc) const {
704+
return Loc.getHashValue();
705+
}
706+
};
707+
708+
struct SourceLocationEqual {
709+
bool operator()(const SourceLocation &LHS, const SourceLocation &RHS) const {
710+
return LHS == RHS;
711+
}
712+
};
713+
714+
} // namespace
715+
716+
static std::optional<SourceLocation> getExpansionLocOfMacroRecursive(
717+
StringRef MacroName, SourceLocation Loc, const ASTContext &Context,
718+
std::unordered_set<SourceLocation, SourceLocationHash, SourceLocationEqual>
719+
&CheckedLocations) {
703720
auto &SM = Context.getSourceManager();
704721
const LangOptions &LangOpts = Context.getLangOpts();
705722
while (Loc.isMacroID()) {
723+
if (CheckedLocations.count(Loc)) {
724+
return std::nullopt;
725+
}
726+
CheckedLocations.insert(Loc);
706727
SrcMgr::ExpansionInfo Expansion =
707728
SM.getSLocEntry(SM.getFileID(Loc)).getExpansion();
708-
if (Expansion.isMacroArgExpansion())
729+
if (Expansion.isMacroArgExpansion()) {
709730
// Check macro argument for an expansion of the given macro. For example,
710731
// `F(G(3))`, where `MacroName` is `G`.
711-
if (std::optional<SourceLocation> ArgLoc = getExpansionLocOfMacro(
712-
MacroName, Expansion.getSpellingLoc(), Context))
732+
if (std::optional<SourceLocation> ArgLoc =
733+
getExpansionLocOfMacroRecursive(MacroName,
734+
Expansion.getSpellingLoc(),
735+
Context, CheckedLocations)) {
713736
return ArgLoc;
737+
}
738+
}
714739
Loc = Expansion.getExpansionLocStart();
715-
if (isTokenAtLoc(SM, LangOpts, MacroName, Loc))
740+
if (isTokenAtLoc(SM, LangOpts, MacroName, Loc)) {
716741
return Loc;
742+
}
717743
}
718744
return std::nullopt;
719745
}
720746

747+
std::optional<SourceLocation>
748+
getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
749+
const ASTContext &Context) {
750+
std::unordered_set<SourceLocation, SourceLocationHash, SourceLocationEqual>
751+
CheckedLocations;
752+
return getExpansionLocOfMacroRecursive(MacroName, Loc, Context,
753+
CheckedLocations);
754+
}
755+
721756
std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
722757
llvm::Regex::RegexFlags Flags,
723758
StringRef MatcherID) {

0 commit comments

Comments
 (0)