|
36 | 36 | #include <cstddef>
|
37 | 37 | #include <optional>
|
38 | 38 | #include <string>
|
| 39 | +#include <unordered_set> |
39 | 40 | #include <utility>
|
40 | 41 | #include <vector>
|
41 | 42 |
|
@@ -697,27 +698,61 @@ static bool isTokenAtLoc(const SourceManager &SM, const LangOptions &LangOpts,
|
697 | 698 | return !Invalid && Text == TokenText;
|
698 | 699 | }
|
699 | 700 |
|
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) { |
703 | 720 | auto &SM = Context.getSourceManager();
|
704 | 721 | const LangOptions &LangOpts = Context.getLangOpts();
|
705 | 722 | while (Loc.isMacroID()) {
|
| 723 | + if (CheckedLocations.count(Loc)) { |
| 724 | + return std::nullopt; |
| 725 | + } |
| 726 | + CheckedLocations.insert(Loc); |
706 | 727 | SrcMgr::ExpansionInfo Expansion =
|
707 | 728 | SM.getSLocEntry(SM.getFileID(Loc)).getExpansion();
|
708 |
| - if (Expansion.isMacroArgExpansion()) |
| 729 | + if (Expansion.isMacroArgExpansion()) { |
709 | 730 | // Check macro argument for an expansion of the given macro. For example,
|
710 | 731 | // `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)) { |
713 | 736 | return ArgLoc;
|
| 737 | + } |
| 738 | + } |
714 | 739 | Loc = Expansion.getExpansionLocStart();
|
715 |
| - if (isTokenAtLoc(SM, LangOpts, MacroName, Loc)) |
| 740 | + if (isTokenAtLoc(SM, LangOpts, MacroName, Loc)) { |
716 | 741 | return Loc;
|
| 742 | + } |
717 | 743 | }
|
718 | 744 | return std::nullopt;
|
719 | 745 | }
|
720 | 746 |
|
| 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 | + |
721 | 756 | std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
|
722 | 757 | llvm::Regex::RegexFlags Flags,
|
723 | 758 | StringRef MatcherID) {
|
|
0 commit comments